fix(wayland): open windows on compositors without xdg-decoration, viewporter or fractional scale
Window - The constructor made a fractional scale, a toplevel decoration and a viewport from Device::fractionalScaleManager, Device::manager and Device::wpViewporter without looking at them. Device::handle_global binds those globals only when the compositor advertises them, and Initialize requires only wl_shm, wl_compositor and xdg_wm_base, so on a compositor without one of the three (GNOME's Mutter has no xdg-decoration) the constructor handed libwayland a null proxy and crashed before the window existed (#162). Each object is now made only when its global is there, which Resize and the destructor already assumed. - The fractional scale needs the viewporter too: the preferred scale is applied through the viewport, which shows the buffer's physical pixels at width/scale x height/scale. A surface without a viewport is as large as its buffer, so there the scale stays 1, which keeps pointer and touch positions, configure sizes and the text-input caret, all converted by it, in physical pixels; the compositor scales the window up on a HiDPI output. A scale that changes after the constructor is still applied only by the next resize, which is #165. - Without xdg-decoration the window has no title bar, since the library draws no client-side decorations. Device - The optional globals say they are optional, and that a request on a null proxy crashes. Tests - WindowOptionalGlobals: hides xdg-decoration, wp_viewporter and wp_fractional_scale_v1 from the Window one at a time and all at once, by nulling the Device statics after Initialize, and renders, resizes and closes a window each time without a protocol error. Before the fix it crashed on the window without xdg-decoration. A global the compositor does not offer is reported as a SKIP line, since the path that uses it goes untested there. README - Which Wayland protocols the window needs, and what it does without the optional ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
6e94cc6209
commit
670df31cc6
5 changed files with 184 additions and 7 deletions
|
|
@ -364,18 +364,36 @@ Window::Window(std::uint32_t width, std::uint32_t height) : width(width), height
|
|||
xdg_toplevel_add_listener(xdgToplevel, &xdg_toplevel_listener, this);
|
||||
wl_surface_commit(surface);
|
||||
|
||||
wp_scale = wp_fractional_scale_manager_v1_get_fractional_scale(Device::fractionalScaleManager, surface);
|
||||
wp_fractional_scale_v1_add_listener(wp_scale, &wp_fractional_scale_v1_listener, this);
|
||||
// The fractional scale, the decoration and the viewport come from
|
||||
// optional protocols: Device::handle_global binds a global only when the
|
||||
// compositor advertises it, and a request on the null proxy it leaves
|
||||
// otherwise crashes in libwayland (#162). The preferred scale is applied
|
||||
// through the viewport, which shows the width x height physical pixels of
|
||||
// the buffer at width/scale x height/scale, so without a viewporter there
|
||||
// is no fractional scale either: scale stays 1, the surface is as large as
|
||||
// its buffer, and the compositor scales it up on a HiDPI output. A scale
|
||||
// that changes after this is applied only by the next resize (#165).
|
||||
if (Device::fractionalScaleManager != nullptr && Device::wpViewporter != nullptr) {
|
||||
wp_scale = wp_fractional_scale_manager_v1_get_fractional_scale(Device::fractionalScaleManager, surface);
|
||||
wp_fractional_scale_v1_add_listener(wp_scale, &wp_fractional_scale_v1_listener, this);
|
||||
}
|
||||
|
||||
while (wl_display_dispatch(Device::display) != -1 && !configured) {}
|
||||
|
||||
wl_surface_commit(surface);
|
||||
|
||||
decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(Device::manager, xdgToplevel);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
// GNOME's Mutter has no xdg-decoration: it leaves decorations to the
|
||||
// client, and the library draws none, so there the window has no title
|
||||
// bar.
|
||||
if (Device::manager != nullptr) {
|
||||
decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(Device::manager, xdgToplevel);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
wpViewport = wp_viewporter_get_viewport(Device::wpViewporter, surface);
|
||||
wp_viewport_set_destination(wpViewport, std::ceil(width/scale), std::ceil(height/scale));
|
||||
if (Device::wpViewporter != nullptr) {
|
||||
wpViewport = wp_viewporter_get_viewport(Device::wpViewporter, surface);
|
||||
wp_viewport_set_destination(wpViewport, std::ceil(width/scale), std::ceil(height/scale));
|
||||
}
|
||||
|
||||
wl_surface_commit(surface);
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in a new issue