Add a new flag to track whether buffer scale is dirty or not,
and centralize calling wl_surface_set_buffer_scale() in a single
place: gdk_wayland_surface_sync_buffer_scale().
gdk_wayland_surface_sync_buffer_scale() is only called by
gdk_wayland_surface_sync(), which itself is called by the GL,
Vulkan, and Cairo contexts, right before submitting a frame.
This ensure that each frame has an up-to-date buffer scale.
This mimics how opaque and input regions are tracked.
If we map, reposition, unmap, remap, the reposition feedback from the
last time a popup was mapped might be received while we're dealing with
the new version of the popup. At this point, the old reposition token
has no meating, so lets drop it. Also reset the reposition tokens when
creating new protocol objects, so that the reposition token are as if
we're in the initial state.
This fixes an issue where we'd get stuck if repeatedly smashing a button
that'd create popups that'd immediately get dismissed by the compositor.
Since Wayland 1.15, it is now possible to use absolute paths in
"WAYLAND_DISPLAY".
In that scenario, having a valid "XDG_RUNTIME_DIR" is not a requirement
anymore.
For this reason we remove the "XDG_RUNTIME_DIR" check and we let
`wl_display_connect()` decide if our environment is correct.
Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com>
The cursor-theme-size setting is documented as
'0 means the default size'. Make it so by using
size 24 if we see a 0. Its better than crashing.
Fixes: #5700
Otherwise GL surfaces that redraw without changing the hotspot have it
applied on top every frame and quickly slide away.
The cairo path and the X11 backend do not have this bug.
GdkDragSurface-backed widgets are not parented to an existing widget,
unlike popovers, and like toplevels. This means that there's nobody to
actively call gdk_drag_surface_present() to update the size, and
GdkDragSurface should do it on its own, just like GdkToplevel.
This commit implements this for the Wayland backend.
The split-up of gdksurface-wayland.c introduced a protocol violation
when it didn't make sure xdg_surface was destroyed after the role
objects (xdg_popup / xdg_toplevel). Fix that.
Fixes: 2a463baed0 ("wayland: Rearrange the surface code")
The availability of wl_surface.offset depends on the compositor, so we
can't call it unconditionally. Add a version check to so we only call
offset if we know we won't raise a protocol error.
Fixes: 0eb791eaaa ("Make mask nodes more versatile")
This is a bit spaghetti right now, since seats and devices were
heavily entangled there are a number of crossed private API calls that
should ideally not be there.
Let this be a first step, so more bits may move from the seat
implementation to devices.
This file, event though a clump of input-y objects, has more of
seats than anything else. Rename it so that we can start splitting
these objects out of it.
This is currently just used as a convenience storage of the startup ID
between the GtkApplication and the GtkWindow (after it's ready to notify
on it).
This could be untangled in the GTK layers so there is no involvement
from GDK in keeping the startup ID around, in the mean time just deprecate
these gdk_wayland* API calls.
This call has everything to perform activation as specified by the
xdg_activation protocol, notably a surface to activate as opposed to
gdk_display_notify_startup_complete().
Make activation happen here, so that the surface gets activated when
its gets a startup ID assigned.
The argument to xdg_activation_token_v1_set_surface is documented to be the
surface requesting the activation, not the surface to be activated, which is
given later when calling xdg_activation_v1_activate.
(c.f. 36cee4bdbc)
Use the same logic as in gdk_wayland_app_launch_context_get_startup_notify_id,
i.e. if we have a surface with focus, set that, otherwise set NULL.
This fixes requesting urgent/focus on wlroots (compositors like Sway, etc.),
which was blocked as the surface requesting the activation didn't have focus.
Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com>
By using wl_output_release(), GDK lets the compositor to clean up the
output global more nicely.
For example, currently, most compositors remove the global and then
destroy it later after N seconds expire. With this, the compositor could
experiment with destroying the output global once all its resources are
destroyed.
There's 2 things broken here:
- The mask was calculated on top of the GDK button (i.e. skipping
4-7 buttons), so GDK_BUTTON4_MASK and GDK_BUTTON5_MASK were not
assigned. This is now calculated on the (continuous) BTN_ evcodes
so it is guaranteed that the next 2 physical buttons (i.e.
back/forward) get these two places in the mask assigned.
- Furthermore, these buttons would be pushed to places in the
modifier mask that they didn't belong to. It is now checked hard
that only the first 5 buttons enable a modifier flag.
Overall, this ensures that no event masks with bonkers values are
forwarded, and that no stale implicit grabs are left after additional
buttons are pressed.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5301
When getting the serial for primary/clipboard selections we used a
function that largely relied on a GdkEvent being passed. We have
another available function that looks up the most recent serial
given the ongoing touch/tablet input as well.
This is the second best, compared to actually knowing the
input/device from the event that was received by the UI an triggered
the clipboard operation, and is already in use in other places
(e.g. window dragging). It is valid for these situations too.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5250
We shouldn't assume there is always a monitor to derive bounds from.
If there is no monitor, pass empty bounds, as this matches what
xdg_toplevel.configure_bounds do in this case.
As far as I'm aware, these only exist with `gdk_wayland_surface_` names
for historical reasons, before these types were split.
This way, those functions will be able to access members of the
`GdkWaylandToplevel` struct. And it just saves a few lines of code.
`apply_monitor_change()` already calls `update_scale()`.
Note that this only affects old compositor versions (see
`should_update_monitor()`) so it's just a minor cleanup.
Starting with the Wayland protocol wl_pointer >= 8, discrete axis
events have been deprecated in favour of high-resolution scroll event.
Add a listener for high-resolution scroll events and, for backwards
compatibility, handle discrete events as discrete*120.
Even though the argument is non-nullable, GTK sometimes incurs in that
by itself by destroying the surface while the event is in flight. This
is the case of popping down a GtkDropdown. When this happens we simply
ignore the crossing event, but we should let it through instead, the
compositor did not send it in vain and we possibly still have pointer
state to undo.
Drop the surface checks, so that the event is propagated along GTK.
Following what was done for pinch/swipe events, give hold gestures their
own distinct sequence as well. Without this it was NULL, which was already
distinct to other touchpad gestures.
This serial should be that from a button press/touch down/etc, use
the last implicit grab here, which will presumably be from the same
device that triggered the event.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/5048
The GdkToplevelSize struct already has the concept of "bounds", which
means the largest size a window should reasonably have. It's practically
the equivalent of the monitor the window is intended to be mapped on,
with the "struts" (e.g. panels) cut out. It's used by GTK to use this
information to calculate a default window size that is "lagom" (swedish;
not too large, not too small).
When loading cursors at scale, we expect the
cursor images to have a size of scale * size.
If we don't find such images, load them at their
unscaled size and scale them up ourselves.
Without this, cursors will appear in unexpected
sizes depending on scales and themes.
Related: #4746
On Wayland it is a protocol violation to upload buffers with
dimensions that are not an integer multiple of the buffer scale.
Until recently, Mutter did not enforce this. When it started
doing so, some users started seeing crashes in GTK apps because the
cursor theme ended up with e.g. a 15x16 pixel image at scale of 2.
Add a small sanity check for this case.
Previously, there was an issue with glitching after showing/hiding a
popover that was not also destroyed. This was due to the popover having
an update_freeze_count of zero after hiding the surface.
That resulted in it's toplevel continuously dropping frames such as during
high-frame-rate scrolling in textviews. This problem is much more visible
on high-frame-rate displays such as 120hz/144hz.
With this commit, we freeze the frame clock of the popup until it is
mapped again.
Add a new GdkScrollUnit enum that represent the
unit of scroll deltas provided by GdkScrollEvent.
The unit is accessible through
gdk_scroll_event_get_unit().
Currently, we have all the plumbing in place so that GTK consumes the
startup notification ID when focusing a window through the xdg-activation
protocol.
This however misses the case that a window might be requested to be
focused with no startup ID (i.e. via interaction with the application,
not through GApplication or other application launching logic).
In this case, we let the application create a token that will be
consumed by itself. The serial used is that from the last
interaction, so the compositor will still be able to do focus prevention
logic if it applies.
Since we already do have a last serial at hand, prefer xdg-activation
all the way over the now stale gtk-shell focusing support. The timestamp
argument becomes unused, but that is a weak argument to prefer the
private protocol over the standard one. The gtk-shell protocol support
is so far left for interaction with older Mutter.
Tools like gtk4-launch can't set surface on the activation token so
don't require it. If the compositor requires it we can't do anything
about it anyway. This avoids a critical:
(gtk4-launch:23497): Gdk-CRITICAL **: 17:07:24.704: gdk_wayland_surface_get_wl_surface: assertion 'GDK_IS_WAYLAND_SURFACE (surface)' failed
Fixes: be4216e051 ("gdk/wayland: Support the xdg-activation wayland protocol")
Signed-off-by: Guido Günther <agx@sigxcpu.org>
We only save the size when we transition from floating to fixed, so that
we can restore the size to the one prior to being fixed.
However, we should not restore to this size whenever we see a 0x0 size
from xdg_toplevel, as it can do that any time it doesn't care about the
size, e.g. when the surface is floating and just changing state.
Fix this by only using the saved size when transitioning from fixed to
floating, not when staying floating while previously floating.
Closes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4634
gdk_wayland_toplevel_inhibit_idle() contained a contradictory assert
that always fail. More specifically, in the branch that is supposed to
create the idle inhibitor, there is an assertion that it must already
exist and that the refcount must be greater than zero. This causes a
crash on WMs/DEs that use the ZWP idle inhibit manager protocol such as
KDE Plasma and Sway. Fix this by just asserting that the refcount is
zero instead.
This makes the hotspot of DND surfaces work when using the Vulkan and
OpenGL renderers.
This bumps the CI image used to the newly built image. This is needed to
install a new enough libwayland-client.so needed for wl_surface.offset.
This is done by adding wayland as a meson subproject, building it
on-demand if the version in the system is not new enough. As
libwayland-client.so is pulled in implicitly when linking to gtk4, the
compile step needs LD_LIBRARY_PATH set to make ld find the right library
to link to.
If we ended up on no output at all, keep the HiDPI scale as is, as it
likely means we were on a workspace that was switched away from. By
keeping the same scale, we avoid unnecessary scale changes that would
otherwise take place if the scale when on monitors would end up being
more than 1.
We now have a boolean setting that determines whether the high-contrast
theme should be used. Support it by automatically setting the existing
`gtk-theme-name` and `gtk-icon-theme-name` properties when enabled.
With that, it is no longer necessary to change the regular theme settings
for high-contrast, so toggling between high-contrast and a non-default
theme finally works reliably.
It makes sense to connect the begin/update/end events
for touchpad swipes and pinches in a sequence. This
commit adds the plumbing for it, but not backends
are setting sequences yet.
In some circumstances (e.g. activating with a stylus something that
closes a window), we can receive zwp_tablet_tool.proximity_out without
receiving a zwp_tablet_tool.up beforehand.
In those cases, we are not expecting neither .up nor .button, so
reset the stylus device button modifiers on proximity_out.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4103
We are looking up the seat logical pointer modifiers (i.e. the wl_pointer),
not the ones for the tablet tool device. This breaks accounting further
along in GTK leaving stuck implicit grabs.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/4102
As far as I can tell, the code here is redundant and probably ended up
this way for historical reasons. A drag surface without
`->is_drag_surface` would be created if `gdk_display_create_surface`
were called with `GDK_SURFACE_TEMP`, but drag surfaces never seem to be
created that way.
In `gtk4-demos`, drag and drop and popovers seem to be working normally
with this.
Ping/pong serials are not meant to be interpreted as user input serials
(e.g. those given back later to the compositor on grabs). As a matter
of fact, Mutter uses a different count (i.e. timestamps) in these, so
using these serials may confuse the compositor into denying certain
operations like DnD.
Instead of using GL_BACK, use GL_BACK_LEFT, because the spec demands
this (many drivers don't).
Also move the call from the GDK backends into the GLContext code, as
this is a generic EGL issue (nvidia being the main driver in need of
this call, see 9c4c4eaaa1 for a longer
discussion).
Fixes#4402
Otherwise if we hide and show a window we recreate a new surface,
breaking the compositor's association, but potentially not resend this
data for the new surface.
This matches what we do for input_region.
The term "hdr" is so overloaded, we shouldn't use them anywhere, except
from maybe describing all of this work in blog posts and other marketing
materials.
So do renames:
* hdr => high_depth
* request_hdr => prefers_high_depth
This more accurately describes what is going on.
Unify the X11 and Wayland EGL contexts.
This is a bit ugly to implement, because I don't want to create an
interface and I can't make them inherit from the same object, because
one needs to inherit from X11GLContext and the other from
WaylandGLContext.
So we have to put the code in GdkGLContext and make sure non-EGL
contexts can't accidentally run it. This is rather easy because we can
just check for priv->egl_context != NULL.
Print the extensions one per line, and sort them
alphabetically, so it is actually possible to find
something in the list.
Also print a short description of the chosen config.
Creative people managed to create an X11 display and a Wayland display
at once, thereby getting EGL and GLX involved in a fight to the death
over the ownership of the glFoo() symbolspace.
A way to force such a fight with available tools here is (on Wayland)
running something like:
GTK_INSPECTOR_DISPLAY=:1 GTK_DEBUG=interactive gtk4-demo
Related: xdg-desktop-portal-gnome#5
Goals:
1. Provide as much information as possible in the error message, so
users can try to fix their system themselves.
2. Try to formulate the error message in a way that explains that this
is not something GTK can fix, but a lower layer problem.
Related: #4193
Usually the "dnd-finished" signal will be used to unref the GdkDrag. In
those cases, we would lose the object, so that when we do the final
drag_drop_done() afterwards, we wouldn't have a remaining reference.
With the reference guard, this now works.
nvidia sets the default draw buffer to GL_NONE if EGL contexts are
initially bound to EGL_NO_SURFACE which is exactly what we are doing. So
bind them to GL_BACK when drawing, as they should be.
See https://phabricator.services.mozilla.com/D118743 for a discussion
about EGL_NO_CONTEXT and draw buffers.
Now that we have the display's context to hook into, we can use it to
construct other GL contexts and don't need a GdkSurface vfunc anymore.
This has the added benefit that backends can have different GdkGLContext
classes on the display and get new GLContexts generated from them, so
we get multiple GL backend support per GDK backend for free.
I originally wanted to make this a vfunc on GdkGLContextClass, but
it turns out all the abckends would just call g_object_new() anyway.
Instead of
Display::make_gl_context_current()
we now have
GLContext::clear_current()
GLContext::make_current()
This fits better with the backends (we can actually implement
clearCurrent on macOS now) and makes it easier to implement different GL
backends for backends (like EGL/GLX on X11).
We also pass a surfaceless boolean to make_current() so the calling code
can decide if a surface needs to be bound or not, because the backends
were all doing whatever, which was very counterproductive.
The code to create and manage a fake egl surface to bind to is
complex and completely untested because everyone seems to support this
extension.
nvidia and Mesa do support it and according to Mesa devs, adding support
in a new driver is rather simple and Mesa drivers gain that feature
automatically, so all future drivers shoould have it.
... or more exactly: Only use paint contexts with
gdk_cairo_draw_from_gl().
Instead of paint contexts being the only contexts who call swapBuffer(),
any context can be used for this, when it's used with
begin_frame()/end_frame().
This removes 2 features:
1. We no longer need a big sharing hierarchy. All contexts are now
shared with gdk_display_get_gl_context().
2. There is no longer a difference between attached and non-attached
contexts. All contexts work the same way.
The vfunc is called to initialize GL and it returns a "base" context
that GDK then uses as the context all others are shared with. So the GL
context share tree now looks like:
+ context from init_gl
- context1
- context2
...
So this is a flat tree now, the complexity is gone.
The only caveat is that backends now need to create a GL context when
initializing GL so some refactoring was needed.
Two new functions have been added:
* gdk_display_prepare_gl()
This is public API and can be used to ensure that GL has been
initialized or if not, retrieve an error to display (or debug-print).
* gdk_display_get_gl_context()
This is a private function to retrieve the base context from
init_gl(). It replaces gdk_surface_get_shared_data_context().
Create it during init and then reuse it for all contexts.
While doing that, also improve error reporting - that's not used yet but
will in later commits.
If the pointer capability is added, pointer swipe and pinch gestures
will be created. However, if the pointer capability is removed, the
gesture objects won't be destroyed.
If the pointer capability is removed and added several times in a row,
for example due to plugging and unplugging physical mouse, this can lead
to leaking the old gesture objects.
In order to prevent that, this change makes the seat destroy swipe and
pinch gestures when the pointer capability is withdrawn.
We must call gdk_drag_drop_done() when the drag ends,
successfully or not. Without this, we get an unwarranted
emission of ::cancel after a successful drop.
Since only the first call to gdk_drag_drop_done() is taking
effect, it is safe to call as a fallback, after emitting
::dnd-finished. If the application connects to that signal
and calls gdk_drag_drop_done() itself, its call will take
precedence.
This matches what the X11 implementation does.
The releasing of grabs while a button is pressed (e.g. after starting dnd, or
dragging the window, or going to overview with a pressed button, etc...) was
generalized here in https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/1879.
However we shouldn't break all grabs here. In the case of grabbing popups,
compositors will still emit crossing events between client surfaces (e.g.
popping up and selecting a menu item via press-drag-release), breaking all
grabs here means inconsistent client state, that was
https://gitlab.gnome.org/GNOME/gtk/-/issues/2746.
That was fixed in mutter, by essentially making implicit grabs
owner_events=FALSE, however that breaks the mentioned use pattern entirely.
Mutter is changing this behavior back, so GTK should handle these crossing
events.
The grab that we are interested in breaking here is the implicit pointer
one. Popups will be dismissed via other means if the compositor says their
active grab needs breaking. This still leaves dnd/move/resize drags in
one place, while not allowing #2746 to happen with popups.
Remove a boatload of "or %NULL" from nullable parameters
and return values. gi-docgen generates suitable text from
the annotation that we don't need to duplicate.
This adds a few missing nullable annotations too.
Width and height of a GdkMonitor are derived via wl_output which
talks about physical dimensions of a device and compositors usually
implement this as the untransformed values (e.g. weston, wlroots).
Since the GTK client has no way to figure out if a monitor was rotated,
transform the physical dimensions according to the applied wayland
transform to have the physical dimensions match the logical ones.
Mutter flips the physical dimensions itself but doesn't announce the
transform so this shouldn't break anything there.
Rewrite this in a way that doesn't depend on kernel
header defines at the time the wayland scanner was run.
This was causing the build to break on Centos 8, where
a bunch of fourcc formats are missing.
When building for homebrew/linuxbrew on Ubuntu 16.04, memfd_create() is
not available and causes the build to fail.
This adds a proper check for the function.