This avoids invalidating the size of all widgets when updating CSS
transforms.
In theory, we don't even have to allocate the widget itself, because we
didn't change its size. But we have no way to track that.
Don't leave memory in an unitinialized case when returning FALSE from
gtk_widget_compute_transform().
We both know that people are going to call that function without
checking the return value.
This is the same as the old code since the transformation only contains
teh offset right now, but it will be different later where arbitrary
transformations are possible per widget.
The transform matrix is a translation matrix from the parent's origin to
the widget origin. We will later allow more transformations than just
translations.
Instead of style + rect_of_one_box, pass the new GtkCssBoxes object.
This has the nice side effect that when drawing background + border +
outline, we only compute all the boxes we need once.
Previously, those numbers stored the values relative to the margin box
of the widget. Now they store values relative to the content box,
thereby getting rid of the last remains of weird coordinate systems.
This way, we can compare with literally the previous allocation and the
size will not be influenced by an adjusted allocation.
But more importantly, we can now use the transform/width/height values
for other stuff.
It's not priv->transform (to be turned into a graphene matrix),
priv->width and priv->height.
The numbers are still the same.
The only difference is that unallocated widgets will now have x/y set to
0, not to -1.
The change to make widgets visible by default broke GtkInvisibles
special-cased state handling and that in turn caused picking in
the inspector to break with another recent change.
This change makes the inspector pick button work again.
Without this, disabling a widget that's being hovered and is a child
widget of the widget we're disabling (e.g. the GtkImage child of a
GtkButton) will retain its :hover state even though it should be
insensitive to any sort of input now.
As stated by the documentation, this should be called when a widget gets
updated, but in that case, one can equally use
gtk_widget_trigger_tooltip_query.
Most of the time, the GtkSnapshot objects we create while snapshotting
widgets don't end up containing all that many nodes or states in their
respective node or state stack. This undermines the amortized allocation
behavior of the G(Ptr)Array we use for the stacks. So instead, use the
(until now unused) parent_snapshot GtkSnapshot* passed to
gtk_widget_create_render_node and reuse its node and state stack.
We do not avoid allocating a new GtkSnapshot object, but we do avoid
allocating a ton of G(Ptr)Array objects and we also avoid realloc'ing
their storage.
This is important when the target widget of an event is not the one that
would otherwise receive the gesture. For example, the GtkSwitch
implementation currently attaches a pan gesture to the switch itself,
but the target widget below the pointer might be the switch slider or
label.
See #1465
Instead of instantly invalidating, we now cache the old render node and
do the update in an idle handler.
While that gives us a 1 frame delay, it avoids all the tricky things
like queueing resizes while resizing or queueing draws while drawing.
The only remaining issue (and a *big* one at that) is that a nested
widget paintable will now cause the widget to snapshot its previous
render node when creating a new one. And that one will snapshot its
previous render node, and that one will...
And nothing so far breaks this recursion.
This is to go along with the newly introduced GdkDrop.
This commit includes the necessary updates to the X11, Wayland
and Broadway backends. Other backends have to be updated separately.
If we check it too early, we will not unset priv->draw_neeeded, which
will then cause queue_draw() calls to not have an effect later. And that
causes changes in opacity to not register.
Closes#1180
When deciding whether or not to emulate a press event, we're translating
the last event coordinates and mutating the given event structure
unconditionally.
We should modify the newly created GdkEvent copy, since it's what we're
going to use when emitting the press event.
This avoids mutating a constant GdkEvent and global state, and also
avoids a compiler warning.
We are poking again into the event propagation machinery, which
expects events in toplevel coordinates. Since we can't fetch the
original event back at this point, translate the coordinates
back to the toplevel so the emulated press ends up in the right
place.
https://gitlab.gnome.org/GNOME/gtk/issues/1159Closes: #1159
Instead declare a priv local. We should do this even if we don't remove
the priv pointer from GtkWidget entirely, just to stay consistent with
new code we introduce.
We were mutating the list while iterating over it. This was not a
problem before since remove_controller just set the controller pointer
to NULL instead of actually removing it from the list of controllers.
We can avoid a signal connection per event controller (and the
EventControllerData struct) since every event controller knows the
widget it's attached to.
We no longer set the widget on construction, but instead require an
explicit call to gtk_widget_add_controller().
This way, the reference handling becomes explicit and bindable.
Because gtk_widget_add_controller() is (transfer: full), we don't
even need to unref the controller after adding it.
And we don't need to keep track of it, because controllers get cleaned
up by GtkWidget.
This is the first step towards refactoring how widgets deal with event
controllers.
In the future, the widget will treat controllers the same way it treats
child widgets:
1. The controllers will be created without a widget.
2. There will be gtk_widget_add/remove_controller() functions to add
or remove controllers.
3. The widget will hold a reference to all its controllers.
This way we will ultimately be able to automate controllers with ui
files.
Well, they don't require a redraw of the widget, because the widget
itself didn't change.
They require a redraw of the parent, because that now displays the
widget in a different position.
And this means we can keep the cache of the widget's render node.
My fishbowl numbers are through the roof^W water surface. Vulkan gets
4000 now.
Due to the few type checks in gtk_widget_get_display(), it was the
slowest part of a call to gtk_widget_query_size_for_orientation if the
in case of a cache hit.
If widgets want to clip things, they now need to do it themselves.
By not taking care of clip, we avoid the need to track clip. And by not
tracking clip, we can avoid all unnecessary cache invalidations that we
were doing for render nodes whenever the clip changed.
And when you are scrolling, the clip changes *a lot*.
Instead of connecting to / disconnecting from the frame clock, do it
inside the vfuncs next to changing the priv->realized boolean.
This removes a race between those 2 cases that could cause child
widgets' unrealize handlers to reconnect this widget to the frame clock
because it was still marked as realize when the widget had already
disconnected from the frame clock.
Fixes#168
But in turn, also allow it to work on widgets with their own surface.
This way, we can chain up from everywhere and won't have to export
gtk_widget_set_realized().
Now that queue_draw() isn't restricted to clip anymore, we don't need to
care about clip in the CSS engine either.
We do keep GTK_CSS_AFFECTS_CLIP around though because GtkWindow does
care for the window's size.
Even widgets with an empty allocation may still want to draw stuff.
Examples include shadows or child widgets with negative margins.
Fixes GtkEntry's progressbar not showing up anymore.
Deferring a bit further making those a standalone controller, make
binding activation happen on run_controllers(), so it happens by
default on widgets (unless the key event was consumed earlier)
without the need of a legacy event controller.
Non gesture controllers have no means to collaborate with other
controllers, thus should be considered standalone entities. It makes
no sense to propagate any further if scroll/key controllers handled
the event.
This is a GtkGesture done to deal with stylus events from drawing tablets.
Those have a special number of characteristics that extend a regular
pointer, so it makes sense to wrap that.
Instead of just notifying the inspector of what is going to be rendered,
allow the inspector to modify it.
This way, the inspector can overlay information it deems relevant over
the render node while still having access to what the actual widget
(without the inspector) would paint.
If you want to draw a widget to cairo today, you create a widget
paintable, snapshot it to a render node and then draw the render node to
cairo.
And yes, this is that complicated on purpose. Don't draw widgets to
Cairo.
This is actually not just a mechnaism to protect against too many
signals, but it's also a method to getting those signals at the wrong
time.
For every size/content change, a widget needs to invalidate twice:
Once when it queues a resize/redraw (going valid => invalid) and once
when the new size/content is actually assigned (going invalid => valid).
However, one of those invalidations might be inconvenient for the
listener. GtkImage for example does not like receiving
invalidate-contents signals when new contents are assigned, but is fine
with them when the old ones go invalid. And it will not try to draw the
paintable in between anyway.
So by bypassing the 2nd emission if nothing was changed, we can make
GtkImage happy.
When the clip changes that is passed to a snapshot function, we need to
create eventual cached render nodes because they might not have drawn
their whole area before.
Fixes issues with redrawing when scrolling.
Instead of calling gdk_surface_invalidate_region(), just
gdk_surface_queue_expose() and rely on the renderer computing the diff
from the previous rendering.
It doesn't need to be exported anymore.
As a side effect, the inspector no longer has any information about the
render region, so remove the code that was taking care of that.
Now that we don't clip the created render nodes anymore, we don't have
to compute the clip region beforehand.
So snapshot the render nodes before initializing the renderer.
This requires a bunch of refactorings:
1. Don't pass the current clip region to gtk_widget_snapshot()
so we don't create full widget contents
3. Have a widget->priv->draw_needed that we invalidate on every
queue_draw() call and set on every snapshot()
2. In queue_draw(), walk the widget chain to invalidate the
render nodes of all parents
If you want transparent region, you can just render them transparent.
If you want input shaping, use gdk_surface_input_shape_combine_region().
Also remove gtk_widget_shape_combine_region().
This is an automated change doing these command:
git sed -f g gtk_widget_set_has_window gtk_widget_set_has_surface
git sed -f g gtk_widget_get_has_window gtk_widget_get_has_surface
git sed -f g gtk_widget_set_parent_window gtk_widget_set_parent_surface
git sed -f g gtk_widget_get_parent_window gtk_widget_get_parent_surface
git sed -f g gtk_widget_set_window gtk_widget_set_surface
git sed -f g gtk_widget_get_window gtk_widget_get_surface
git sed -f g gtk_widget_register_window gtk_widget_register_surface
git sed -f g gtk_widget_unregister_window gtk_widget_unregister_surface
git checkout NEWS*
This is an automatic rename of various things related
to the window->surface rename.
Public symbols changed by this is:
GDK_MODE_WINDOW
gdk_device_get_window_at_position
gdk_device_get_window_at_position_double
gdk_device_get_last_event_window
gdk_display_get_monitor_at_window
gdk_drag_context_get_source_window
gdk_drag_context_get_dest_window
gdk_drag_context_get_drag_window
gdk_draw_context_get_window
gdk_drawing_context_get_window
gdk_gl_context_get_window
gdk_synthesize_window_state
gdk_surface_get_window_type
gdk_x11_display_set_window_scale
gsk_renderer_new_for_window
gsk_renderer_get_window
gtk_text_view_buffer_to_window_coords
gtk_tree_view_convert_widget_to_bin_window_coords
gtk_tree_view_convert_tree_to_bin_window_coords
The commands that generated this are:
git sed -f g "GDK window" "GDK surface"
git sed -f g window_impl surface_impl
(cd gdk; git sed -f g impl_window impl_surface)
git sed -f g WINDOW_IMPL SURFACE_IMPL
git sed -f g GDK_MODE_WINDOW GDK_MODE_SURFACE
git sed -f g gdk_draw_context_get_window gdk_draw_context_get_surface
git sed -f g gdk_drawing_context_get_window gdk_drawing_context_get_surface
git sed -f g gdk_gl_context_get_window gdk_gl_context_get_surface
git sed -f g gsk_renderer_get_window gsk_renderer_get_surface
git sed -f g gsk_renderer_new_for_window gsk_renderer_new_for_surface
(cd gdk; git sed -f g window_type surface_type)
git sed -f g gdk_surface_get_window_type gdk_surface_get_surface_type
git sed -f g window_at_position surface_at_position
git sed -f g event_window event_surface
git sed -f g window_coord surface_coord
git sed -f g window_state surface_state
git sed -f g window_cursor surface_cursor
git sed -f g window_scale surface_scale
git sed -f g window_events surface_events
git sed -f g monitor_at_window monitor_at_surface
git sed -f g window_under_pointer surface_under_pointer
(cd gdk; git sed -f g for_window for_surface)
git sed -f g window_anchor surface_anchor
git sed -f g WINDOW_IS_TOPLEVEL SURFACE_IS_TOPLEVEL
git sed -f g native_window native_surface
git sed -f g source_window source_surface
git sed -f g dest_window dest_surface
git sed -f g drag_window drag_surface
git sed -f g input_window input_surface
git checkout NEWS* po-properties po docs/reference/gtk/migrating-3to4.xml
This renames the GdkWindow class and related classes (impl, backend
subclasses) to surface. Additionally it renames related types:
GdkWindowAttr, GdkWindowPaint, GdkWindowWindowClass, GdkWindowType,
GdkWindowTypeHint, GdkWindowHints, GdkWindowState, GdkWindowEdge
This is an automatic conversion using the below commands:
git sed -f g GdkWindowWindowClass GdkSurfaceSurfaceClass
git sed -f g GdkWindow GdkSurface
git sed -f g "gdk_window\([ _\(\),;]\|$\)" "gdk_surface\1" # Avoid hitting gdk_windowing
git sed -f g "GDK_WINDOW\([ _\(]\|$\)" "GDK_SURFACE\1" # Avoid hitting GDK_WINDOWING
git sed "GDK_\([A-Z]*\)IS_WINDOW\([_ (]\|$\)" "GDK_\1IS_SURFACE\2"
git sed GDK_TYPE_WINDOW GDK_TYPE_SURFACE
git sed -f g GdkPointerWindowInfo GdkPointerSurfaceInfo
git sed -f g "BROADWAY_WINDOW" "BROADWAY_SURFACE"
git sed -f g "broadway_window" "broadway_surface"
git sed -f g "BroadwayWindow" "BroadwaySurface"
git sed -f g "WAYLAND_WINDOW" "WAYLAND_SURFACE"
git sed -f g "wayland_window" "wayland_surface"
git sed -f g "WaylandWindow" "WaylandSurface"
git sed -f g "X11_WINDOW" "X11_SURFACE"
git sed -f g "x11_window" "x11_surface"
git sed -f g "X11Window" "X11Surface"
git sed -f g "WIN32_WINDOW" "WIN32_SURFACE"
git sed -f g "win32_window" "win32_surface"
git sed -f g "Win32Window" "Win32Surface"
git sed -f g "QUARTZ_WINDOW" "QUARTZ_SURFACE"
git sed -f g "quartz_window" "quartz_surface"
git sed -f g "QuartzWindow" "QuartzSurface"
git checkout NEWS* po-properties
This allows to override the role declared to the atk stack. For
instance,
<accessibility>
<role type="static"/>
</accessibility>
allows to tell the accessibility stack that a label is just a message in
a message box.
Fixes#109
So we can use that one when translating event coordinates. Also adapt
the widgetfocus demo to ensure this works.
We should probably at some point delete either the int or the double
version.
Remove all the old 2.x and 3.x version annotations.
GTK+ 4 is a new start, and from the perspective of a
GTK+ 4 developer all these APIs have been around since
the beginning.
The result won't be visible anyway. This also prevents problems with
widgets that create some resource the size of the widget, like
GtkGLArea. It also keeps us from snapshotting revealers with
size 0.
The main GDK thread lock is not portable and deprecated.
The only reason why gdk_threads_add_idle() and
gdk_threads_add_idle_full() exist is to allow invoking a callback with
the GDK lock held, in case 3rd party libraries still use the deprecated
gdk_threads_enter()/gdk_threads_leave() API.
Since we're removing the GDK lock, and we're releasing a new major API,
such code cannot exist any more; this means we can use the GLib API for
installing idle callbacks.
https://bugzilla.gnome.org/show_bug.cgi?id=793124
GtkGesture is a GtkEventController. gtk_event_controller_dispose() calls
_gtk_widget_remove_controller(). That NULLs the pointer-to-Controller in
our EventControllerData but does not delete said ECData from our GList.
Subsequently, if that same Widget gets unparent()ed, that method calls
unset_state_flags(), which leads to doing reset_controllers() if we are
insensitive. Now, unlike most most other loops over the GList of ECData,
reset_controllers() does not skip nodes whose pointer-to-Controller is
NULL. So, we call gtk_event_controller_reset(NULL) and get a CRITICAL.
This surfaced in a gtkmm program. The Gesture is destroyed before the
Widget. The Widget then gets dispose()d, which calls unparent()… boom.
I didn’t find an MCVE yet but would hope this logic is correct anyway:
The simplest fix is to make the loop in gtk_widget_reset_controllers()
skip GList nodes with a NULL Controller pointer, like most other such
loops, so we avoid passing the NULL to gtk_event_controller_reset().
In other, live cases, _gtk_widget_run_controllers() loops over the GList
and removes/frees nodes having NULL Controllers, so that should suffice.
But this clearly was not getting a chance to happen in the failing case.
https://bugzilla.gnome.org/show_bug.cgi?id=792624