This MR introduces support for basic window management in the Wayland driver.
A summary of the commits (but see commit messages for more info):
1. Replace double locking during `wayland_surface` destruction (to protect `xdg_surface` user data) with a simpler mechanism, since we established in the last MR that we don't need to worry about HWND recycling. 2. Support compositor initiated window closing. 3. Respect compositor size hints. 4. Handling/syncing of maximized state, requested by either the compositor or app/Wine. 5. Interactive window moving (but only in the compositor virtual space, see notes below!) 6. Interactive window resizing.
A few notes:
1. At the moment, the driver doesn't change the position of windows in the Windows virtual screen space, since Wayland doesn't provide any relevant position information. This can lead to situations where parts of the window become apparently inaccessible to mouse input, because although those parts are visible from a Wayland perspective they are outside the Windows virtual screen. In future MRs I will provide mitigations/workarounds for this fundamental incompatibility between Win32 and Wayland.
2. To support interactive window moving/resizing, both the `xdg_toplevel` and the `wl_seat` need to remain valid during our request, so we introduce a double lock to ensure their concurrent validity.
Thanks!
-- v2: winewayland.drv: Fix removal of wl_seat globals.
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Ignoring the possibility of HWND recycling allows us to use a simpler scheme to ensure valid access to the wayland_surface associated with an xdg_surface during event handling. The scheme involves setting HWND as the xdg_surface user data and using that to get to the wayland_surface.
The prerequisite for this code to be correct is that the wayland surface destruction for a HWND must be performed under the wayland_win_data mutex. --- dlls/winewayland.drv/wayland_surface.c | 25 +++---------------------- dlls/winewayland.drv/waylanddrv.h | 1 + dlls/winewayland.drv/window.c | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 22 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 7e77c9ba55f..e8ab52da543 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -33,38 +33,22 @@
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
-/* Protects access to the user data of xdg_surface */ -static pthread_mutex_t xdg_data_mutex = PTHREAD_MUTEX_INITIALIZER; - -static struct wayland_surface *wayland_surface_lock_xdg(struct xdg_surface *xdg_surface) -{ - struct wayland_surface *surface; - - pthread_mutex_lock(&xdg_data_mutex); - surface = xdg_surface_get_user_data(xdg_surface); - if (surface) pthread_mutex_lock(&surface->mutex); - pthread_mutex_unlock(&xdg_data_mutex); - - return surface; -} - static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { struct wayland_surface *surface; BOOL initial_configure = FALSE; - HWND hwnd; + HWND hwnd = data;
TRACE("serial=%u\n", serial);
- if (!(surface = wayland_surface_lock_xdg(xdg_surface))) return; + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
/* Handle this event only if wayland_surface is still associated with * the target xdg_surface. */ if (surface->xdg_surface == xdg_surface) { initial_configure = surface->current_serial == 0; - hwnd = surface->hwnd; surface->current_serial = serial; xdg_surface_ack_configure(xdg_surface, serial); } @@ -132,7 +116,6 @@ void wayland_surface_destroy(struct wayland_surface *surface) } pthread_mutex_unlock(&process_wayland.pointer.mutex);
- pthread_mutex_lock(&xdg_data_mutex); pthread_mutex_lock(&surface->mutex);
if (surface->xdg_toplevel) @@ -143,7 +126,6 @@ void wayland_surface_destroy(struct wayland_surface *surface)
if (surface->xdg_surface) { - xdg_surface_set_user_data(surface->xdg_surface, NULL); xdg_surface_destroy(surface->xdg_surface); surface->xdg_surface = NULL; } @@ -155,7 +137,6 @@ void wayland_surface_destroy(struct wayland_surface *surface) }
pthread_mutex_unlock(&surface->mutex); - pthread_mutex_unlock(&xdg_data_mutex);
if (surface->latest_window_buffer) wayland_shm_buffer_unref(surface->latest_window_buffer); @@ -179,7 +160,7 @@ void wayland_surface_make_toplevel(struct wayland_surface *surface) surface->xdg_surface = xdg_wm_base_get_xdg_surface(process_wayland.xdg_wm_base, surface->wl_surface); if (!surface->xdg_surface) goto err; - xdg_surface_add_listener(surface->xdg_surface, &xdg_surface_listener, surface); + xdg_surface_add_listener(surface->xdg_surface, &xdg_surface_listener, surface->hwnd);
surface->xdg_toplevel = xdg_surface_get_toplevel(surface->xdg_surface); if (!surface->xdg_toplevel) goto err; diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index f4292e0ae28..6e0b5c6fb10 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -166,6 +166,7 @@ void wayland_surface_clear_role(struct wayland_surface *surface) DECLSPEC_HIDDEN void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region) DECLSPEC_HIDDEN; +struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN;
/********************************************************************** * Wayland SHM buffer diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index efe72baf92e..958bc5dbe68 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -338,3 +338,20 @@ void wayland_window_flush(HWND hwnd)
wayland_win_data_release(data); } + +/********************************************************************** + * wayland_surface_lock_hwnd + */ +struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) +{ + struct wayland_win_data *data = wayland_win_data_get(hwnd); + struct wayland_surface *surface; + + if (!data) return NULL; + + if ((surface = data->wayland_surface)) pthread_mutex_lock(&surface->mutex); + + wayland_win_data_release(data); + + return surface; +}
From: Alexandros Frantzis alexandros.frantzis@collabora.com
--- dlls/winewayland.drv/wayland_surface.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index e8ab52da543..832a1081234 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -65,6 +65,24 @@ static const struct xdg_surface_listener xdg_surface_listener = xdg_surface_handle_configure };
+static void xdg_toplevel_handle_configure(void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, int32_t height, + struct wl_array *states) +{ +} + +static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) +{ + NtUserPostMessage((HWND)data, WM_SYSCOMMAND, SC_CLOSE, 0); +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = +{ + xdg_toplevel_handle_configure, + xdg_toplevel_handle_close +}; + /********************************************************************** * wayland_surface_create * @@ -164,6 +182,7 @@ void wayland_surface_make_toplevel(struct wayland_surface *surface)
surface->xdg_toplevel = xdg_surface_get_toplevel(surface->xdg_surface); if (!surface->xdg_toplevel) goto err; + xdg_toplevel_add_listener(surface->xdg_toplevel, &xdg_toplevel_listener, surface->hwnd);
wl_surface_commit(surface->wl_surface); wl_display_flush(process_wayland.wl_display);
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Use the size hint provided by the compositor to resize the window associated with a Wayland toplevel surface.
A surface config moves through the following stages (each stage may hold a different event):
1. Pending: In the process of being populated from separate Wayland events.
2. Requested: A fully formed config which hasn't been handled yet. A new finalized Pending event will always be promoted to a Requested event (so we will skip previous events if new ones arrive quickly enough).
3. Processing: A config that is being processed. When processing is done, we mark it with `wayland_surface_config.processed = TRUE`.
4. Current: The config has been acknowledged, i.e., we are promising to respect any implied content constraints. --- dlls/winewayland.drv/wayland_surface.c | 67 ++++++++++++++++++++++++-- dlls/winewayland.drv/waylanddrv.h | 13 ++++- dlls/winewayland.drv/window.c | 54 +++++++++++++++++++++ dlls/winewayland.drv/window_surface.c | 2 +- 4 files changed, 129 insertions(+), 7 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 832a1081234..0004e51fe0f 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -48,9 +48,15 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur * the target xdg_surface. */ if (surface->xdg_surface == xdg_surface) { - initial_configure = surface->current_serial == 0; - surface->current_serial = serial; - xdg_surface_ack_configure(xdg_surface, serial); + /* If we have a previously requested config, we have already sent a + * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case, + * avoid sending another message to reduce message queue traffic. */ + BOOL should_post = surface->requested.serial == 0; + initial_configure = surface->current.serial == 0; + surface->pending.serial = serial; + surface->requested = surface->pending; + memset(&surface->pending, 0, sizeof(surface->pending)); + if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0); }
pthread_mutex_unlock(&surface->mutex); @@ -70,6 +76,20 @@ static void xdg_toplevel_handle_configure(void *data, int32_t width, int32_t height, struct wl_array *states) { + struct wayland_surface *surface; + HWND hwnd = data; + + TRACE("hwnd=%p %dx%d\n", hwnd, width, height); + + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + + if (surface->xdg_toplevel == xdg_toplevel) + { + surface->pending.width = width; + surface->pending.height = height; + } + + pthread_mutex_unlock(&surface->mutex); }
static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) @@ -217,7 +237,10 @@ void wayland_surface_clear_role(struct wayland_surface *surface) surface->xdg_surface = NULL; }
- surface->current_serial = 0; + memset(&surface->pending, 0, sizeof(surface->pending)); + memset(&surface->requested, 0, sizeof(surface->requested)); + memset(&surface->processing, 0, sizeof(surface->processing)); + memset(&surface->current, 0, sizeof(surface->current));
/* Ensure no buffer is attached, otherwise future role assignments may fail. */ wl_surface_attach(surface->wl_surface, NULL, 0, 0); @@ -268,6 +291,42 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, } }
+/********************************************************************** + * wayland_surface_reconfigure + * + * Reconfigures the wayland surface as needed to match the latest requested + * state. + */ +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) +{ + if (!surface->xdg_toplevel) return TRUE; + + TRACE("hwnd=%p\n", surface->hwnd); + + /* Acknowledge any processed config. */ + if (surface->processing.serial && surface->processing.processed) + { + surface->current = surface->processing; + memset(&surface->processing, 0, sizeof(surface->processing)); + xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); + } + /* If this is the initial configure, and we have a requested config, + * use that, in order to draw windows that don't go through the message + * loop (e.g., some splash screens). */ + else if (!surface->current.serial && surface->requested.serial) + { + surface->current = surface->requested; + memset(&surface->requested, 0, sizeof(surface->requested)); + xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); + } + else if (!surface->current.serial) + { + return FALSE; + } + + return TRUE; +} + /********************************************************************** * wayland_shm_buffer_ref * diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 6e0b5c6fb10..5246d3ba9cb 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -53,7 +53,8 @@ extern struct wayland process_wayland DECLSPEC_HIDDEN;
enum wayland_window_message { - WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000 + WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000, + WM_WAYLAND_CONFIGURE = 0x80001001 };
struct wayland_cursor @@ -117,6 +118,13 @@ struct wayland_output struct wayland_output_state current; };
+struct wayland_surface_config +{ + int32_t width, height; + uint32_t serial; + BOOL processed; +}; + struct wayland_surface { HWND hwnd; @@ -124,7 +132,7 @@ struct wayland_surface struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; pthread_mutex_t mutex; - uint32_t current_serial; + struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; };
@@ -167,6 +175,7 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region) DECLSPEC_HIDDEN; struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN; +BOOL wayland_surface_reconfigure(struct wayland_surface *surface) DECLSPEC_HIDDEN;
/********************************************************************** * Wayland SHM buffer diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 958bc5dbe68..86f4e30b136 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -192,6 +192,20 @@ out: data->wayland_surface = surface; }
+static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) +{ + struct wayland_surface *surface = data->wayland_surface; + + pthread_mutex_lock(&surface->mutex); + + if (!surface->xdg_toplevel) goto out; + + if (surface->processing.serial) surface->processing.processed = TRUE; + +out: + pthread_mutex_unlock(&surface->mutex); +} + /*********************************************************************** * WAYLAND_DestroyWindow */ @@ -276,6 +290,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, data->window_surface = surface;
wayland_win_data_update_wayland_surface(data); + if (data->wayland_surface) wayland_win_data_update_wayland_state(data);
wayland_win_data_release(data); } @@ -290,6 +305,42 @@ static void wayland_resize_desktop(void) SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); }
+static void wayland_configure_window(HWND hwnd) +{ + struct wayland_surface *surface; + INT width, height; + UINT flags; + + if (!(surface = wayland_surface_lock_hwnd(hwnd))) return; + + if (!surface->xdg_toplevel) + { + TRACE("missing xdg_toplevel, returning"); + pthread_mutex_unlock(&surface->mutex); + return; + } + + if (!surface->requested.serial) + { + TRACE("requested configure event already handled, returning\n"); + pthread_mutex_unlock(&surface->mutex); + return; + } + + surface->processing = surface->requested; + memset(&surface->requested, 0, sizeof(surface->requested)); + + width = surface->processing.width; + height = surface->processing.height; + + pthread_mutex_unlock(&surface->mutex); + + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; + if (width == 0 || height == 0) flags |= SWP_NOSIZE; + + NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); +} + /********************************************************************** * WAYLAND_WindowMessage */ @@ -301,6 +352,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) wayland_init_display_devices(TRUE); wayland_resize_desktop(); return 0; + case WM_WAYLAND_CONFIGURE: + wayland_configure_window(hwnd); + return 0; default: FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); return 0; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index baf2c12a922..67cb2fe2d0b 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -444,7 +444,7 @@ static void wayland_window_surface_flush(struct window_surface *window_surface) wayland_window_surface_copy_to_buffer(wws, shm_buffer, copy_from_window_region);
pthread_mutex_lock(&wws->wayland_surface->mutex); - if (wws->wayland_surface->current_serial) + if (wayland_surface_reconfigure(wws->wayland_surface)) { wayland_surface_attach_shm(wws->wayland_surface, shm_buffer, surface_damage_region);
From: Alexandros Frantzis alexandros.frantzis@collabora.com
A request for the maximized state has two potential origins:
1. The compositor, through an xdg_toplevel configure event. In this case we update the window state and size accordingly.
2. The application or Wine itself, by changing the window style. When we detect such a style, we make a request to the compositor to set the maximized state. The compositor will then eventually reply with a configure event, and we continue with case (1). Note that the compositor may deny our request, in which case we will also sync the window style accordingly.
An acknowledged maximized state imposes very strict constraints on the size of surface content we can present. We are careful to not violate these constraints, since otherwise the compositor will disconnect us. --- dlls/winewayland.drv/wayland_surface.c | 88 ++++++++++++++++++++++---- dlls/winewayland.drv/waylanddrv.h | 6 ++ dlls/winewayland.drv/window.c | 41 +++++++++++- 3 files changed, 123 insertions(+), 12 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 0004e51fe0f..9514106d0d1 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -78,8 +78,22 @@ static void xdg_toplevel_handle_configure(void *data, { struct wayland_surface *surface; HWND hwnd = data; + uint32_t *state; + enum wayland_surface_config_state config_state = 0;
- TRACE("hwnd=%p %dx%d\n", hwnd, width, height); + wl_array_for_each(state, states) + { + switch(*state) + { + case XDG_TOPLEVEL_STATE_MAXIMIZED: + config_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; + break; + default: + break; + } + } + + TRACE("hwnd=%p %dx%d,%#x\n", hwnd, width, height, config_state);
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
@@ -87,6 +101,7 @@ static void xdg_toplevel_handle_configure(void *data, { surface->pending.width = width; surface->pending.height = height; + surface->pending.state = config_state; }
pthread_mutex_unlock(&surface->mutex); @@ -291,6 +306,32 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, } }
+/********************************************************************** + * wayland_surface_configure_is_compatible + * + * Checks whether a wayland_surface_configure object is compatible with the + * the provided arguments. + */ +static BOOL wayland_surface_configure_is_compatible(struct wayland_surface_config *conf, + int width, int height, + enum wayland_surface_config_state state) +{ + static enum wayland_surface_config_state mask = + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; + + /* We require the same state. */ + if ((state & mask) != (conf->state & mask)) return FALSE; + + /* The maximized state requires the configured size. */ + if ((conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + (width != conf->width || height != conf->height)) + { + return FALSE; + } + + return TRUE; +} + /********************************************************************** * wayland_surface_reconfigure * @@ -299,27 +340,52 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, */ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) { - if (!surface->xdg_toplevel) return TRUE; + RECT window_rect; + int width, height; + enum wayland_surface_config_state window_state;
- TRACE("hwnd=%p\n", surface->hwnd); - - /* Acknowledge any processed config. */ - if (surface->processing.serial && surface->processing.processed) + if (!surface->xdg_toplevel) return TRUE; + if (!NtUserGetWindowRect(surface->hwnd, &window_rect)) return FALSE; + + width = window_rect.right - window_rect.left; + height = window_rect.bottom - window_rect.top; + + window_state = + (NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ? + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; + + TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", + surface->hwnd, width, height, window_state, + surface->processing.width, surface->processing.height, + surface->processing.state, surface->current.width, + surface->current.height, surface->current.state); + + /* Acknowledge any compatible processed config. */ + if (surface->processing.serial && surface->processing.processed && + wayland_surface_configure_is_compatible(&surface->processing, + width, height, + window_state)) { surface->current = surface->processing; memset(&surface->processing, 0, sizeof(surface->processing)); xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } - /* If this is the initial configure, and we have a requested config, - * use that, in order to draw windows that don't go through the message - * loop (e.g., some splash screens). */ - else if (!surface->current.serial && surface->requested.serial) + /* If this is the initial configure, and we have a compatible requested + * config, use that, in order to draw windows that don't go through the + * message loop (e.g., some splash screens). */ + else if (!surface->current.serial && surface->requested.serial && + wayland_surface_configure_is_compatible(&surface->requested, + width, height, + window_state)) { surface->current = surface->requested; memset(&surface->requested, 0, sizeof(surface->requested)); xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial); } - else if (!surface->current.serial) + else if (!surface->current.serial || + !wayland_surface_configure_is_compatible(&surface->current, + width, height, + window_state)) { return FALSE; } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 5246d3ba9cb..51e958c85f8 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -57,6 +57,11 @@ enum wayland_window_message WM_WAYLAND_CONFIGURE = 0x80001001 };
+enum wayland_surface_config_state +{ + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0) +}; + struct wayland_cursor { struct wayland_shm_buffer *shm_buffer; @@ -121,6 +126,7 @@ struct wayland_output struct wayland_surface_config { int32_t width, height; + enum wayland_surface_config_state state; uint32_t serial; BOOL processed; }; diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 86f4e30b136..194568e0228 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -195,15 +195,38 @@ out: static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) { struct wayland_surface *surface = data->wayland_surface; + uint32_t window_state; + struct wayland_surface_config *conf;
pthread_mutex_lock(&surface->mutex);
if (!surface->xdg_toplevel) goto out;
- if (surface->processing.serial) surface->processing.processed = TRUE; + window_state = + (NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ? + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; + + conf = surface->processing.serial ? &surface->processing : &surface->current; + + TRACE("hwnd=%p window_state=%#x conf->state=%#x\n", + data->hwnd, window_state, conf->state); + + if ((window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + !(conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + { + xdg_toplevel_set_maximized(surface->xdg_toplevel); + } + else if (!(window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + (conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) + { + xdg_toplevel_unset_maximized(surface->xdg_toplevel); + } + + conf->processed = TRUE;
out: pthread_mutex_unlock(&surface->mutex); + wl_display_flush(process_wayland.wl_display); }
/*********************************************************************** @@ -310,6 +333,8 @@ static void wayland_configure_window(HWND hwnd) struct wayland_surface *surface; INT width, height; UINT flags; + uint32_t state; + DWORD style;
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
@@ -332,12 +357,26 @@ static void wayland_configure_window(HWND hwnd)
width = surface->processing.width; height = surface->processing.height; + state = surface->processing.state;
pthread_mutex_unlock(&surface->mutex);
+ TRACE("processing=%dx%d,%#x\n", width, height, state); + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; if (width == 0 || height == 0) flags |= SWP_NOSIZE;
+ style = NtUserGetWindowLongW(hwnd, GWL_STYLE); + if (!(state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) != !(style & WS_MAXIMIZE)) + { + NtUserSetWindowLong(hwnd, GWL_STYLE, style ^ WS_MAXIMIZE, FALSE); + flags |= SWP_FRAMECHANGED; + } + + /* The Wayland maximized state is very strict about surface size, so don't + * let the application override it. */ + if (state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) flags |= SWP_NOSENDCHANGING; + NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags); }
From: Alexandros Frantzis alexandros.frantzis@collabora.com
When we are notified by Wine core that the user wants to interactively move the window, forward the request to compositor, so it can take over and move the window according to user input.
Note that the move does *not* affect the position of the window in the Wine virtual screen space. --- dlls/winewayland.drv/wayland.c | 24 ++++++++++------ dlls/winewayland.drv/wayland_pointer.c | 6 ++++ dlls/winewayland.drv/waylanddrv.h | 10 ++++++- dlls/winewayland.drv/waylanddrv_main.c | 1 + dlls/winewayland.drv/window.c | 39 ++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 51e36b5ba60..700eb41fee7 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -34,6 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
struct wayland process_wayland = { + .seat.mutex = PTHREAD_MUTEX_INITIALIZER, .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, .output_mutex = PTHREAD_MUTEX_INITIALIZER @@ -124,14 +125,17 @@ static void registry_handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, "wl_seat") == 0) { - if (process_wayland.wl_seat) + struct wayland_seat *seat = &process_wayland.seat; + if (seat->wl_seat) { WARN("Only a single seat is currently supported, ignoring additional seats.\n"); return; } - process_wayland.wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, - version < 5 ? version : 5); - wl_seat_add_listener(process_wayland.wl_seat, &seat_listener, NULL); + pthread_mutex_lock(&seat->mutex); + seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, + version < 5 ? version : 5); + wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); + pthread_mutex_unlock(&seat->mutex); } }
@@ -139,6 +143,7 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist uint32_t id) { struct wayland_output *output, *tmp; + struct wayland_seat *seat;
TRACE("id=%u\n", id);
@@ -152,13 +157,16 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist } }
- if (process_wayland.wl_seat && - wl_proxy_get_id((struct wl_proxy *)process_wayland.wl_seat) == id) + seat = &process_wayland.seat; + if (seat->wl_seat && + wl_proxy_get_id((struct wl_proxy *)seat->wl_seat) == id) { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); - wl_seat_release(process_wayland.wl_seat); - process_wayland.wl_seat = NULL; + pthread_mutex_lock(&seat->mutex); + wl_seat_release(seat->wl_seat); + seat->wl_seat = NULL; + pthread_mutex_unlock(&seat->mutex); } }
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 69f3a7c16a7..ff376882d73 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -129,6 +129,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + struct wayland_pointer *pointer = &process_wayland.pointer; INPUT input = {0}; HWND hwnd;
@@ -146,6 +147,11 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
if (state == WL_POINTER_BUTTON_STATE_RELEASED) input.mi.dwFlags <<= 1;
+ pthread_mutex_lock(&pointer->mutex); + pointer->button_serial = state == WL_POINTER_BUTTON_STATE_PRESSED ? + serial : 0; + pthread_mutex_unlock(&pointer->mutex); + TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state);
__wine_send_input(hwnd, &input, NULL); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 51e958c85f8..bb78883c539 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -74,10 +74,17 @@ struct wayland_pointer struct wl_pointer *wl_pointer; HWND focused_hwnd; uint32_t enter_serial; + uint32_t button_serial; struct wayland_cursor cursor; pthread_mutex_t mutex; };
+struct wayland_seat +{ + struct wl_seat *wl_seat; + pthread_mutex_t mutex; +}; + struct wayland { BOOL initialized; @@ -88,7 +95,7 @@ struct wayland struct wl_compositor *wl_compositor; struct xdg_wm_base *xdg_wm_base; struct wl_shm *wl_shm; - struct wl_seat *wl_seat; + struct wayland_seat seat; struct wayland_pointer pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ @@ -230,6 +237,7 @@ RGNDATA *get_region_data(HRGN region) DECLSPEC_HIDDEN; LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; void WAYLAND_DestroyWindow(HWND hwnd) DECLSPEC_HIDDEN; void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor) DECLSPEC_HIDDEN; +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) DECLSPEC_HIDDEN; BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manager, BOOL force, void *param) DECLSPEC_HIDDEN; LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index eb54efe1180..7151d7b931a 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -34,6 +34,7 @@ static const struct user_driver_funcs waylanddrv_funcs = .pDesktopWindowProc = WAYLAND_DesktopWindowProc, .pDestroyWindow = WAYLAND_DestroyWindow, .pSetCursor = WAYLAND_SetCursor, + .pSysCommand = WAYLAND_SysCommand, .pUpdateDisplayDevices = WAYLAND_UpdateDisplayDevices, .pWindowMessage = WAYLAND_WindowMessage, .pWindowPosChanged = WAYLAND_WindowPosChanged, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 194568e0228..881ba24d01d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -415,6 +415,45 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); }
+/*********************************************************************** + * WAYLAND_SysCommand + */ +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) +{ + LRESULT ret = -1; + WPARAM command = wparam & 0xfff0; + uint32_t button_serial; + struct wl_seat *wl_seat; + struct wayland_surface *surface; + + TRACE("cmd=%lx hwnd=%p, %lx, %lx\n", + (long)command, hwnd, (long)wparam, lparam); + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if (process_wayland.pointer.focused_hwnd == hwnd) + button_serial = process_wayland.pointer.button_serial; + else + button_serial = 0; + pthread_mutex_unlock(&process_wayland.pointer.mutex); + + if (command == SC_MOVE) + { + if ((surface = wayland_surface_lock_hwnd(hwnd))) + { + pthread_mutex_lock(&process_wayland.seat.mutex); + wl_seat = process_wayland.seat.wl_seat; + if (wl_seat && surface->xdg_toplevel && button_serial) + xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + pthread_mutex_unlock(&process_wayland.seat.mutex); + pthread_mutex_unlock(&surface->mutex); + ret = 0; + } + } + + wl_display_flush(process_wayland.wl_display); + return ret; +} + /********************************************************************** * wayland_window_flush *
From: Alexandros Frantzis alexandros.frantzis@collabora.com
When we are notified by Wine core that the user wants to interactively resize the window, forward the request to compositor, so it can take over and resize the window according to user input.
In the process of the interactive resize we receive a stream of xdg_toplevel configure events informing us about the updated window sizes. --- dlls/winewayland.drv/wayland_surface.c | 3 ++ dlls/winewayland.drv/waylanddrv.h | 9 ++++- dlls/winewayland.drv/window.c | 47 ++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index 9514106d0d1..8551ad98eeb 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -88,6 +88,9 @@ static void xdg_toplevel_handle_configure(void *data, case XDG_TOPLEVEL_STATE_MAXIMIZED: config_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED; break; + case XDG_TOPLEVEL_STATE_RESIZING: + config_state |= WAYLAND_SURFACE_CONFIG_STATE_RESIZING; + break; default: break; } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index bb78883c539..4c6eb170900 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -59,7 +59,8 @@ enum wayland_window_message
enum wayland_surface_config_state { - WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0) + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0), + WAYLAND_SURFACE_CONFIG_STATE_RESIZING = (1 << 1) };
struct wayland_cursor @@ -147,6 +148,7 @@ struct wayland_surface pthread_mutex_t mutex; struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; + BOOL resizing; };
struct wayland_shm_buffer @@ -228,6 +230,11 @@ static inline BOOL intersect_rect(RECT *dst, const RECT *src1, const RECT *src2) return !IsRectEmpty(dst); }
+static inline LRESULT send_message(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + return NtUserMessageCall(hwnd, msg, wparam, lparam, NULL, NtUserSendMessage, FALSE); +} + RGNDATA *get_region_data(HRGN region) DECLSPEC_HIDDEN;
/********************************************************************** diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 881ba24d01d..5079d820929 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -335,6 +335,8 @@ static void wayland_configure_window(HWND hwnd) UINT flags; uint32_t state; DWORD style; + BOOL needs_enter_size_move = FALSE; + BOOL needs_exit_size_move = FALSE;
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
@@ -359,10 +361,25 @@ static void wayland_configure_window(HWND hwnd) height = surface->processing.height; state = surface->processing.state;
+ if ((state & WAYLAND_SURFACE_CONFIG_STATE_RESIZING) && !surface->resizing) + { + surface->resizing = TRUE; + needs_enter_size_move = TRUE; + } + + if (!(state & WAYLAND_SURFACE_CONFIG_STATE_RESIZING) && surface->resizing) + { + surface->resizing = FALSE; + needs_exit_size_move = TRUE; + } + pthread_mutex_unlock(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state);
+ if (needs_enter_size_move) send_message(hwnd, WM_ENTERSIZEMOVE, 0, 0); + if (needs_exit_size_move) send_message(hwnd, WM_EXITSIZEMOVE, 0, 0); + flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE; if (width == 0 || height == 0) flags |= SWP_NOSIZE;
@@ -415,6 +432,22 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); }
+static enum xdg_toplevel_resize_edge hittest_to_resize_edge(WPARAM hittest) +{ + switch (hittest) + { + case WMSZ_LEFT: return XDG_TOPLEVEL_RESIZE_EDGE_LEFT; + case WMSZ_RIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_RIGHT; + case WMSZ_TOP: return XDG_TOPLEVEL_RESIZE_EDGE_TOP; + case WMSZ_TOPLEFT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT; + case WMSZ_TOPRIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT; + case WMSZ_BOTTOM: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM; + case WMSZ_BOTTOMLEFT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT; + case WMSZ_BOTTOMRIGHT: return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT; + default: return XDG_TOPLEVEL_RESIZE_EDGE_NONE; + } +} + /*********************************************************************** * WAYLAND_SysCommand */ @@ -436,14 +469,24 @@ LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) button_serial = 0; pthread_mutex_unlock(&process_wayland.pointer.mutex);
- if (command == SC_MOVE) + if (command == SC_MOVE || command == SC_SIZE) { if ((surface = wayland_surface_lock_hwnd(hwnd))) { pthread_mutex_lock(&process_wayland.seat.mutex); wl_seat = process_wayland.seat.wl_seat; if (wl_seat && surface->xdg_toplevel && button_serial) - xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + { + if (command == SC_MOVE) + { + xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + } + else if (command == SC_SIZE) + { + xdg_toplevel_resize(surface->xdg_toplevel, wl_seat, button_serial, + hittest_to_resize_edge(wparam & 0x0f)); + } + } pthread_mutex_unlock(&process_wayland.seat.mutex); pthread_mutex_unlock(&surface->mutex); ret = 0;
From: Alexandros Frantzis alexandros.frantzis@collabora.com
Store and compare against the wl_seat global id (aka name) during global_remove, since the global id is distinct from the wl_proxy id which we were previously checking. --- dlls/winewayland.drv/wayland.c | 5 +++-- dlls/winewayland.drv/waylanddrv.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 700eb41fee7..b8c69a105cb 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -134,6 +134,7 @@ static void registry_handle_global(void *data, struct wl_registry *registry, pthread_mutex_lock(&seat->mutex); seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, version < 5 ? version : 5); + seat->global_id = id; wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); pthread_mutex_unlock(&seat->mutex); } @@ -158,14 +159,14 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist }
seat = &process_wayland.seat; - if (seat->wl_seat && - wl_proxy_get_id((struct wl_proxy *)seat->wl_seat) == id) + if (seat->wl_seat && seat->global_id == id) { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); pthread_mutex_lock(&seat->mutex); wl_seat_release(seat->wl_seat); seat->wl_seat = NULL; + seat->global_id = 0; pthread_mutex_unlock(&seat->mutex); } } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 4c6eb170900..faff529940d 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -83,6 +83,7 @@ struct wayland_pointer struct wayland_seat { struct wl_seat *wl_seat; + uint32_t global_id; pthread_mutex_t mutex; };
Looks okay I think although I find the seat locking again a bit overkill. I don't really see a scenario where a wine process would be used across seats, can this really happen on Wayland?
I understand that as the event is dynamically sent we may have to support it, but I would find it simpler if we could assume that we have a seat from the start (eventually waiting for it on startup, idk), and where we'd just abort if the seat is removed.
Probably the most interesting scenario for dynamic seat management is remote access (e.g, VNC/RDP). This is typically implemented by the compositor by exposing a separate `wl_seat` for each viewer/connection. When the remote viewer is closed, the compositor destroys the associated `wl_seat`, so Wayland clients should ideally be able to gracefully handle such removals.
Proper/full remote support (e.g., multiple viewers and/or non-headless setups) would require multi-seat handling, which we don't currently implement in the driver.
@rbernon The discussion/investigation around remote sessions and `wl_seat` handling, led me to find issue with `wl_seat` removals. I have added the fix as a new commit to this MR. Thanks!
On Thu Sep 21 18:31:57 2023 +0000, Alexandros Frantzis wrote:
An easy and non-intrusive way to experiment with the upstream Wayland driver is:
- Create the registry key `HKEY_CURRENT_USER\Software\Wine\Drivers\Graphics="x11,wayland"`
- Unset the `DISPLAY` env. variable, e.g, `DISPLAY= wine ...`, to force
the use of the Wayland driver
hello @afrantzis thanks for your hard work I just needed a little help
so I was curious to check how will all of this work out to be when it will all be ready so I tried building the Wayland branch of wine
![image.png](/uploads/0976ecc3a2465c9a0bc68401b1be2946/image.png){width=418 height=165}
so when I run
./configure
make -j 8
and than run ./wine notepad well that didn't work and its still on xwayland
![image.png](/uploads/969abc5169949ae167ed49711d3af740/image.png)
so when I saw this response I tried it by doing this
![image.png](/uploads/605057980ac3fdba7a01fd8550baccc0/image.png)
and then run `DISPLAY=wine ./wine notepad`
`yeah that didn't work as well`
`so can you provide the actual method to test either the wayland driver in the master branch or even the full wayland driver on the wayland branch`
On Sat Sep 23 20:08:39 2023 +0000, beh 591 wrote:
hello @afrantzis thanks for your hard work I just needed a little help so I was curious to check how will all of this work out to be when it will all be ready so I tried building the Wayland branch of wine ![image.png](/uploads/0976ecc3a2465c9a0bc68401b1be2946/image.png){width=418 height=165} so when I run
./configure
make -j 8
and than run ./wine notepad well that didn't work and its still on xwayland ![image.png](/uploads/969abc5169949ae167ed49711d3af740/image.png) so when I saw this response I tried it by doing this ![image.png](/uploads/605057980ac3fdba7a01fd8550baccc0/image.png) and then run `DISPLAY=wine ./wine notepad` `yeah that didn't work as well` `so can you provide the actual method to test either the wayland driver in the master branch or even the full wayland driver on the wayland branch`
@beh_591 I don't know much about all of this, I just noticed you didn't follow the instructions correctly.
The instructions are telling you to unset the `DISPLAY` variable, you should be doing
`DISPLAY= ./wine notepad`
instead of
`DISPLAY=wine ./wine notepad`
Hope this helps :)
On Sat Sep 23 20:15:22 2023 +0000, Benjamin Blacher wrote:
@beh_591 I don't know much about all of this, I just noticed you didn't follow the instructions correctly. The instructions are telling you to unset the `DISPLAY` variable, you should be doing `DISPLAY= ./wine notepad` instead of `DISPLAY=wine ./wine notepad` Hope this helps :)
Also you should create Graphics as a string value in Drivers. This works for me.
![Screenshot_from_2023-09-24_01-27-44](/uploads/8c0ce21f48aa5cff55693c19559286d5/Screenshot_from_2023-09-24_01-27-44.png)
On Sat Sep 23 20:28:43 2023 +0000, darkblaze69 wrote:
Also you should create Graphics as a string value in Drivers. This works for me. ![Screenshot_from_2023-09-24_01-27-44](/uploads/8c0ce21f48aa5cff55693c19559286d5/Screenshot_from_2023-09-24_01-27-44.png)
@bblacher @darkblaze69 after reconfiguring again I just noticed
`configure: Wayland 32-bit development files not found or not new enough, the Wayland driver won't be supported.`
`so I guess I should download whatever that is I'll make an update when I figure the name of the package on arch`
On Sat Sep 23 20:45:48 2023 +0000, beh 591 wrote:
@bblacher @darkblaze69 after reconfiguring again I just noticed `configure: Wayland 32-bit development files not found or not new enough, the Wayland driver won't be supported.` `so I guess I should download whatever that is I'll make an update when I figure the name of the package on arch`
update so I have this launch error now
`wine: could not load ntdll.so: /home/..../wine/dlls/ntdll/ntdll.so: wrong ELF class: ELFCLASS64`
On Sat Sep 23 21:11:10 2023 +0000, beh 591 wrote:
update so I have this launch error now `wine: could not load ntdll.so: /home/..../wine/dlls/ntdll/ntdll.so: wrong ELF class: ELFCLASS64`
anyway so I made it work thanks guys and yes as you all said I should use
DISPLAY= ./wine64 notepad
and put the graphics key as its own string key
On Sat Sep 23 21:22:58 2023 +0000, beh 591 wrote:
anyway so I made it work thanks guys and yes as you all said I should use DISPLAY= ./wine64 notepad and put the graphics key as its own string key
huh even after that its still not loading ![image](/uploads/86f1ffc4484cebbfebd6095f62237a09/image.png) ![image](/uploads/c6fcab061a8c0c0ea9edea67cadf5297/image.png)
On Sun Sep 24 02:27:30 2023 +0000, Vixea wrote:
huh even after that its still not loading ![image](/uploads/86f1ffc4484cebbfebd6095f62237a09/image.png) ![image](/uploads/c6fcab061a8c0c0ea9edea67cadf5297/image.png)
OHHH, I know what I did lol
What happened to this? Everything seems to be ready now.
On Thu Sep 21 16:10:06 2023 +0000, Alexandros Frantzis wrote:
Hi! At this point there are no plans to use any external client-side mechanism to draw window decorations. For libdecor, in particular, my impression is that while its abstractions for event dispatching and surface configuration are helpful for typical Wayland clients, they are not a good match for the driver's integration needs, for which we need finer and more direct control. Some other ideas:
- Support server-side decorations, which will help with KDE and wlroots
based compositors. 2. Create a Wine decoration theme to better match typical GNOME/KDE etc (will only help with apps that don't do their own decorations).
Noting that server-side decorations and libdecor are not mutually exclusive; if a user of libdecor runs in an SSD-enabled context, it will just ask the compositor to draw decorations instead.
But it would probably be better to do the latter (Wine decoration) for GNOME, and maybe one other generic (Windows 10/11-like?) decoration for unrecognized desktops that require a decoration. Or just one or the other.
The only intent here is for some nice looking decorations on GNOME and Weston, or any other compositors without decorations, which any solution that I mentioned would result in.