It's unused. At the same time, rename "begin_paint_region" to
"begin_paint". This will help us clean up how GDK painting works
in the future to allow more creative use of double-buffering.
This is required for the X backend GL integration. If the
window has a height that is not a multiple of the window scale
we can't properly do the y coordinate flipping that GL needs.
Other backends can ignore this and use the default implementation.
https://bugzilla.gnome.org/show_bug.cgi?id=739750
If buffer age is undefined and the updated area is not the whole
window then we use bit-blits instead of swap-buffers to end the
frame.
This allows us to not repaint the entire window unnecessarily if
buffer_age is not supported, like e.g. with DRI2.
This moves the GDK_ALWAYS_USE_GL env var to GDK_GL=always.
It also changes GDK_DEBUG=nogl to GDK_GL=disable, as GDK_DEBUG
is really only about debug loggin.
It also adds some completely new flags:
software-draw-gl:
Always use software fallback for drawing gl content to a cairo_t.
This disables the fastpaths that exist for drawing directly to
a window and instead reads back the pixels into a cairo image
surface.
software-draw-surface:
Always use software fallback for drawing cairo surfaces onto a
gl-using window. This disables e.g. texture-from-pixmap on X11.
software-draw:
Enables both the above.
This is mostly useful for fallback testing.
I suppose if people want finer grained GL ability testing, they can use
Mesa environment variables to tune things.
Its not really reasonable to handle failures to make_current, it
basically only happens if you pass invalid arguments to it, and
thats not something we trap on similar things on the X drawing side.
If GL is not supported that should be handled by the context creation
failing, and anything going wrong after that is essentially a critical
(or an async X error).
We make user facing gl contexts not attached to a surface if possible,
or attached to dummy surfaces. This means nothing can accidentally
read/write to the toplevel back buffer.
This adds the new type GdkGLContext that wraps an OpenGL context for a
particular native window. It also adds support for the gdk paint
machinery to use OpenGL to draw everything. As soon as anyone creates
a GL context for a native window we create a "paint context" for that
GdkWindow and switch to using GL for painting it.
This commit contains only an implementation for X11 (using GLX).
The way painting works is that all client gl contexts draw into
offscreen buffers rather than directly to the back buffer, and the
way something gets onto the window is by using gdk_cairo_draw_from_gl()
to draw part of that buffer onto the draw cairo context.
As a fallback (if we're doing redirected drawing or some effect like a
cairo_push_group()) we read back the gl buffer into memory and composite
using cairo. This means that GL rendering works in all cases, including
rendering to a PDF. However, this is not particularly fast.
In the *typical* case, where we're drawing directly to the window in
the regular paint loop we hit the fast path. The fast path uses opengl
to draw the buffer to the window back buffer, either by blitting or
texturing. Then we track the region that was drawn, and when the draw
ends we paint the normal cairo surface to the window (using
texture-from-pixmap in the X11 case, or texture from cairo image
otherwise) in the regions where there is no gl painted.
There are some complexities wrt layering of gl and cairo areas though:
* We track via gdk_window_mark_paint_from_clip() whenever gtk is
painting over a region we previously rendered with opengl
(flushed_region). This area (needs_blend_region) is blended
rather than copied at the end of the frame.
* If we're drawing a gl texture with alpha we first copy the current
cairo_surface inside the target region to the back buffer before
we blend over it.
These two operations allow us full stacking of transparent gl and cairo
regions.
This is a new function that gets called every time we're drawing
some area in the Gtk paint machinery. It is a no-op right now, but
it will be required later to keep track of what areas which
we previously rendered with GL was overwritten with cairo contents.
First of all we track the current update area during an
update in window->active_update_area. This will be used later
in end_paint to know the damaged area.
Secondly we keep track of old update areas for the last 2
frames. This will later allow us to reuse old framebuffer
contents in double or tripple buffer setups, only painting
what has changed since then.
Parent is guaranteed to not be NULL. It can only ever be NULL for root
windows and root windows cannot be created with gdk_window_new() and
gdk_window_ensure_native() will exit early because they already are
native.
Also, both functions would crash a few lines below where parent gets
dereferenced.
If !owner_events, the pointer window has been usually set to NULL if
the pointer fell outside the grabbing widget, but it was not being
checked that the pointer_window is actually a child of the grab
window, in which case it should be obtained as if ungrabbed.
https://bugzilla.gnome.org/show_bug.cgi?id=735749
When recursing the update area down into native subwindows we forgot
to apply the native window position. This caused us to repaint the
wrong thing in certain cases. I noticed this when playing with the
wip/gdk-gl branch, because it was triggering unnecessary repaints
of the (native window) gl widgets.
Some windows, like GtkWindow and some other apps, set a transparent
background. The guarantee for begin_paint_region is that there should
be a full clear to the specified background color, not a composite
against what was there before.
This fixes repaint artifacts in Wayland and Weston in a better way than
76922c169f.
The resize grip code in GTK+ likes to call gdk_window_raise a lot. The
unfortunate side effect of gdk_window_raise is that it queues an
invalidation on the entire window, even if it's already the topmost
child.
Add a return value to gdk_window_raise_internal, and only queue the
invalidation if the raise had an effect.
Otherwise, a user that calls gdk_window_resize (window, 0, 0); over and
over won't properly fizzle out, and will queue a redraw. Clipped, but
still. These redraws can be chatty on some platforms like Wayland, and
there's no good reason to not avoid them.
This was the case for resize grips.
This reverts commit b875572f2a.
Apps like Abiword, gnumeric and gnome-chess, and toolkits like
ClutterGTK were all using this for various purposes, and this made them
break. Bring back this feature for now.
It still won't work under Wayland.
Apps had quite a bit of difficulty getting used to the new rules.
While we weren't expecting anything too deadly, it seemed that
gnumeric and Abiword both used gdk_cairo_create like this.
If a window both has an impl and its impl_window is of type offscreen,
that must mean that it is the offscreen window, and the impl window is
itself. We can reduce the indirection here and make it more clear.
We removed the parameter from callers and from the implementation, but
not from the signature up top. I didn't notice because the branch I was
working on removed the signature entirely.
This code is only called with the current paint region as its argument.
Instead of having to copy it and do a no-op intersect against itself,
just use the current paint directly.
cairo_surface_create_for_rectangle takes a ref on the parent surface,
so we need to drop ours.
Rename get_window_surface to ref_window_surface to make the code more
clear and to stop this error from happening again.
Previously, each begin_paint_region added to a stack of current paints,
and when end_paint was called, the paint was popped off of the stack and
the surface was composited into the parent paint surface.
However, the code was broken in the case of a backend like Wayland which
didn't keep track of nested calls and simply wiped and returned the
native impl backing surface every time.
Since this feature is flat out unused by GTK+ and we don't want to
really support tricksy things like these for other clients, just remove
the feature. If somebody does call begin_paint_region more than once,
warn and return without doing anything.
Traditionally, the way painting was done in GTK+ was with the
"expose-event" handler, where you'd use GDK methods to do drawing on
your surface. In GTK+ 2.24, we added cairo support with gdk_cairo_create,
so you could paint your graphics with cairo.
Since then, we've added client-side windows, double buffering, the paint
clock, and various other enhancements, and the modern way to do drawing
is to connect to the "draw" signal on GtkWidget, which hands you a
cairo_t. To do double-buffering, the cairo_t we hand you is actually on
a secret surface, not the actual backing store of the window, and when
the draw handler completes we blit it into the main backing store
atomically.
The code to do this is with the APIs gdk_window_begin_paint_region,
which creates the temporary surface, and gdk_window_end_paint which
blits it back into the backing store. GTK+'s implementation of the
"draw" signal uses these APIs.
We've always sort-of supported people calling gdk_cairo_create
"outside" of a begin_paint / end_paint like old times, but then you're
not getting the benefit of double-buffering, and it's harder for GDK to
optimize.
Additionally, newer backends like Mir and Wayland can't actually support
this model, since they're based on double-buffering and swapping buffers
at various points in time. If we hand you a random cairo_t, we have no
idea when is a good time to swap.
Remove support for this.
This is technically a GDK API break: a warning is added in cases where
gdk_cairo_create is called outside of a paint cycle, and the returned
surface is a dummy that won't ever be composited back onto the main
surface. Testing with complex applications like Ardour didn't produce
any warnings.
gtk_widget_set_double_buffered is now deprecated, and we don't support
non-double-buffered widgets. This means that under normal circumstances,
paints are never outside of a begin_paint / end_paint sequence, which
natively-double-buffered backends like Wayland can't possibly support.
When the pointer cursor is updated on CSW, lookup for either a device
cursor, or a global one. It would previously lookup for windows with
a global cursor, and then check if it had a device cursor, which would
skip windows with only device cursors set, and unexpectedly set the
global cursor.
This avoids a bunch of policy problems with deciding how to lay
out the window menu under different WMs.
For now, we use the special event _GTK_SHOW_WINDOW_MENU, but we
hope to have this standardized in wm-spec quite soon, as KDE wants
it as well.
Rendering doesn't do much about clipping drawing operations to the window shape,
although invalidation applies the shape to every window, leaving possibly trails
of "overrendered" content. So ensure the shape portions get invalidated too when
the window is moved/resized.
https://bugzilla.gnome.org/show_bug.cgi?id=729095
It seems that some backends implemented get_root_origin wrong
and returned the client window coordinates, not the frame window
coordinates. Since it's possible to implement generically for all
windows, let's do that instead of having a separate impl vfunc.
The point of GdkWindowImpl::get_root_coords is to translate the passed
in coordinates against the passed-in impl window. For a child window,
in fact, window->abs_x and window->abs_y already track the child
window's coordinates against the impl window.
If we pass in a child window, and backends don't explicitly get the impl
window from it, we'll double-count the child window.
Really, we should *always* be passing impl windows to backends, and
never child windows. However, I'm a bit worried for regressions late
in the cycle if we want to fix up the rest of the callers, like
gdk_window_get_geometry, so I'm only going to touch get_root_coords
for now after careful review of all the backends.
Instead of destroying the surface in the backend if this is
unable to resize, let the core code do it, and do it properly.
Based on a patch by Benjamin Otte.
https://bugzilla.gnome.org/show_bug.cgi?id=725172
The EWMH defines _NET_WM_MOVERESIZE_SIZE_KEYBOARD and
_NET_WM_MOVERESIZE_MOVE_KEYBOARD for operations that are not
initiated by a button-press event. Allow using these by passing
a button of 0 to gdk_window_begin_move/resize_drag.
Since update_windows list is a static variable in GdkWindow.c which
contains pointers to windows which needs to be updated, it can happen
that it contains a pointer to a window even after quit from a gtk_main().
If another gtk_main() is called in the same process it tries to process
windows in the list which leads to a crash.
Correct reference count handling of added windows prevents such applications
from crash.
https://bugzilla.gnome.org/show_bug.cgi?id=711552
And deprecate the X11-specific version of it.
We call this new API _set_shadow_width() and not _set_frame_extents()
because we already have a gdk_window_get_frame_extents() with a
different meaning and different type of value.
https://bugzilla.gnome.org/show_bug.cgi?id=720374
If a motion event handler (or other handler running from the flush-events
phase of the frame clock) recursed the main loop then flushing wouldn't
complete until after the recursed main loop returned, and various aspects
of the state would get out of sync.
To fix this, change flushing of the event queue to simply mark events as
ready to flush, and let normal event delivery handle the rest.
https://bugzilla.gnome.org/show_bug.cgi?id=705176
Setting event compression to false will allow inter-frame
mouse motion events to be delivered, which are necessary
for painting applications to produce smooth strokes.
https://bugzilla.gnome.org/show_bug.cgi?id=702392
Discovered via a crash because b's (dest's) toplevel was NULL;
ensuring that the dest is actually a GdkWindow or setting b to NULL
prevents that path from being taken.
The version of device scale that landed in upstream cairo
master already inherits the device scale in cairo_create_similar,
so no need to do that in gtk anymore.
We've long had double precision mouse coordinates on wayland (e.g.
when rotating a window) but with the new scaling we even have it on
X (and, its also in Xinput2), so convert all the internal mouse/device
position getters to use doubles and add new accessors for the
public APIs that take doubles instead of ints.
If a cairo_surface for a window has a device scale set we need
to respect this when creating a similar window. I.e. we want
to then automatically create a larger window which inherits
the scale from the original.
We also need to calculate a different device_offset if there
is a device_scale set.
Only look at "impl" windows in gdk_window_process_updates_with_mode()
since these are the only ones we care about. This avoids a lot of
unnecessary calls to g_list_copy() and g_object_ref().
We don't want to recurse into children that are clipped, as that is
wasted work. We handle this by moving the empty check to the top
of the function and only using the clipped region everywhere.
We don't track the full clip for each window anymore, as this
is not useful when no windows are opaque. However, we still
need the full clip for the shape, so its calculated manually.
However, it was previously only recalculated when the clip changes
which doesn't correctly handle the case of a sibling geometry changing.
So, instead of doing this directly when geometry changes we just
set a bit in the toplevel whenever some window geometry changes, and
we then handle this in process_updates, updating the shape for all
native windows. This should be ok performance-wise because we don't
expect a lot of native children.
In the ancient X days you could have Xservers that had multiple active windows, like
one truecolor and one 8bit palette. Then most apps ran in 8bpp but a single window
would use truecolor. This is done by specifying different visuals for the windows.
To make this work we ensured that a window with a visual different from its parent
gets a native subwindow, so that X can tell the hardware to do its magic.
These days the only real time we get two different visual is when one is a rgba visual
and the other is not. So, the code to check this doesn't really do anything but
get in the way when someone accidentally manages to not get a rgba visual on
a child window (see bb7054b508). So, to avoid
such errors we just remove the "different visual than parent" check.
We need to send exposes for all native windows, even the ones
without an exposure mask set, because otherwise non-native
children of the native window with an exposure mask will
not be drawn.
This function returns all the children that has a specific user_data set.
This is used a lot in the new GtkWidget drawing code and doing
it this way is faster than getting every child and calling get_user_data
on each (which was a non-neglible part of the profiles). Additionally it
also allows use to use some kind of hashtable to make this operation even
faster if needed in the future.
This lets you register callbacks for when child widgets invalidate
areas of the window read it and/or change it.
For instance, this lets you do rendering effects and keeping offscreen
caches uptodate.
First of all, we now only do paints on native windows, as there is
really no reason anymore to do it for subwindows. Secondly, we
keep track of the paints even for GtkPaintable windows, but for
that case we don't create the offscreen surface, but rather
assume the windowing system does the backing store.
Now that all windows are non-opaque we can simplify the invalidation
a lot. There is no need to clip the invalidate area to child regions,
because we will always redraw everything under all the children.
We only have to handle native childen specially.
We now only do one expose event per native window, so there will
only be one begin/end_paint() call. This means all the work with
implicit paints to combine the paints on a single double buffer
surface is unnecessary, so we can just delete it.
We now consider non-native windows non-opaque, which means any invalid
area in a subwindow will also be invalid all the way up to the nearest
native windows. We take advantage of this by ignoring all expose events
on non-native windows (which typically means just the toplevel) and instead
propagating down the draw() calls to children directly via
gtk_container_propagate_draw.
This is nice as it means we always draw widgets the same way, and it
will let us do some interesting ways in the future.
We also clean up the GtkWidget opacity handling as we can now always
rely on the draing happening via cairo.
We can't really just draw by walking down the widget hierarchy, as
this doesn't get the clipping right (so e.g. widgets doing cairo_paint
may draw outside the expected gdkwindow subarea) nor does it let
us paint window backgrounds.
So, we now do multiple draws for each widget, once for each GdkWindow,
although we still do it on the same base cairo_t that we get for the
toplevel native window. The difference is only the clipping, the rendering
order, and which other widgets we propagate into.
We also collect all the windows of a widget so we can expose them inside
the same opacity group if needed.
NOTE: This change neuters gtk_widget_set_double_buffered for
widgets without native windows. Its impossible to disable
the double buffering in this model.
Since we dropped the move region optimization there is really no need
to try carefully keep track of opaque non-overlapped regions, as we
don't use this information to trigger the optimization anymore.
So, by assuming that all windows are non-opaque we can vastly simplify
the clip region stuff. First of all, we don't need clip_region_with_children,
as each window will need to draw under all children anyway. Secondly, we
don't remove overlapping sibling areas from clip_region, as these are
all non-opaque anyway and we need to draw under them
Finally, we don't need to track the layered region anymore as its
essentially unused. The few times something like it is needed we can
compute it explicitly.
For the case of native children of widgets we may cause a repaint
under native windows that are guaranteed to be opaque, but these
will be clipped by the native child anyway.
This basically neuters gdk_window_move_region, gdk_window_scroll
and gdk_window_move_resize, in that they now never copy any bits but
just invalidate the source and destination regions. This is a performance
loss, but the hope is that the simplifications it later allows will let
us recover this performance loss (which mainly affects scrolling).
If gdk_window_flush_outstanding_moves() creates new update area
we handle this directly in the same draw to avoid flashing.
This mainly affects win32 as X11 does its exposes from moves async.
However, its important for win32 since ScrollDC seems to sometimes
invalidate (and not copy) unexected regions.
http://bugzilla.gnome.org/show_bug.cgi?674051