18#ifdef WITH_OPENGL_BACKEND
21#ifdef WITH_VULKAN_BACKEND
25#include <wayland-client-protocol.h>
27#ifdef WITH_OPENGL_BACKEND
28# ifdef WITH_GHOST_WAYLAND_DYNLOAD
31# include <wayland-egl.h>
36#ifdef WITH_GHOST_WAYLAND_LIBDECOR
37# ifdef WITH_GHOST_WAYLAND_DYNLOAD
42# ifdef WITH_VULKAN_BACKEND
48#include <fractional-scale-v1-client-protocol.h>
49#include <viewporter-client-protocol.h>
50#include <xdg-activation-v1-client-protocol.h>
51#include <xdg-decoration-unstable-v1-client-protocol.h>
52#include <xdg-shell-client-protocol.h>
74#ifdef USE_EVENT_BACKGROUND_THREAD
75# ifdef WITH_GHOST_WAYLAND_LIBDECOR
76# ifdef HAVE_MALLOC_USABLE_SIZE
77# define USE_LIBDECOR_CONFIG_COPY_WORKAROUND
87#ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
88# define USE_LIBDECOR_CONFIG_COPY_QUEUE
91#ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
92static libdecor_configuration *ghost_wl_libdecor_configuration_copy(
93 const libdecor_configuration *configuration);
94static void ghost_wl_libdecor_configuration_free(libdecor_configuration *configuration);
101#ifdef WITH_GHOST_WAYLAND_LIBDECOR
103# define use_libdecor GHOST_SystemWayland::use_libdecor_runtime()
106#ifdef WITH_GHOST_WAYLAND_LIBDECOR
107struct GWL_LibDecor_Window {
108 libdecor_frame *frame =
nullptr;
116 bool ack_configure =
false;
118 int size[2] = {0, 0};
119 libdecor_configuration *configuration =
nullptr;
121# ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
122 bool configuration_needs_free =
false;
125# ifdef USE_LIBDECOR_CONFIG_COPY_QUEUE
130 std::vector<libdecor_configuration *> configuration_queue;
136 bool initial_configure_seen =
false;
139static void gwl_libdecor_window_destroy(GWL_LibDecor_Window *decor)
141# ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
142 if (decor->pending.configuration_needs_free) {
143 ghost_wl_libdecor_configuration_free(decor->pending.configuration);
148# ifdef USE_LIBDECOR_CONFIG_COPY_QUEUE
149 for (libdecor_configuration *configuration : decor->pending.configuration_queue) {
150 ghost_wl_libdecor_configuration_free(configuration);
152 decor->pending.configuration_queue.clear();
161 xdg_surface *surface =
nullptr;
164 enum zxdg_toplevel_decoration_v1_mode mode = (
enum zxdg_toplevel_decoration_v1_mode)0;
188 xdg_toplevel_destroy(decor->
toplevel);
189 xdg_surface_destroy(decor->
surface);
199 GHOST_ASSERT(round_value > 0,
"Invalid rounding value!");
200 *value_p = (*value_p / round_value) * round_value;
205 GHOST_ASSERT(round_value > 0,
"Invalid rounding value!");
206 value_p[0] = (value_p[0] / round_value) * round_value;
207 value_p[1] = (value_p[1] / round_value) * round_value;
215 return value == ((value / round_value) * round_value);
231 wl_fixed_t scale = 0;
240 return value * scale_params.
scale;
248 return value / scale_params.
scale;
295 bool can_invert_color)
299 const size_t bitmap_size =
sizeof(
uint8_t) * ((size[0] + 7) / 8) * size[1];
303 memcpy(ccs.
bitmap, bitmap, bitmap_size);
306 ccs.
mask =
static_cast<uint8_t *
>(malloc(bitmap_size));
307 memcpy(ccs.
mask, mask, bitmap_size);
310 ccs.
size[0] = size[0];
311 ccs.
size[1] = size[1];
335#ifdef USE_EVENT_BACKGROUND_THREAD
358#ifdef USE_EVENT_BACKGROUND_THREAD
395# define PENDING_NUM (PENDING_WINDOW_CURSOR_SHAPE_REFRESH + 1)
433 wp_viewport *viewport =
nullptr;
449#ifdef WITH_OPENGL_BACKEND
450 wl_egl_window *egl_window =
nullptr;
452#ifdef WITH_VULKAN_BACKEND
469#ifdef WITH_GHOST_WAYLAND_LIBDECOR
470 GWL_LibDecor_Window *libdecor =
nullptr;
481#ifdef USE_EVENT_BACKGROUND_THREAD
504#ifdef USE_EVENT_BACKGROUND_THREAD
515#ifdef WITH_OPENGL_BACKEND
523#ifdef WITH_VULKAN_BACKEND
525 win->
backend.vulkan_window_info->size[0] = size[0];
526 win->
backend.vulkan_window_info->size[1] = size[1];
533#ifdef WITH_GHOST_WAYLAND_LIBDECOR
535 GWL_LibDecor_Window &decor = *win->libdecor;
542 xdg_toplevel_set_title(decor.
toplevel, title);
559#ifdef WITH_GHOST_WAYLAND_LIBDECOR
563static bool gwl_window_state_set_for_libdecor(libdecor_frame *frame,
570 switch (state_current) {
612 switch (state_current) {
614 xdg_toplevel_unset_maximized(toplevel);
618 xdg_toplevel_unset_fullscreen(toplevel);
627 xdg_toplevel_set_maximized(toplevel);
631 xdg_toplevel_set_minimized(toplevel);
635 xdg_toplevel_set_fullscreen(toplevel,
nullptr);
646#ifdef WITH_GHOST_WAYLAND_LIBDECOR
648 result = gwl_window_state_set_for_libdecor(win->libdecor->
frame,
state, state_current);
704 bool *r_surface_needs_commit,
705 bool *r_surface_needs_buffer_scale)
711 if (viewporter ==
nullptr) {
723 if (r_surface_needs_buffer_scale) {
724 *r_surface_needs_buffer_scale =
true;
730 if (r_surface_needs_commit) {
731 *r_surface_needs_commit =
true;
742 bool *r_surface_needs_commit,
743 bool *r_surface_needs_buffer_scale)
756 if (r_surface_needs_buffer_scale) {
757 *r_surface_needs_buffer_scale =
true;
763 if (r_surface_needs_commit) {
764 *r_surface_needs_commit =
true;
782 wp_viewport_set_destination(
805 if (
UNLIKELY(activation_manager ==
nullptr)) {
815 xdg_activation_token_v1_add_listener(
834 if (ghost_window_active) {
852 GWL_Window *win,
bool *r_surface_needs_commit,
bool *r_surface_needs_buffer_scale)
865 if (r_surface_needs_buffer_scale) {
866 *r_surface_needs_buffer_scale =
true;
871 if (r_surface_needs_commit) {
872 *r_surface_needs_commit =
true;
882 bool *r_surface_needs_commit,
883 bool *r_surface_needs_buffer_scale)
891 win, r_surface_needs_commit, r_surface_needs_buffer_scale);
895 bool *r_surface_needs_commit,
896 bool *r_surface_needs_resize_for_backend,
897 bool *r_surface_needs_buffer_scale)
910 win, r_surface_needs_commit, r_surface_needs_buffer_scale);
916 if (r_surface_needs_resize_for_backend) {
917 *r_surface_needs_resize_for_backend =
true;
931#ifdef USE_EVENT_BACKGROUND_THREAD
947 for (
size_t i = 0; i <
ARRAY_SIZE(actions); i++) {
980#ifdef USE_EVENT_BACKGROUND_THREAD
982 "Only from main thread!");
987 bool surface_needs_commit =
false;
988 bool surface_needs_resize_for_backend =
false;
989 bool surface_needs_buffer_scale =
false;
996 &surface_needs_commit,
997 &surface_needs_resize_for_backend,
998 &surface_needs_buffer_scale);
1004 win, &surface_needs_commit, &surface_needs_buffer_scale);
1009 surface_needs_buffer_scale =
true;
1013 if (surface_needs_resize_for_backend) {
1017 if (surface_needs_buffer_scale) {
1021#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1023 GWL_LibDecor_Window &decor = *win->libdecor;
1024 if (decor.pending.ack_configure) {
1025 surface_needs_commit =
true;
1027 decor.pending.ack_configure =
false;
1031# ifdef USE_LIBDECOR_CONFIG_COPY_QUEUE
1032 GHOST_ASSERT(decor.pending.size[0] != 0 && decor.pending.size[1] != 0,
"Invalid size");
1033 for (libdecor_configuration *configuration : decor.pending.configuration_queue) {
1035 ghost_wl_libdecor_configuration_free(configuration);
1037 decor.pending.configuration_queue.clear();
1044 decor.pending.size[0] = 0;
1045 decor.pending.size[1] = 0;
1047 decor.initial_configure_seen =
true;
1049# ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
1050 if (decor.pending.configuration_needs_free) {
1051 ghost_wl_libdecor_configuration_free(decor.pending.configuration);
1052 decor.pending.configuration_needs_free =
false;
1056 decor.pending.configuration =
nullptr;
1067 surface_needs_commit =
true;
1076 if (surface_needs_commit) {
1077#ifdef USE_EVENT_BACKGROUND_THREAD
1105 "GHOST internal active state does not match WAYLAND!");
1120#ifdef USE_EVENT_BACKGROUND_THREAD
1150 if (scale_fractional_a < scale_fractional_b) {
1153 if (scale_fractional_a > scale_fractional_b) {
1162 int *r_scale_fractional)
1167 output_max = reg_output;
1172 if (r_scale_fractional) {
1177 return output_max->
scale;
1179 if (r_scale_fractional) {
1182 return scale_default;
1187 int *r_scale_fractional)
1191 if (!output_uniform) {
1192 output_uniform = reg_output;
1196 output_uniform =
nullptr;
1201 if (output_uniform) {
1202 if (r_scale_fractional) {
1207 return output_uniform->
scale;
1209 if (r_scale_fractional) {
1212 return scale_default;
1223#ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
1225static libdecor_configuration *ghost_wl_libdecor_configuration_copy(
1226 const libdecor_configuration *configuration)
1228 size_t configuration_size = malloc_usable_size((
void *)configuration);
1229 libdecor_configuration *configuration_copy = (libdecor_configuration *)malloc(
1230 configuration_size);
1231 memcpy((
void *)configuration_copy, (
const void *)configuration, configuration_size);
1232 return configuration_copy;
1235static void ghost_wl_libdecor_configuration_free(libdecor_configuration *configuration)
1237 free((
void *)configuration);
1249#define LOG (&LOG_WL_XDG_TOPLEVEL)
1258 CLOG_INFO(
LOG, 2,
"configure (size=[%d, %d])", width, height);
1262#ifdef USE_EVENT_BACKGROUND_THREAD
1266 const int32_t size[2] = {width, height};
1267 for (
int i = 0; i < 2; i++) {
1281 enum xdg_toplevel_state *
state;
1284 case XDG_TOPLEVEL_STATE_MAXIMIZED:
1287 case XDG_TOPLEVEL_STATE_FULLSCREEN:
1290 case XDG_TOPLEVEL_STATE_ACTIVATED:
1314 CLOG_INFO(
LOG, 2,
"configure_bounds (size=[%d, %d])", width, height);
1352 xdg_activation_token_v1 *xdg_activation_token_v1,
1362 xdg_activation_v1_activate(activation_manager, token, win->
wl.
surface);
1385#define LOG (&LOG_WL_FRACTIONAL_SCALE)
1388 void *data, wp_fractional_scale_v1 * ,
uint preferred_scale)
1390#ifdef USE_EVENT_BACKGROUND_THREAD
1391 std::lock_guard lock_frame_guard{
static_cast<GWL_Window *
>(
data)->frame_pending_mutex};
1395 "preferred_scale (preferred_scale=%.6f)",
1418#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1420static CLG_LogRef LOG_WL_LIBDECOR_FRAME = {
"ghost.wl.handle.libdecor_frame"};
1421# define LOG (&LOG_WL_LIBDECOR_FRAME)
1423static void libdecor_frame_handle_configure(libdecor_frame *frame,
1424 libdecor_configuration *configuration,
1429# ifdef USE_EVENT_BACKGROUND_THREAD
1430 std::lock_guard lock_frame_guard{
static_cast<GWL_Window *
>(
data)->frame_pending_mutex};
1431 const bool is_main_thread = [
data] {
1441 int size_next[2] = {0, 0};
1450 "Fractional scale has no fractional component!");
1455 win->frame.buffer_scale;
1458 configuration, frame, &size_next[0], &size_next[1]))
1460 if (fractional_scale) {
1467 frame_pending.
size[0] = ((size_next[0] * scale) * fractional_scale) / scale_as_fractional;
1468 frame_pending.
size[1] = ((size_next[1] * scale) * fractional_scale) / scale_as_fractional;
1471 frame_pending.
size[0] = size_next[0] * scale;
1472 frame_pending.
size[1] = size_next[1] * scale;
1483 const GWL_LibDecor_Window &decor = *win->libdecor;
1484 size_next[0] = decor.pending.size[0];
1485 size_next[1] = decor.pending.size[1];
1491 enum libdecor_window_state window_state;
1493 frame_pending.
is_maximised = window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED;
1494 frame_pending.
is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN;
1495 frame_pending.
is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE;
1501 GWL_LibDecor_Window &decor = *win->libdecor;
1503# ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
1505 if (decor.pending.configuration_needs_free) {
1506 ghost_wl_libdecor_configuration_free(decor.pending.configuration);
1507 decor.pending.configuration_needs_free =
false;
1511 decor.pending.size[0] = size_next[0];
1512 decor.pending.size[1] = size_next[1];
1513 decor.pending.configuration = configuration;
1514 decor.pending.ack_configure =
true;
1516# ifdef USE_EVENT_BACKGROUND_THREAD
1517 if (!is_main_thread) {
1518# ifdef USE_LIBDECOR_CONFIG_COPY_WORKAROUND
1519 decor.pending.configuration = ghost_wl_libdecor_configuration_copy(configuration);
1520 decor.pending.configuration_needs_free =
true;
1524 decor.pending.configuration =
nullptr;
1529# ifdef USE_LIBDECOR_CONFIG_COPY_QUEUE
1530 if (!(size_next[0] && size_next[1])) {
1532 if (decor.pending.configuration_needs_free ==
false) {
1533 decor.pending.configuration = ghost_wl_libdecor_configuration_copy(
1534 decor.pending.configuration);
1535 decor.pending.configuration_needs_free =
true;
1538 decor.pending.configuration_queue.push_back(decor.pending.configuration);
1539 decor.pending.configuration =
nullptr;
1540 decor.pending.configuration_needs_free =
false;
1542 decor.pending.ack_configure =
false;
1550# ifdef USE_EVENT_BACKGROUND_THREAD
1551 if (!is_main_thread) {
1562static void libdecor_frame_handle_close(libdecor_frame * ,
void *data)
1571static void libdecor_frame_handle_commit(libdecor_frame * ,
void *data)
1584static libdecor_frame_interface libdecor_frame_iface = {
1585 libdecor_frame_handle_configure,
1586 libdecor_frame_handle_close,
1587 libdecor_frame_handle_commit,
1601#define LOG (&LOG_WL_XDG_TOPLEVEL_DECORATION)
1604 void *data, zxdg_toplevel_decoration_v1 * ,
const uint32_t mode)
1610 win->
xdg_decor->
mode = (zxdg_toplevel_decoration_v1_mode)mode;
1626#define LOG (&LOG_WL_XDG_SURFACE)
1629 xdg_surface *xdg_surface,
1640#ifdef USE_EVENT_BACKGROUND_THREAD
1641 std::lock_guard lock_frame_guard{
static_cast<GWL_Window *
>(
data)->frame_pending_mutex};
1646#ifdef USE_EVENT_BACKGROUND_THREAD
1648 const bool is_main_thread = system->
main_thread_id == std::this_thread::get_id();
1649 if (!is_main_thread) {
1674#define LOG (&LOG_WL_SURFACE)
1706#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
1707 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
1708static void surface_handle_preferred_buffer_scale(
void * ,
1713 CLOG_INFO(
LOG, 2,
"handle_preferred_buffer_scale (factor=%d)", factor);
1716static void surface_handle_preferred_buffer_transform(
void * ,
1721 CLOG_INFO(
LOG, 2,
"handle_preferred_buffer_transform (transform=%u)", transform);
1729#if defined(WL_SURFACE_PREFERRED_BUFFER_SCALE_SINCE_VERSION) && \
1730 defined(WL_SURFACE_PREFERRED_BUFFER_TRANSFORM_SINCE_VERSION)
1731 surface_handle_preferred_buffer_scale,
1732 surface_handle_preferred_buffer_transform,
1755 const bool is_dialog,
1756 const bool stereoVisual,
1757 const bool exclusive,
1758 const bool is_debug,
1763 is_debug_context_(is_debug),
1764 preferred_device_(preferred_device)
1766#ifdef USE_EVENT_BACKGROUND_THREAD
1767 std::lock_guard lock_server_guard{*system->
server_mutex};
1793 int scale_fractional_from_output;
1795 system_->
outputs_get(), 0, &scale_fractional_from_output);
1808 wp_fractional_scale_manager_v1 *fractional_scale_manager =
1810 if (fractional_scale_manager) {
1812 fractional_scale_manager, window_->
wl.
surface);
1813 wp_fractional_scale_v1_add_listener(
1821 const int32_t size_min[2] = {320, 240};
1825#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1827 window_->libdecor =
new GWL_LibDecor_Window;
1828 GWL_LibDecor_Window &decor = *window_->libdecor;
1832 system_->libdecor_context_get(), window_->
wl.
surface, &libdecor_frame_iface, window_);
1838 GWL_LibDecor_Window &decor_parent =
1853 xdg_toplevel_set_app_id(decor.
toplevel, xdg_app_id);
1858 if (parentWindow && is_dialog) {
1867#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1875 wl_surface_set_user_data(window_->
wl.
surface,
this);
1881#ifdef WITH_GHOST_WAYLAND_LIBDECOR
1891 decor.
toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
1893 zxdg_toplevel_decoration_v1_add_listener(
1896 ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
1911 int early_buffer_scale = 0;
1912 int early_fractional_scale = 0;
1914 if (
const int test_fractional_scale =
1917 scale_fractional_from_output) :
1921 early_fractional_scale = test_fractional_scale;
1926 early_fractional_scale = 0;
1929 else if (buffer_scale_from_output) {
1930 early_buffer_scale = buffer_scale_from_output;
1933 if (early_fractional_scale != 0) {
1948 bool surface_needs_commit_dummy =
false, surface_needs_buffer_scale_dummy =
false;
1950 window_, &surface_needs_commit_dummy, &surface_needs_buffer_scale_dummy);
1952 else if (early_buffer_scale != 0) {
1971 "An initialized scale is not expected");
1977 "Fractional scale was not properly initialized");
1984#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2004#ifdef WITH_OPENGL_BACKEND
2005 if (type == GHOST_kDrawingContextTypeOpenGL) {
2010#ifdef WITH_VULKAN_BACKEND
2011 if (type == GHOST_kDrawingContextTypeVulkan) {
2022 GHOST_PRINT(
"Failed to create drawing context" << std::endl);
2033#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2038 GWL_LibDecor_Window &decor = *window_->libdecor;
2046# ifdef WITH_VULKAN_BACKEND
2049 wl_buffer *dummy_buffer =
nullptr;
2052 const int format_size = 4;
2053 const int buffer_size = (window_->
frame.
size[0] * window_->
frame.
size[1]) * format_size;
2054 const int fd = memfd_create_sealed_for_vulkan_hack(
"ghost-wl-dummy-buffer");
2055 ftruncate(fd, buffer_size);
2057 wl_shm_pool *pool = wl_shm_create_pool(shm, fd, buffer_size);
2058 dummy_buffer = wl_shm_pool_create_buffer(pool,
2064 wl_shm_pool_destroy(pool);
2066 wl_surface_attach(window_->
wl.
surface, dummy_buffer, 0, 0);
2079# ifdef WITH_VULKAN_BACKEND
2081 wl_surface_attach(window_->
wl.
surface,
nullptr, 0, 0);
2083 wl_buffer_destroy(dummy_buffer);
2126#ifdef USE_EVENT_BACKGROUND_THREAD
2127 std::lock_guard lock_server_guard{*system_->
server_mutex};
2132#ifdef WITH_OPENGL_BACKEND
2137#ifdef WITH_VULKAN_BACKEND
2139 delete window_->
backend.vulkan_window_info;
2158#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2160 gwl_libdecor_window_destroy(window_->libdecor);
2172 wl_surface_destroy(window_->
wl.
surface);
2184#ifdef USE_EVENT_BACKGROUND_THREAD
2199#ifdef USE_EVENT_BACKGROUND_THREAD
2200 std::lock_guard lock_server_guard{*system_->
server_mutex};
2218 this->scale_params_get()))
2227#ifdef USE_EVENT_BACKGROUND_THREAD
2228 std::lock_guard lock_server_guard{*system_->
server_mutex};
2263#ifdef USE_EVENT_BACKGROUND_THREAD
2264 std::lock_guard lock_server_guard{*system_->
server_mutex};
2270 uint8_t *bitmap,
uint8_t *mask,
int sizex,
int sizey,
int hotX,
int hotY,
bool canInvertColor)
2272#ifdef USE_EVENT_BACKGROUND_THREAD
2273 std::lock_guard lock_server_guard{*system_->
server_mutex};
2278 const int32_t size[2] = {sizex, sizey};
2279 const int32_t hot_spot[2] = {hotX, hotY};
2308#ifdef USE_EVENT_BACKGROUND_THREAD
2309 std::lock_guard lock_server_guard{*system_->
server_mutex};
2321#ifdef USE_EVENT_BACKGROUND_THREAD
2322 std::lock_guard lock_server_guard{*system_->
server_mutex};
2330 return window_->
title.empty() ?
"untitled" : window_->
title;
2356#ifdef USE_EVENT_BACKGROUND_THREAD
2357 std::lock_guard lock_server_guard{*system_->
server_mutex};
2363 frame_pending.
size[0] = width;
2364 frame_pending.
size[1] = height;
2404#ifdef USE_EVENT_BACKGROUND_THREAD
2405 std::lock_guard lock_server_guard{*system_->
server_mutex};
2417#ifdef USE_EVENT_BACKGROUND_THREAD
2418 std::lock_guard lock_server_guard{*system_->
server_mutex};
2425#ifdef USE_EVENT_BACKGROUND_THREAD
2426 std::lock_guard lock_server_guard{*system_->
server_mutex};
2451#ifdef USE_EVENT_BACKGROUND_THREAD
2452 std::lock_guard lock_server_guard{*system_->
server_mutex};
2455#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2470#ifdef USE_EVENT_BACKGROUND_THREAD
2471 std::lock_guard lock_server_guard{*system_->
server_mutex};
2474#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2499#ifdef WITH_VULKAN_BACKEND
2500 case GHOST_kDrawingContextTypeVulkan: {
2502 GHOST_kVulkanPlatformWayland,
2507 window_->
backend.vulkan_window_info,
2512 if (context->initializeDrawingContext()) {
2520#ifdef WITH_OPENGL_BACKEND
2521 case GHOST_kDrawingContextTypeOpenGL: {
2522 for (
int minor = 6; minor >= 3; --minor) {
2526 EGLNativeWindowType(window_->
backend.egl_window),
2528 EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
2532 (is_debug_context_ ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0),
2536 if (context->initializeDrawingContext()) {
2551#ifdef WITH_INPUT_IME
2555 system_->
ime_begin(
this, x, y,
w, h, completed);
2558void GHOST_WindowWayland::endIME()
2586 return *scale_params;
2631#ifdef USE_EVENT_BACKGROUND_THREAD
2632 const bool is_main_thread = system_->
main_thread_id == std::this_thread::get_id();
2646#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2659#ifdef USE_EVENT_BACKGROUND_THREAD
2661 const bool is_main_thread = system_->
main_thread_id == std::this_thread::get_id();
2672#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2707#ifdef USE_EVENT_BACKGROUND_THREAD
2718#ifdef USE_EVENT_BACKGROUND_THREAD
2730#ifdef USE_EVENT_BACKGROUND_THREAD
2736 int fractional_scale_next = -1;
2737 int fractional_scale_from_output = 0;
2745#ifdef USE_EVENT_BACKGROUND_THREAD
2758 if (fractional_scale_next == -1) {
2759 fractional_scale_next = fractional_scale_from_output;
2763 bool changed =
false;
2780 bool do_frame_resize =
false;
2781 bool do_frame_update =
false;
2793#ifdef WITH_GHOST_WAYLAND_LIBDECOR
2802 int size_next[2] = {0, 0};
2803 int size_orig[2] = {0, 0};
2808 size_orig[i] = value;
2809 if (is_fractional_prev || is_fractional_next) {
2811 double(fractional_scale_next));
2814 size_next[i] = value / scale_prev;
2821 if (size_orig[0] != size_next[0] || size_orig[1] != size_next[1]) {
2822 GWL_LibDecor_Window &decor = *window_->libdecor;
2830 do_frame_resize =
false;
2831 do_frame_update =
true;
2835 if ((fractional_scale_prev != fractional_scale_next) ||
2838 do_frame_resize =
true;
2842 if (do_frame_resize) {
2852 if (is_fractional_prev || is_fractional_next) {
2853 window_->
frame_pending.
size[i] = lroundf((value *
double(fractional_scale_next)) /
2854 double(fractional_scale_prev));
2863 do_frame_update =
true;
2866 if (do_frame_update) {
2876 std::vector<GWL_Output *> &outputs = window_->
outputs;
2877 auto it = std::find(outputs.begin(), outputs.end(), output);
2878 if (it != outputs.end()) {
2881 outputs.push_back(output);
2887 std::vector<GWL_Output *> &outputs = window_->
outputs;
2888 auto it = std::find(outputs.begin(), outputs.end(), output);
2889 if (it == outputs.end()) {
2896#ifdef USE_EVENT_BACKGROUND_THREAD
2904 "Run from main thread!");
void BLI_kdtree_nd_ free(KDTree *tree)
#define CLOG_INFO(clg_ref, level,...)
#define GHOST_OPENGL_EGL_CONTEXT_FLAGS
#define GHOST_OPENGL_EGL_RESET_NOTIFICATION_STRATEGY
#define GHOST_ASSERT(x, info)
GWL_Output * ghost_wl_output_user_data(wl_output *wl_output)
void ghost_wl_surface_tag(wl_surface *wl_surface)
bool ghost_wl_display_report_error_if_set(wl_display *display)
bool ghost_wl_output_own(const wl_output *wl_output)
#define FRACTIONAL_DENOMINATOR
@ GHOST_kWindowStateMinimized
@ GHOST_kWindowStateMaximized
@ GHOST_kWindowStateNormal
@ GHOST_kWindowStateFullScreen
@ GHOST_kStandardCursorCustom
@ GHOST_kStandardCursorDefault
@ GHOST_kEventWindowClose
@ GHOST_kEventWindowActivate
@ GHOST_kEventWindowUpdateDecor
@ GHOST_kEventWindowDeactivate
@ GHOST_kEventWindowDPIHintChanged
GHOST_TDrawingContextType
@ GHOST_kDrawingContextTypeNone
#define WL_ARRAY_FOR_EACH(pos, array)
static void wp_fractional_scale_handle_preferred_scale(void *data, wp_fractional_scale_v1 *, uint preferred_scale)
wl_fixed_t gwl_window_scale_wl_fixed_to(const GWL_WindowScaleParams &scale_params, wl_fixed_t value)
eGWL_PendingWindowActions
@ PENDING_WINDOW_FRAME_CONFIGURE
@ PENDING_OUTPUT_SCALE_UPDATE_DEFERRED
@ PENDING_WINDOW_CURSOR_SHAPE_REFRESH
@ PENDING_WINDOW_SURFACE_COMMIT
@ PENDING_OUTPUT_SCALE_UPDATE
wl_fixed_t gwl_window_scale_wl_fixed_from(const GWL_WindowScaleParams &scale_params, wl_fixed_t value)
static void gwl_round_int2_by(int value_p[2], const int round_value)
static int gwl_window_fractional_from_viewport(const GWL_WindowFrame &frame, int value)
static void surface_handle_leave(void *data, wl_surface *, wl_output *wl_output)
static void gwl_window_frame_pending_fractional_scale_set_notest(GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_buffer_scale)
static CLG_LogRef LOG_WL_XDG_TOPLEVEL_DECORATION
static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
int gwl_window_scale_int_to(const GWL_WindowScaleParams &scale_params, int value)
static bool gwl_window_viewport_unset(GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_buffer_scale)
static void gwl_window_cursor_custom_free(GWL_WindowCursorCustomShape &ccs)
static GHOST_TWindowState gwl_window_state_get(const GWL_Window *win)
static void xdg_toplevel_handle_configure(void *data, xdg_toplevel *, const int32_t width, const int32_t height, wl_array *states)
static CLG_LogRef LOG_WL_XDG_SURFACE
static void gwl_window_frame_pending_fractional_scale_set(GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_buffer_scale)
static void xdg_surface_handle_configure(void *data, xdg_surface *xdg_surface, const uint32_t serial)
static void gwl_window_frame_update_from_pending(GWL_Window *win)
static const wp_fractional_scale_v1_listener wp_fractional_scale_listener
static CLG_LogRef LOG_WL_SURFACE
static const xdg_toplevel_listener xdg_toplevel_listener
static const zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_v1_listener
static GHOST_TSuccess gwl_window_cursor_custom_load(const GWL_WindowCursorCustomShape &ccs, GHOST_SystemWayland *system)
static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state)
static GHOST_TSuccess gwl_window_cursor_shape_refresh(GHOST_TStandardCursor shape, const GWL_WindowCursorCustomShape &ccs, GHOST_SystemWayland *system)
static void gwl_window_frame_pending_size_set(GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_resize_for_backend, bool *r_surface_needs_buffer_scale)
static bool gwl_window_state_set_for_xdg(xdg_toplevel *toplevel, const GHOST_TWindowState state, const GHOST_TWindowState state_current)
static int outputs_uniform_scale_or_default(const std::vector< GWL_Output * > &outputs, const int32_t scale_default, int *r_scale_fractional)
static void gwl_xdg_decor_window_destroy(GWL_XDG_Decor_Window *decor)
int gwl_window_scale_int_from(const GWL_WindowScaleParams &scale_params, int value)
static CLG_LogRef LOG_WL_FRACTIONAL_SCALE
static void xdg_toplevel_handle_configure_bounds(void *data, xdg_toplevel *, int32_t width, int32_t height)
static int gwl_window_fractional_to_viewport(const GWL_WindowFrame &frame, int value)
static void gwl_window_activate(GWL_Window *win)
static void gwl_window_resize_for_backend(GWL_Window *win, const int32_t size[2])
static int outputs_max_scale_or_default(const std::vector< GWL_Output * > &outputs, const int32_t scale_default, int *r_scale_fractional)
static constexpr size_t base_dpi
static void gwl_window_cursor_custom_clear(GWL_WindowCursorCustomShape &ccs)
static void gwl_window_pending_actions_handle(GWL_Window *win)
static const xdg_surface_listener xdg_surface_listener
static int gwl_window_fractional_to_viewport_round(const GWL_WindowFrame &frame, int value)
static int output_scale_cmp(const GWL_Output *output_a, const GWL_Output *output_b)
static void gwl_round_int_by(int *value_p, const int round_value)
static CLG_LogRef LOG_WL_XDG_TOPLEVEL
static void gwl_window_cursor_custom_store(GWL_WindowCursorCustomShape &ccs, const uint8_t *bitmap, const uint8_t *mask, const int32_t size[2], const int32_t hot_spot[2], bool can_invert_color)
static bool gwl_window_viewport_size_update(GWL_Window *win)
static void xdg_activation_handle_done(void *data, xdg_activation_token_v1 *xdg_activation_token_v1, const char *token)
static const xdg_activation_token_v1_listener xdg_activation_listener
static void xdg_toplevel_handle_wm_capabilities(void *, xdg_toplevel *, wl_array *)
static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
static void surface_handle_enter(void *data, wl_surface *, wl_output *wl_output)
static bool gwl_round_int_test(int value, const int round_value)
static bool gwl_window_viewport_set(GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_buffer_scale)
static void gwl_window_title_set(GWL_Window *win, const char *title)
static int gwl_window_fractional_from_viewport_round(const GWL_WindowFrame &frame, int value)
static void xdg_toplevel_decoration_handle_configure(void *data, zxdg_toplevel_decoration_v1 *, const uint32_t mode)
static const xdg_activation_token_v1_listener * xdg_activation_listener_get()
static const wl_surface_listener wl_surface_listener
static void xdg_toplevel_handle_close(void *data, xdg_toplevel *)
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
static const char * xdg_app_id_get()
GHOST_TSuccess pushEvent_maybe_pending(const GHOST_IEvent *event)
bool window_surface_unref(const wl_surface *wl_surface)
uint64_t getMilliSeconds() const override
bool window_cursor_grab_set(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, int32_t init_grab_xy[2], const GHOST_Rect *wrap_bounds, GHOST_TAxisFlag wrap_axis, wl_surface *wl_surface, const struct GWL_WindowScaleParams &scale_params)
GHOST_TSuccess cursor_visibility_set(bool visible)
std::thread::id main_thread_id
struct wl_display * wl_display_get()
GHOST_TSuccess cursor_shape_check(GHOST_TStandardCursor cursorShape)
bool cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
struct xdg_wm_base * xdg_decor_shell_get()
struct wl_compositor * wl_compositor_get()
struct wp_fractional_scale_manager_v1 * wp_fractional_scale_manager_get()
struct wl_shm * wl_shm_get() const
GHOST_TSuccess cursor_shape_set(GHOST_TStandardCursor shape)
const std::vector< GWL_Output * > & outputs_get() const
struct wp_viewporter * wp_viewporter_get()
struct zxdg_decoration_manager_v1 * xdg_decor_manager_get()
struct wl_seat * wl_seat_active_get_with_input_serial(uint32_t &serial)
GHOST_TSuccess cursor_bitmap_get(GHOST_CursorBitmapRef *bitmap)
GHOST_TSuccess cursor_shape_custom_set(const uint8_t *bitmap, const uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
void ime_begin(const GHOST_WindowWayland *win, int32_t x, int32_t y, int32_t w, int32_t h, bool completed) const
std::atomic< bool > has_pending_actions_for_window
std::mutex * server_mutex
struct xdg_activation_v1 * xdg_activation_manager_get()
void ime_end(const GHOST_WindowWayland *win) const
GHOST_WindowManager * getWindowManager() const
GHOST_TSuccess pushEvent(const GHOST_IEvent *event)
GHOST_IWindow * getActiveWindow() const
GHOST_TSuccess setActiveWindow(GHOST_IWindow *window)
void setWindowInactive(const GHOST_IWindow *window)
GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape) override
const struct GWL_WindowScaleParams & scale_params_get() const
GHOST_TSuccess setClientSize(uint32_t width, uint32_t height) override
bool outputs_leave(GWL_Output *output)
GHOST_TSuccess setClientWidth(uint32_t width) override
wl_fixed_t wl_fixed_to_window(wl_fixed_t value) const
GHOST_TSuccess setOrder(GHOST_TWindowOrder order) override
GHOST_TSuccess swapBuffers() override
GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode) override
GHOST_TSuccess notify_size()
void outputs_changed_update_scale_tag()
GHOST_TSuccess setState(GHOST_TWindowState state) override
GHOST_TSuccess setWindowCursorVisibility(bool visible) override
GHOST_TWindowState getState() const override
bool getCursorGrabUseSoftwareDisplay() override
GHOST_TSuccess beginFullScreen() const override
bool isDialog() const override
struct wl_surface * wl_surface_get() const
GHOST_TSuccess notify_decor_redraw()
bool getValid() const override
wl_fixed_t wl_fixed_from_window(wl_fixed_t value) const
std::string getTitle() const override
GHOST_TSuccess deactivate()
bool outputs_changed_update_scale()
void getClientBounds(GHOST_Rect &bounds) const override
GHOST_TSuccess activate()
uint16_t getDPIHint() override
void clientToScreen(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
GHOST_TSuccess endFullScreen() const override
GHOST_TSuccess setClientHeight(uint32_t height) override
GHOST_TSuccess cursor_shape_refresh()
void screenToClient(int32_t inX, int32_t inY, int32_t &outX, int32_t &outY) const override
bool outputs_enter(GWL_Output *output)
const void pending_actions_handle()
~GHOST_WindowWayland() override
GHOST_TSuccess invalidate() override
GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape) override
void setTitle(const char *title) override
GHOST_WindowWayland(GHOST_SystemWayland *system, const char *title, int32_t left, int32_t top, uint32_t width, uint32_t height, GHOST_TWindowState state, const GHOST_IWindow *parentWindow, GHOST_TDrawingContextType type, const bool is_dialog, const bool stereoVisual, const bool exclusive, const bool is_debug, const GHOST_GPUDevice &preferred_device)
GHOST_TSuccess setWindowCustomCursorShape(uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor) override
void getWindowBounds(GHOST_Rect &bounds) const override
GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap) override
const std::vector< GWL_Output * > & outputs_get()
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) const override
GHOST_TGrabCursorMode m_cursorGrab
int32_t m_cursorGrabInitPos[2]
GHOST_TStandardCursor getCursorShape() const override
GHOST_TSuccess setDrawingContextType(GHOST_TDrawingContextType type) override
GHOST_TStandardCursor m_cursorShape
GHOST_TSuccess setSwapInterval(int interval) override
GHOST_TSuccess releaseNativeHandles()
GHOST_TAxisFlag m_cursorGrabAxis
virtual GHOST_TSuccess swapBuffers() override
virtual bool getValid() const override
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static blender::bke::bNodeSocketTemplate outputs[]
bool has_scale_fractional
int fractional_scale_preferred
struct GWL_Window::@1508 wp
GHOST_SystemWayland * ghost_system
std::atomic< bool > pending_actions[PENDING_NUM]
wp_fractional_scale_v1 * fractional_scale_handle
GWL_XDG_Decor_Window * xdg_decor
struct GWL_Window::@1510 backend
GWL_WindowScaleParams scale_params
xdg_activation_token_v1 * activation_token
std::mutex frame_pending_mutex
GWL_WindowFrame frame_pending
struct GWL_Window::@1507 wl
GHOST_WindowWayland * ghost_window
struct GWL_Window::@1509 xdg
GWL_WindowCursorCustomShape cursor_custom_shape
std::vector< GWL_Output * > outputs
GHOST_TDrawingContextType ghost_context_type
zxdg_toplevel_decoration_v1 * toplevel_decor
uint32_t ack_configure_serial
struct GWL_XDG_Decor_Window::@1506 pending
enum zxdg_toplevel_decoration_v1_mode mode
bool initial_configure_seen
#define wl_display_dispatch(...)
#define wl_display_flush(...)
#define wl_display_roundtrip(...)
#define wl_egl_window_resize(...)
#define wl_egl_window_create(...)
#define wl_egl_window_destroy(...)
#define libdecor_frame_set_fullscreen(...)
#define libdecor_frame_map(...)
#define libdecor_state_new(...)
#define libdecor_frame_unset_fullscreen(...)
#define libdecor_configuration_get_content_size(...)
#define libdecor_state_free(...)
#define libdecor_configuration_get_window_state(...)
#define libdecor_frame_unref(...)
#define libdecor_frame_unset_maximized(...)
#define libdecor_frame_get_xdg_toplevel(...)
#define libdecor_frame_set_app_id(...)
#define libdecor_frame_set_min_content_size(...)
#define libdecor_frame_set_parent(...)
#define libdecor_frame_set_title(...)
#define libdecor_frame_set_minimized(...)
#define libdecor_frame_commit(...)
#define libdecor_decorate(...)
#define libdecor_frame_set_maximized(...)