We only have one config, because we use the same Visual everywhere.
Store this config in the GdkDisplayX11 struct for easy access.
Also do this on initialize, because if creating the config fails, we
want to switch to GLX instead of failing to do GL at all.
This also simplifies a lot of code as we can share Visual, Colormap, etc
across surfaces.
There's no need to use g_object_set_data() for it.
We can also stop caching it elsewhere because we know the display has
it.
And finally, we can remove the display->have_egl boolean and use
display->egl_display != NULL instead. We initialize the display at
startup, so that variable is the perfect indicator.
We need to initialize GL to select the Visual we are going to use for
all our Windows.
As the Visual needs to be known before we know if we are even gonna use
GL later, we can't avoid initializing it.
Note that this previously happened, too. It was just hidden behind the
GdkScreen initialization.
We don't want to bind ourselves to GTK3 - both because we don't want to
accidentally cause bugs in a different codebase and because we want to
deviate from it.
While doing so, also store visuals as visuals and not as integers.
And only store one Visual because GTK4 only uses one visual.
And then remove the code that is leftover for dealing with the
compatibility Visual for GTK3.
PS: I'm kinda proud of my STRINGIFY_WITHOUT_BRACKETS hack.
The old code was ordering visuals by depth, but considering that these
days we either use the default visual or a 32bit RGBA visual, that
reordering does not have an effect anymore.
In theory, the only effect is that the GLX Visual selection might select
a different replacement Visual when it checks for improved GL Visuals, but
even there I can't come up with a case where that matters, because
again, the visuals are only reordered by depth and we want to keep the
depth.
In any case, make this a separate commit so bisecting can find this
problem if it ever shows up.
Instead of the display telling the screen to tell the visuals to tell
the display to initialize itself, just init the display directly.
What a concept.
It's only used during DND to allow use of the root window's cow window
as a DND target, because apparently gnome-shell used to think that was a
great idea to DND to the overview.
Somebody complain to gnome-shell devs about it not being a good idea if
they want it fixed.
Potentially using Wayland is a better idea though.
This reverts 85ae875dcb
Related: https://bugzilla.gnome.org/show_bug.cgi?id=601731
Check that we are indeed running inside an Xorg server before enabling
the workaround.
XWayland or other nested X servers deadlock when that workaround is
applied.
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.
If we want to add an EGL implementation for the X11 backend, we are
going to need to move the GLX bits into their own class. The first step
is to declare GdkX11GLContext as an abstract type, and then subclass it
into a GdkX11GLContextGLX type, which includes the whole GLX
implementation.
The condition we check for to catch X servers going away
may not be accurate anymore, and the warning shows up in
logs, causing customers to be concerned. So, be quiet by
default, unless the user explicitly asked for a message.
The DnD code for X11 adds the composite overlay window (aka COW) to the
cache.
Yet the X11 requests to get and release the COW may trigger XErrors that
we ought to ignore otherwise the client will abort.
Fixes: #3715
If cairo is a subproject, it's not necessarily installed when gtk
is built. In the source tree, cairo's headers are not stored in
a directory called 'cairo'.
We were calling _gdk_surface_update_size() every frame, even if the
window size didn't change. This would cause us to discard all cached
buffers and redraw the whole screen.
This was BAD.
Whenever we communicate targets, we need to the union, otherwise
we don't tell the other side about our serialization. This makes
drops of images from gtk4-icon-browser to gimp and libreoffice
succeed in transferring data.
Fixes: #3654
When creating the output stream for a drop, we must
pass the mimetypes we support, otherwise the picking
of the right handler does not work.
Fixes: #3652
On x11 toplevel layout is not created before toplevel
is presented, but GTK tries to update it on idle
which leads to a crash due to accessing property
of undefined object. Treat soon to be created layout
as a layout with default values upon creation (resizable).
Depending on the input driver, we will get XI_Motion based scroll
events for regular mouse wheels. These are intended to be handled
as discrete scroll, so detect smooth scroll events that move by
exactly 1.0 in either direction.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/3459
When being fullscreen, and wanting to unfullscreen but not caring about
whether to go unmaximized or maximized (as this information is lost), if
the GdkToplevelLayout represents the full intended state, we won't be
able to do the right thing.
To avoid this issue, make the GdkToplevelLayout API intend based, where
if one e.g. doesn't call gdk_toplevel_set_maximized() with anything, the
backend will not attempt to change the maximized state.
This means we can also remove the old 'initially_maximized' and
'initially_fullscreen' fields from the private GtkWindow struct, as we
only deal with intents now.
It was used by all surfaces to track 'is-mapped', but still part of the
GdkToplevelState, and is now replaced with a separate boolean in the
GdkSurface structure.
It also caused issues when a widget was unmapped, and due to that
unmapped a popover which hid its corresponding surface. When this
surface was hidden, it emitted a state change event, which would then go
back into GTK and queue a resize on popover widget, which would travel
back down to the widget that was originally unmapped, causing confusino
when doing future allocations.
To summarize, one should not hide widgets during allocation, and to
avoid this, make this new is-mapped boolean asynchronous when hiding a
surface, meaning the notification event for the changed mapped state
will be emitted in an idle callback. This avoids the above described
reentry issue.
This will sometimes mean a frame is skipped if a resize was requested
during the update phase of the frame dispatch. Not doing so can cause
trying to allocate a window smaller than the minimum size of the widget.
If compute_size() returns TRUE, the layout will not be propagated to
GTK. This will be used by the X11 backend to queue asynchronous resizes
that shouldn't yet allocate in GTK.
This removes the gdk_surface_set_shadow_width() function and related
vfuncs. The point here is that the shadow width and surface size can now
be communicated to GDK atomically, meaning it's possible to avoid
intermediate stages where the surface size includes the shadow, but
without the shadow width set, or the other way around.
This follows the trail of the Wayland backend in that GdkSurface changes
happen during the layout phase, and that a GDK_CONFIGURE no longer being
used to communicate the size changes of a surface; this now also uses
the layout signal on the GdkSurface.
Reading the comment, it seems to be related being a window manager
decoration utility; this is not something GTK4 aims to handle, just drop
support for this.
The plan is to concencrate size computations as part of the frame clock
dispatch, meaning we shouldn't do it synchronously in the present()
function.
Still, in Wayland, and maybe elsewhere, it is done in the present()
function, e.g. when no state change was made, but this will eventually
be changed.
GTK will not up front know how to correctly calculate a size, since it
will not be able to reliably predict the constraints that may exist
where it will be mapped.
Thus, to handle this, calculate the size of the toplevel by having GDK
emitting a signal called 'compute-size' that will contain information
needed for computing a toplevel window size.
This signal may be emitted at any time, e.g. during
gdk_toplevel_present(), or spontaneously if constraints change.
This also drops the max size from the toplevel layout, while moving the
min size from the toplevel layout struct to the struct passed via the
signal,
This needs changes to a test case where we make sure we process
GDK_CONFIGURE etc, which means we also needs to show the window and
process all pending events in the test-focus-chain test case.
It's not a portable API, so remove it. The corresponding backend
specific functions are still available, if they were implemented, e.g.
gdk_macos_monitor_get_workarea() and gdk_x11_monitor_get_workarea().
Make GdkEvents hold a single GdkDevice. This device is closer to
the logical device conceptually, although it must be sufficient for
device checks (i.e. GdkInputSource), which makes it similar to the
physical devices.
Make the logical devices have a more accurate GdkInputSource where
needed, and conflate the event devices altogether.
Looking at the xf86-input-wacom driver code, this is not even a thing
anymore. Drop this device type, in modern days there's
GDK_DEVICE_TOOL_TYPE_MOUSE for this.
Not all compositors support _NET_WM_FRAME_DRAWN. In cases
where the compositor doesn't support _NET_WM_FRAME_DRAWN we don't
need to do all the fancy damage tracking and fence watching.
Furthermore, if the compositor doesn't support _NET_WM_FRAME_DRAWN,
it's possible that one frame will start before the previous frame has
made it through the pipeline, leading to a blown assertion.
This commit side-steps the unnecessary code and associated assertion
when _NET_WM_FRAME_DRAWN isn't supported.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2927
If we create an implicit grab on a surface, leave the surface, and
release the button, we would get 2 XI_Leave events, one with mode
XINotifyNormal when the pointer leaves the surface, and another with
mode XINotifyUngrab when the button is released.
Meanwhile, the upper layers rely on crossing events being paired,
and particularly in no crossing event being sent until the implicit
grab is dismissed (either by releasing it, or via more pervasive
grabs).
Ignoring the set of XINotifyNormal events while an implicit grab
is active adapts the X11 backend to this behavior. If the grab were
released or taken away by another grab, a crossing event with one
of the other XINotify*Grab/XINotify*Ungrab will be generated.
Fixes: https://gitlab.gnome.org/GNOME/gtk/-/issues/2879
Since commit 972134abe4 a frame getting
drawn has three states (with the vendor nvidia driver at least):
1. drawn by gtk waiting on the GPU
2. drawn by GPU waiting on the compositor
3. drawn by compositor
Those three states are encoded in two flags: frame_pending and
frame_still_painting.
frame_pending means step 1 is done, but step 2 and 3 are still
in progress. frame_still_painting means step 2 is still in progress.
After step 1 is finished the surface is frozen until step 3 is finished.
When the compositor notifies gtk it's done with step 3, with a
_NET_WM_FRAME_DRAWN client message, the toolkit thaws the surface to
allow the next frame to proceed.
The compositor sometimes sends gtk a _NET_WM_FRAME_DRAWN client message
between steps 1 and 2. This message should be ignored because it's not
a reply to the current frame.
Unfortunately, gtk currently assumes if it gets a _NET_WM_FRAME_DRAWN
client message while waiting for step 2 that it's actually at step 3,
and proceeds to draw a new frame while the existing frame is still
pending, leading to a blown assertion.
This commit addresses the problem by ignoring _NET_WM_FRAME_DRAWN
client messages from the compositor unless actually expecting one.
Fixes: #2902
Since commit 972134abe4 we now call
glClientWaitSync for the vendor nvidia driver, to know when a frame
is ready for the compositor to process.
If a surface is hidden while a frame is still being rendered by the GPU,
the surface will never produce the damage event the code relies on to
trigger the call to glClientWaitSync. This leaves the fence dangling,
and the next time the surface is shown, it will start a fresh frame
and blow an assertion since the fence from the last frame is still
hanging around.
This commit ensures a frame gets fully wrapped up before hiding a
surface.
Commit a0f6ff101e made sure that a
context was bound before calling glClientWaitSync, but it doesn't
check that the context shares objects with the context that created
the fence.
This commit does a little more validation before deciding the current
context is good enough.
Since commit 972134abe4 we now call
glClientWaitSync for the vendor nvidia driver, to know when a frame
is ready for the compositor to process.
glClientWaitSync can be called regardless of which context is currently
bound, but if no context is bound at all, it returns 0 without
doing anything.
This commit checks for that edge case, and ensures a context gets
made current in the event no context is already current, before calling
glClientWaitSync.
When given a 0 timeout, glClientWaitSync is only supposed to return one
of three possible values:
- GL_ALREADY_SIGNALED - fence fired
- GL_WAIT_FAILED - there was an error
- GL_TIMEOUT_EXPIRED - fence hasn't fired yet
In addition, it can also return GL_CONDITION_SATISFIED if a non-zero
timeout is passed, and the fence fires while waiting on the timeout.
Since commit 972134abe4 we now call
glClientWaitSync (with a 0 timeout), but one user is reporting it's
returning some value that's not one of the above four.
This commit changes the g_assert to a g_error so we can see what
value is getting returned.
May help with https://gitlab.gnome.org/GNOME/gtk/-/issues/2858
With the vendor provided Nvidia driver there is a small window of time
after drawing to a GL surface before the updates to that surface
can be used by the compositor.
Drawing is already coordinated with the compositor through the frame
synchronization protocol detailed here:
https://fishsoup.net/misc/wm-spec-synchronization.html
Unfortunately, at the moment, GdkX11Surface tells the compositor the
frame is ready immediately after drawing to the surface, not later,
when it's consumable by the compositor.
This commit defers announcing the frame as ready until it's consumable
by the compositor. It does this by listening for the X server to announce
damage events associated with the frame drawing. It tries to find the
right damage event by waiting until fence placed at buffer swap time
signals.
This commit moves some of the end frame sync counter handling
code to subroutines.
It's a minor readability win, but the main motivation is to
make it easier in a subsequent commit to defer updating the
sync counter until a more appropriate time.
commit 14bf58ec5d dropped support
for using the DAMAGE extension since there was no code that
needed it.
We're going to need it again, however, to address an NVidia
vendor driver issue.
This commit does the plumbing to add it back.
This is not used anymore now that surfaces are always toplevel in the
semantics of GdkWindow where child windows were available. We can drop
that and simplify the vfunc just a bit more.
Fixes#2765
On X11, shortcuts inhibition is emulated using a grab on the keyboard.
So if another widget ungrabs the keyboard behind our back (for example
when a popup window is dismissed) that effectively disables the effects
of the shortcut inhibition on the surface and we need to update the
shortcut inhibition status accordingly.
Check for "grab-broken" events on the surface and clear existing
shortcuts inhibition for the matching seat, so that the client can be
notified and may decide to re-enable shortcut inhibition if desired.