Compare commits

...

46 Commits

Author SHA1 Message Date
Matthias Clasen b8d7777cc4 xim: Stop using gdk_surface_get_user_data
Use gtk_root_get_for_surface instead.
2019-02-23 22:01:58 -05:00
Matthias Clasen c4edc28542 ime: Stop using gdk_surface_get_user_data
Use gtk_root_get_for_surface instead.
2019-02-23 22:01:50 -05:00
Matthias Clasen b4e0bae7dc Add gtk_root_get_for_surface
This is a replacement for gdk_surface_get_user_data.
2019-02-23 21:56:47 -05:00
Matthias Clasen b82e57fec6 fixup: warn about nothing events 2019-02-23 21:25:10 -05:00
Matthias Clasen 5dbfb18d11 inspector: Make picking work again
This was broken by the change in 01f7f255b5 which
caused the inspector to not get any events anymore.
Revert that part, even though it may be technically
correct.
2019-02-23 18:23:42 -05:00
Matthias Clasen b6893b6d9f Quietly ignore GDK_NOTHING events
These don't have a surface, so we can't deliver
them via the ::event signal. But then, they're
good for nothing anyway.
2019-02-23 17:09:25 -05:00
Matthias Clasen 4001e7645b docs: Refresh the "Q & A" part
Remove references to long-gone API, add some pointers
to more modern alternatives, etc.
2019-02-23 16:08:05 -05:00
Matthias Clasen ac8b192eab gdk: Document surface signals
At least a little bit.
2019-02-23 16:08:05 -05:00
Matthias Clasen fad9468e77 Merge branch 'drawing-model-refresh' into 'master'
doc: Rewrite the drawing model overview

See merge request GNOME/gtk!603
2019-02-23 21:05:35 +00:00
Matthias Clasen 222d310370 doc: Rewrite the drawing model overview
This is a first cut at updating the drawing model chapter
for the way we do things now. It introduces the scene graph and
render nodes, explains node caching and tree diffing, and removes
sections about subwindows.
2019-02-23 15:24:07 -05:00
Benjamin Otte fe95391184 Merge branch 'event-signal' into 'master'
Drop gdk_event_handler_set

See merge request GNOME/gtk!604
2019-02-23 19:33:51 +00:00
Matthias Clasen e16cdb141c Drop gdk_event_handler_set
This is no longer used by GTK.
2019-02-23 14:13:57 -05:00
Matthias Clasen 08badd23cd Drop some dead code
There were some internal uses of GdkEventFunc. Thankfully,
they were unused, so lets just drop them.
2019-02-23 14:13:57 -05:00
Matthias Clasen cc2c39209c Stop using gdk_event_handler_set
We no longer need it.
2019-02-23 14:13:57 -05:00
Matthias Clasen d633beaccd widget: Connect to GdkSurface::event
This lets us handle input events the same way
we do expose events.
2019-02-23 14:13:57 -05:00
Matthias Clasen 23fb77af43 surface: Introduce an ::event signal
This will eventually replace the event handler
as the method to get events over the gdk/gtk
boundary.
2019-02-23 13:45:10 -05:00
Matthias Clasen ccbaec0231 Merge branch 'kill-hierarchy-changed' into 'master'
Kill hierarchy changed

See merge request GNOME/gtk!601
2019-02-23 16:01:16 +00:00
Matthias Clasen 89470ab201 Document that root and unroot must chain up
I overlooked this at first.
2019-02-23 09:43:57 -05:00
Matthias Clasen a3901f2563 Drop the anchored field
We can just change priv->root instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 5dd0863bd7 widget: Drop ::hierarchy-changed
It is no longer used and has been replaced by the
root and unroot vfuncs.
2019-02-23 09:43:57 -05:00
Matthias Clasen 8d93321461 gtk-demo: Stop using ::hierarchy-changed
We can use root and unroot instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 3ccbcf9f55 menu bar: Stop using ::hierarchy-changed
Use the root and unroot vfuncs instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen ef5108c89f label: Stop using ::hierarchy-changed
Use the new root and unroot vfuncs instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 0230a7b1e5 header bar: Stop using ::hierarchy-changed
Use the root and unroot vfuncs instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 55337c588c file chooser: Stop using ::hierarchy-changed
Use the root and unroot vfuncs instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 9e231f6333 popover: Stop using ::hierarchy-changed
Use notify::root instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 3ebf19b783 text handle: Stop using ::hierarchy-changed
Use notify::root instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 9591d40742 xim: Stop using ::hierarchy-changed
Use notify::root instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen de6132a158 ime: Stop using ::hierarchy-changed
We don't need it at all here.
2019-02-23 09:43:57 -05:00
Matthias Clasen ddb52a5b5e drag dest: Stop using ::hierarchy-changed
Use notify::root instead.
2019-02-23 09:43:57 -05:00
Matthias Clasen 47249431e3 inspector: Stop using ::hierarchy-changed
Use the new root and unroot vfuncs instead.
2019-02-23 09:43:57 -05:00
Timm Bäder f9041230c6 gl renderer: Round size up when rendering to a texture
Both the clip we use and the viewport we set should contain the entire
texture size and not potentially clip the last pixel.
2019-02-23 04:50:25 +01:00
Timm Bäder e54ce8f328 treeview: Don't assume search widget is a GtkEntry
Maybe it's a GtkText!
2019-02-23 04:42:01 +01:00
Chun-wei Fan 8d987be673 Merge branch 'wip/fanc999/meson.msvc' into 'master'
GTK+ 4: Improve Windows/Visual Studio build experience

See merge request GNOME/gtk!185
2019-02-23 02:13:35 +00:00
Matthias Clasen 445dca42f5 widget: Remove ::event leftovers
The signal is long gone, no need for this unused
vfunc anymore.
2019-02-22 20:06:06 -05:00
Matthias Clasen c53e9ed6aa search/password entry: Prevent expand leaks
We don't want the entry to expand, we just want
the text to expand inside the box, so explicitly
unset expand flags on the box.
2019-02-22 15:55:05 -05:00
Matthias Clasen 2b9436b279 search entry: Use a GtkEntryAccessible
This preserves the status quo of a11y support
for entry variations.
2019-02-22 15:50:45 -05:00
Matthias Clasen bd99ae3767 entry accessible: Make work with almost-entries
This is not perfect, but gives a quick way to have
an accessible that can be used for password and
search entries.
2019-02-22 15:49:47 -05:00
Matthias Clasen 0e603a6646 search entry: Don't force-create the accessible
We can just set the accessible name when the
accessible is actually needed.
2019-02-22 14:12:52 -05:00
Timm Bäder 9d0e8b85c1 inspector: Fix an uninitialized value warning 2019-02-22 19:22:58 +01:00
Timm Bäder da0bd697b8 gl renderer: Use the matrix node category 2019-02-22 19:08:43 +01:00
Milo Casagrande 3471aac4ef Update Italian translation 2019-02-22 11:05:55 +00:00
Milo Casagrande 593774133f Update Italian translation 2019-02-22 11:05:21 +00:00
Chun-wei Fan 3fa28ffd92 build: Make post-install script a Python script
The existing post-install shell script will most likely not work on
Visual Studio builds as there is normally no shell interpreter installed
on the system where the build is done, but the build is normally done in
a standard Windows cmd.exe console.

Instead, use a Python script so that it will work on the platforms that
Python supports.
2018-12-06 17:07:33 +08:00
Chun-wei Fan 5383d11bb4 modules/media/meson.build: Export needed symbols on MSVC
We need to override _GLIB_EXTERN to export the required symbols for the
GIO module on Visual Studio, so that the media modules can be
successfully loaded.
2018-12-06 17:07:33 +08:00
Chun-wei Fan ed65ab1ba9 meson: Build .rc files for Windows
Build the .rc files for Windows so that one can track the version info
more easily for Windows, as well as giving GTK+ apps a default icon.

Also, move back the manifest embedding for the themed Windows print
dialog back into gtk-win32.rc.body.in, so that we just have one way of
embedding this manifest file, making things easier for ourselves, as
this is supported in the later Visual Studio compilers as well, which is
2013 and later.
2018-12-06 17:07:33 +08:00
48 changed files with 6755 additions and 7511 deletions
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python
import os
import sys
import subprocess
if 'DESTDIR' not in os.environ:
gtk_api_version = sys.argv[1]
gtk_abi_version = sys.argv[2]
gtk_libdir = sys.argv[3].replace('/', os.sep)
gtk_datadir = sys.argv[4].replace('/', os.sep)
gtk_moduledir = os.path.join(gtk_libdir, 'gtk-' + gtk_api_version, gtk_abi_version)
gtk_printmodule_dir = os.path.join(gtk_moduledir, 'printbackends')
gtk_immodule_dir = os.path.join(gtk_moduledir, 'immodules')
print('Compiling GSettings schemas...')
subprocess.call(['glib-compile-schemas',
os.path.join(gtk_datadir, 'glib-2.0', 'schemas')])
print('Updating icon cache...')
subprocess.call(['gtk-update-icon-cache', '-q', '-t' ,'-f',
os.path.join(gtk_datadir, 'icons', 'hicolor')])
print('Updating module cache for print backends...')
if not os.path.isdir(gtk_printmodule_dir):
os.mkdir(gtk_printmodule_dir)
subprocess.call(['gio-querymodules', gtk_printmodule_dir])
print('Updating module cache for input methods...')
if not os.path.isdir(gtk_immodule_dir):
os.mkdir(gtk_immodule_dir)
subprocess.call(['gio-querymodules', gtk_immodule_dir])
-26
View File
@@ -1,26 +0,0 @@
#!/bin/sh
gtk_api_version=$1
gtk_abi_version=$2
gtk_libdir=$3
gtk_datadir=$4
# Package managers set this so we don't need to run
if [ -z "$DESTDIR" ]; then
echo Compiling GSettings schemas...
glib-compile-schemas ${gtk_datadir}/glib-2.0/schemas
echo Updating desktop database...
update-desktop-database -q ${gtk_datadir}/applications
echo Updating icon cache...
gtk-update-icon-cache -q -t -f ${gtk_datadir}/icons/hicolor
echo Updating module cache for print backends...
mkdir -p ${gtk_libdir}/gtk-4.0/4.0.0/printbackends
gio-querymodules ${gtk_libdir}/gtk-4.0/4.0.0/printbackends
echo Updating module cache for input methods...
mkdir -p ${gtk_libdir}/gtk-4.0/4.0.0/immodules
gio-querymodules ${gtk_libdir}/gtk-4.0/4.0.0/immodules
fi
+23 -15
View File
@@ -171,8 +171,24 @@ on_pad_knob_change (GSimpleAction *action,
}
static void
drawing_area_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
drawing_area_unroot (GtkWidget *widget)
{
DrawingArea *area = (DrawingArea *) widget;
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
if (area->pad_controller)
{
gtk_widget_remove_controller (toplevel, GTK_EVENT_CONTROLLER (area->pad_controller));
area->pad_controller = NULL;
}
GTK_WIDGET_CLASS (drawing_area_parent_class)->unroot (widget);
}
static void
drawing_area_root (GtkWidget *widget)
{
DrawingArea *area = (DrawingArea *) widget;
GSimpleActionGroup *action_group;
@@ -180,20 +196,12 @@ drawing_area_hierarchy_changed (GtkWidget *widget,
GtkWidget *toplevel;
gint i;
if (previous_toplevel && area->pad_controller)
{
gtk_widget_remove_controller (previous_toplevel,
GTK_EVENT_CONTROLLER (area->pad_controller));
area->pad_controller = NULL;
}
GTK_WIDGET_CLASS (drawing_area_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (area));
if (!GTK_IS_WINDOW (toplevel))
return;
action_group = g_simple_action_group_new ();
area->pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (action_group),
NULL);
area->pad_controller = gtk_pad_controller_new (G_ACTION_GROUP (action_group), NULL);
for (i = 0; i < G_N_ELEMENTS (pad_actions); i++)
{
@@ -220,8 +228,7 @@ drawing_area_hierarchy_changed (GtkWidget *widget,
gtk_pad_controller_set_action_entries (area->pad_controller, pad_actions,
G_N_ELEMENTS (pad_actions));
gtk_widget_add_controller (toplevel,
GTK_EVENT_CONTROLLER (area->pad_controller));
gtk_widget_add_controller (toplevel, GTK_EVENT_CONTROLLER (area->pad_controller));
}
static void
@@ -233,7 +240,8 @@ drawing_area_class_init (DrawingAreaClass *klass)
widget_class->snapshot = drawing_area_snapshot;
widget_class->map = drawing_area_map;
widget_class->unmap = drawing_area_unmap;
widget_class->hierarchy_changed = drawing_area_hierarchy_changed;
widget_class->root = drawing_area_root;
widget_class->unroot = drawing_area_unroot;
area_signals[COLOR_SET] =
g_signal_new ("color-set",
-3
View File
@@ -662,9 +662,6 @@ gdk_event_get_touchpad_gesture_n_fingers
gdk_event_get_touchpad_gesture_phase
gdk_event_get_touchpad_scale
gdk_event_is_sent
<SUBSECTION>
gdk_event_handler_set
GdkEventFunc
<SUBSECTION>
gdk_get_show_events
+89 -206
View File
@@ -26,56 +26,42 @@
widgets and windows, you should read this chapter; this will be
useful to know if you decide to implement your own widgets. This
chapter will also clarify the reasons behind the ways certain
things are done in GTK; for example, why you cannot change the
background color of all widgets with the same method.
things are done in GTK.
</para>
<refsect2 id="drawing model windows">
<title>Windows and events</title>
<para>
Programs that run in a windowing system generally create
rectangular regions in the screen called
<firstterm>windows</firstterm>. Traditional windowing systems
do not automatically save the graphical content of windows, and
instead ask client programs to repaint those windows whenever it
is needed. For example, if a window that is stacked below other
windows gets raised to the top, then a client program has to
repaint the area that was previously obscured. When the
windowing system asks a client program to redraw part of a
window, it sends an <firstterm>exposure event</firstterm> to the
program for that window.
Applications that use a windowing system generally create
rectangular regions in the screen called <firstterm>surfaces</firstterm>
(GTK is following the Wayland terminology, other windowing systems
such as X11 may call these <firstterm>windows</firstterm>).
Traditional windowing systems do not automatically save the
graphical content of surfaces, and instead ask applications to
provide new content whenever it is needed.
For example, if a window that is stacked below other
windows gets raised to the top, then the application has to
repaint it, so the previously obscured area can be shown.
When the windowing system asks an application to redraw
a window, it sends an <firstterm>frame event</firstterm>
(<firstterm>expose event</firstterm> in X11 terminology)
for that window.
</para>
<para>
Each GTK toplevel window or dialog is associated with a
windowing system surface. Child widgets such as buttons or
entries don't have their own surface; they use the surface
of their toplevel.
</para>
<para>
Here, "windows" means "rectangular regions with automatic
clipping", instead of "toplevel application windows". Most
windowing systems support nested windows, where the contents of
child windows get clipped by the boundaries of their parents.
Although GTK and GDK in particular may run on a windowing
system with no such notion of nested windows, GDK presents the
illusion of being under such a system. A toplevel window may
contain many subwindows and sub-subwindows, for example, one for
the menu bar, one for the document area, one for each scrollbar,
and one for the status bar. In addition, controls that receive
user input, such as clickable buttons, are likely to have their
own subwindows as well.
</para>
<para>
In practice, most windows in modern GTK application are client-side
constructs. Only few windows (in particular toplevel windows) are
<emphasis>native</emphasis>, which means that they represent a
window from the underlying windowing system on which GTK is running.
For example, on X11 it corresponds to a <type>Window</type>; on Win32,
it corresponds to a <type>HANDLE</type>.
</para>
<para>
Generally, the drawing cycle begins when GTK receives an
exposure event from the underlying windowing system: if the
Generally, the drawing cycle begins when GTK receives
a frame event from the underlying windowing system: if the
user drags a window over another one, the windowing system will
tell the underlying window that it needs to repaint itself. The
tell the underlying surface that it needs to repaint itself. The
drawing cycle can also be initiated when a widget itself decides
that it needs to update its display. For example, when the user
types a character in a <link
@@ -85,13 +71,10 @@
</para>
<para>
The windowing system generates events for native windows. The GDK
interface to the windowing system translates such native events into
<link linkend="GdkEvent"><structname>GdkEvent</structname></link>
structures and sends them on to the GTK layer. In turn, the GTK layer
finds the widget that corresponds to a particular
<classname>GdkSurface</classname> and emits the corresponding event
signals on that widget.
The windowing system generates frame events for surfaces. The GDK
interface to the windowing system translates such events into
emissions of the #GtkSurface::render signal on the affected surfaces.
The GTK toplevel window connects to that signal, and reacts appropriately.
</para>
<para>
@@ -112,8 +95,13 @@
it does. On top of this GTK has a frame clock that gives a
“pulse” to the application. This clock beats at a steady rate,
which is tied to the framerate of the output (this is synced to
the monitor via the window manager/compositor). The clock has
several phases:
the monitor via the window manager/compositor). A typical
refresh rate is 60 frames per second, so a new “pulse” happens
roughly every 16 milliseconds.
</para>
<para>
The clock has several phases:
<itemizedlist>
<listitem><para>Events</para></listitem>
<listitem><para>Update</para></listitem>
@@ -125,24 +113,24 @@
</para>
<para>
The Events phase is a long stretch of time between each
redraw where we get input events from the user and other events
The Events phase is a stretch of time between each redraw where
GTK processes input events from the user and other events
(like e.g. network I/O). Some events, like mouse motion are
compressed so that we only get a single mouse motion event per
clock cycle.
compressed so that only a single mouse motion event per clock
cycle needs to be handled.
</para>
<para>
Once the Events phase is over we pause all external events and
run the redraw loop. First is the Update phase, where all
Once the Events phase is over, external events are paused and
the redraw loop is run. First is the Update phase, where all
animations are run to calculate the new state based on the
estimated time the next frame will be visible (available via
the frame clock). This often involves geometry changes which
drives the next phase, Layout. If there are any changes in
widget size requirements we calculate a new layout for the
widget hierarchy (i.e. we assign sizes and positions). Then
we go to the Paint phase where we redraw the regions of the
window that need redrawing.
drive the next phase, Layout. If there are any changes in
widget size requirements the new layout is calculated for the
widget hierarchy (i.e. sizes and positions for all widgets are
determined). Then comes the Paint phase, where we redraw the
regions of the window that need redrawing.
</para>
<para>
@@ -184,162 +172,57 @@
</para>
</refsect2>
<refsect2 id="scene-graph">
<title>The scene graph</title>
<para>
The first step in “drawing” a window is that GTK creates
<firstterm>render nodes</firstterm> for all the widgets
in the window. The render nodes are combined into a tree
that you can think of as a <firstterm>scene graph</firstterm>
describing your window contents.
</para>
<para>
Render nodes belong to the GSK layer, and there are various kinds
of them, for the various kinds of drawing primitives you are likely
to need when translating widget content and CSS styling. Typical
examples are text nodes, gradient nodes, texture nodes or clip nodes.
<para>
<para>
In the past, all drawing in GTK happened via cairo. It is still possible
to use cairo for drawing your custom widget contents, by using a cairo
render node.
</para>
</para>
A GSK <firstterm>renderer</firstterm> takes these render nodes, transforms
them into rendering commands for the drawing API it targets, and arranges
for the resulting drawing to be associated with the right surface. GSK has
renderers for OpenGL, Vulkan and cairo.
</para>
</refsect2>
<refsect2 id="hierarchical-drawing">
<title>Hierarchical drawing</title>
<para>
During the Paint phase we will send a single expose event to
the toplevel window. The event handler will create a cairo
context for the window and emit a GtkWidget::draw() signal
on it, which will propagate down the entire widget hierarchy
in back-to-front order, using the clipping and transform of
the cairo context. This lets each widget draw its content at
the right place and time, correctly handling things like
partial transparencies and overlapping widgets.
During the Paint phase we will send a single ::render signal the toplevel
window. The signal handler will create a snapshot object (which is a
helper for creating a scene graph) and emit a GtkWidget::snapshot() signal,
which will propagate down the entire widget hierarchy. This lets each widget
snapshot its content at the right place and time, correctly handling things
like partial transparencies and overlapping widgets.
</para>
<para>
When generating the event, GDK also sets up double buffering to
avoid the flickering that would result from each widget drawing
itself in turn. <xref linkend="double-buffering"/> describes
the double buffering mechanism in detail.
</para>
<para>
Normally, there is only a single cairo context which is used in
the entire repaint, rather than one per GdkSurface. This means you
have to respect (and not reset) existing clip and transformations
set on it.
</para>
<para>
Most widgets, including those that create their own GdkSurfaces have
a transparent background, so they draw on top of whatever widgets
are below them. This was not the case in GTK 2 where the theme set
the background of most widgets to the default background color. (In
fact, transparent GdkSurfaces used to be impossible.)
</para>
<para>
The whole rendering hierarchy is captured in the call stack, rather
than having multiple separate draw emissions, so you can use effects
like e.g. cairo_push/pop_group() which will affect all the widgets
below you in the hierarchy. This makes it possible to have e.g.
partially transparent containers.
To avoid excessive work when generating scene graphs, GTK caches render nodes.
GtkWidget keeps a reference to its render node (which in turn, will refer to
the render nodes of children, and grandchildren, and so on), and will reuse
that node during the Paint phase. Invalidating a widget (e.g. by calling
gtk_widget_queue_draw) discards the cached render node, forcing GTK to
regenerate it the next time it needs to snapshot the widget.
</para>
</refsect2>
<refsect2 id="scrolling drawing model">
<title>Scrolling</title>
<para>
Traditionally, GTK has used self-copy operations to implement
scrolling with native windows. With transparent backgrounds, this
no longer works. Instead, we just mark the entire affected area for
repainting when these operations are used. This allows (partially)
transparent backgrounds, and it also more closely models modern
hardware where self-copy operations are problematic (they break the
rendering pipeline).
</para>
</refsect2>
</refsect1>
<refsect1 id="double-buffering">
<title>Double buffering</title>
<para>
If each of the drawing calls made by each subwidget's
<literal>draw</literal> handler were sent directly to the
windowing system, flicker could result. This is because areas may get
redrawn repeatedly: the background, then decorative frames, then text
labels, etc. To avoid flicker, GTK employs a <firstterm>double
buffering</firstterm> system at the GDK level. Widgets normally don't
know that they are drawing to an off-screen buffer; they just issue their
normal drawing commands, and the buffer gets sent to the windowing system
when all drawing operations are done.
</para>
<para>
Two basic functions in GDK form the core of the double-buffering
mechanism: <link
linkend="gdk_surface_begin_paint_region"><function>gdk_surface_begin_paint_region()</function></link>
and <link
linkend="gdk_surface_end_paint"><function>gdk_surface_end_paint()</function></link>.
The first function tells a <classname>GdkSurface</classname> to
create a temporary off-screen buffer for drawing. All
subsequent drawing operations to this window get automatically
redirected to that buffer. The second function actually paints
the buffer onto the on-screen window, and frees the buffer.
</para>
<refsect2 id="automatic-double-buffering">
<title>Automatic double buffering</title>
<para>
It would be inconvenient for all widgets to call
<function>gdk_surface_begin_paint_region()</function> and
<function>gdk_surface_end_paint()</function> at the beginning
and end of their draw handlers.
</para>
<para>
To make this easier, GTK normally calls
<function>gdk_surface_begin_paint_region()</function>
before emitting the #GtkWidget::draw signal, and
then it calls <function>gdk_surface_end_paint()</function>
after the signal has been emitted. This is convenient for
most widgets, as they do not need to worry about creating
their own temporary drawing buffers or about calling those
functions.
</para>
<para>
However, some widgets may prefer to disable this kind of
automatic double buffering and do things on their own.
To do this, call the
<function>gtk_widget_set_double_buffered()</function>
function in your widget's constructor. Double buffering
can only be turned off for widgets that have a native
window.
</para>
<example id="disabling-double-buffering">
<title>Disabling automatic double buffering</title>
<programlisting>
static void
my_widget_init (MyWidget *widget)
{
...
gtk_widget_set_double_buffered (widget, FALSE);
...
}
</programlisting>
</example>
<para>
When is it convenient to disable double buffering? Generally,
this is the case only if your widget gets drawn in such a way
that the different drawing operations do not overlap each
other. For example, this may be the case for a simple image
viewer: it can just draw the image in a single operation.
This would <emphasis>not</emphasis> be the case with a word
processor, since it will need to draw and over-draw the page's
background, then the background for highlighted text, and then
the text itself.
</para>
<para>
Even if you turn off double buffering on a widget, you
can still call
<function>gdk_surface_begin_paint_region()</function> and
<function>gdk_surface_end_paint()</function> by hand to use
temporary drawing buffers.
</para>
</refsect2>
</refsect1>
</refentry>
+51 -72
View File
@@ -47,8 +47,7 @@ this reference manual for details.
<qandaentry>
<question><para>
Where can I get help with GTK, submit a bug report, or make a feature
request?
Where can I get help with GTK, submit a bug report, or make a feature request?
</para></question>
<answer>
@@ -63,13 +62,14 @@ See the <link linkend="gtk-resources">documentation on this topic</link>.
<qandaentry>
<question><para>How do I port from one GTK
version to another?</para></question>
<question><para>
How do I port from one GTK version to another?
</para></question>
<answer>
<para>
See <xref linkend="gtk-migrating-2-to-3"/>.
See <xref linkend="migrating"/>.
You may also find useful information in the documentation for
specific widgets and functions.
</para>
@@ -88,8 +88,7 @@ against the documentation.
<qandaentry>
<question><para>
How does memory management work in GTK? Should I free data returned
from functions?
How does memory management work in GTK? Should I free data returned from functions?
</para></question>
<answer>
@@ -528,10 +527,9 @@ the call away if it appears that the value is not being used.
</para>
<para>
A common workaround for this problem is to store the result in a volatile
variable, which keeps the compiler from optimizing the call away.
GLib provides the g_type_ensure() function to work around this problem.
<informalexample><programlisting>
volatile GType dummy = GTK_TYPE_BLAH;
g_type_ensure (GTK_TYPE_BLAH);
</programlisting></informalexample>
</para>
</answer>
@@ -546,32 +544,9 @@ How do I create a transparent toplevel window ?
<answer>
<para>
To make a window transparent, it needs to use a visual which supports that.
This is done by getting the RGBA visual of the screen with
gdk_screen_get_rgba_visual() and setting it on the window. Note that
gdk_screen_get_rgba_visual() will return %NULL if transparent windows
are not supported on the screen, you should fall back to
gdk_screen_get_system_visual() in that case. Additionally, note that this
will change from screen to screen, so it needs to be repeated whenever the
window is moved to a different screen.
<informalexample><programlisting>
GdkVisual *visual;
visual = gdk_screen_get_rgba_visual (screen);
if (visual == NULL)
visual = gdk_screen_get_system_visual (screen);
gtk_widget_set_visual (GTK_WIDGET (window), visual);
</programlisting></informalexample>
To fill the alpha channel on the window simply use cairos
RGBA drawing capabilities.
</para>
<para>
Note that the presence of an RGBA visual is no guarantee that the
window will actually appear transparent on screen. On X11, this
requires a compositing manager to be running. See
gdk_display_is_composited() for a way to find out if the alpha
channel will be respected.
Any toplevel window can be transparent.
It is just a matter of setting a transparent background
in the CSS style for it.
</para>
</answer>
</qandaentry>
@@ -587,9 +562,19 @@ channel will be respected.
<answer>
<para>
See <link linkend="TreeWidget">tree widget overview</link> &mdash; you
should use the #GtkTreeView widget. (A list is just a tree with no branches,
so the tree widget is used for lists as well).
This question has different answers, depending on the size of the dataset
and the required formatting flexibility.
</para>
<para>
If you want to display a large amount of data in a uniform way, your
best option is a #GtkTreeView widget. See <link linkend="TreeWidget">tree
widget overview</link>. A list is just a tree with no branches, so the treeview
widget is used for lists as well.
</para>
<para>
If you want to display a small amount of items, but need flexible formatting
and widgetry inside the list, then you probably want to use a #GtkListBox,
which uses regular widgets for display.
</para>
</answer>
</qandaentry>
@@ -620,7 +605,11 @@ single-line text entry, see #GtkEntry.
<answer>
<para>
#GtkImage can display images in just about any format GTK understands.
GTK has two widgets that are dedicated to displaying images. #GtkImage, for
small, fixed-size icons and #GtkPicture for content images.
</para>
<para>
Both can display images in just about any format GTK understands.
You can also use #GtkDrawingArea if you need to do something more complex,
such as draw text or graphics over the top of the image.
</para>
@@ -653,9 +642,10 @@ How do I change the color of a widget?
</para></question>
<answer><para>
See gtk_widget_override_color() and gtk_widget_override_background_color().
You can also change the appearance of a widget by installing a
custom style provider, see gtk_style_context_add_provider().
The background color of a widget is determined by the CSS style that applies
to it. To change that, you can set style classes on the widget, and provide
custom CSS to change the appearance. Such CSS can be loaded with
gtk_css_provider_load_from_file() and its variants. See gtk_style_context_add_provider().
</para></answer>
</qandaentry>
@@ -665,16 +655,6 @@ How do I change the font of a widget?
</para></question>
<answer><para>
This has several possible answers, depending on what exactly you want to
achieve. One option is gtk_widget_override_font().
<informalexample><programlisting>
PangoFontDesc *font_desc = pango_font_description_new (<!-- -->);
pango_font_description_set_size (font_desc, 40);
gtk_widget_override_font (widget, font);
pango_font_description_free (font_desc);
</programlisting></informalexample>
</para>
<para>
If you want to make the text of a label larger, you can use
gtk_label_set_markup():
<informalexample><programlisting>
@@ -939,32 +919,28 @@ How do I use cairo to draw in GTK applications ?
</para></question>
<answer><para>
The #GtkWidget::draw signal gets a ready-to-use cairo context
as parameter that you should use.
</para>
<para>
All drawing in GTK is normally done in a draw handler, and GTK
creates a temporary pixmap for double-buffering the drawing.
It is possible to turn off double-buffering, with
gtk_widget_set_double_buffered(), but this is not ideal,
since it can cause some flickering.
Use gtk_snapshot_append_cairo() in your #GtkWidget::snapshot signal handler
to optain a cairo context and draw with that.
</para>
</answer>
</qandaentry>
<qandaentry>
<question><para>
Can I improve the performance of my application by using the
Glitz or GL backend of cairo ?
Can I improve the performance of my application by using another backend
of cairo (such as GL) ?
</para></question>
<answer><para>
No. The GDK X11 backend uses the cairo X backend (and the other
GDK backends use their respective native cairo backends). The
GTK developers believe that the best way to improving the GDK
drawing performance is to optimize the cairo X backend and the
relevant code paths in the X server that is uses (mostly the
Render extension).
No. Most drawing in GTK is not done via cairo anymore (but instead
by the GL or Vulkan renderers of GSK).
</para>
<para>
If you use cairo for drawing your own widgets, gtk_snapshot_append_cairo()
will choose the most appropriate surface type for you.
</para>
<para>
If you are interested in using GL for your own drawing, see #GtkGLArea.
</para></answer>
</qandaentry>
@@ -974,8 +950,11 @@ Can I use cairo to draw on a #GdkPixbuf ?
</para></question>
<answer><para>
No, at least not yet. The cairo image surface does not support the
pixel format used by GdkPixbuf.
No. The cairo image surface does not support the pixel format used by GdkPixbuf.
</para>
<para>
If you need to get cairo drawing into a format that can be displayed efficiently
by GTK, you may want to use an image surface and gdk_memory_texture_new().
</para></answer>
</qandaentry>
-8
View File
@@ -108,14 +108,6 @@
* of deprecated GDK APIs.
*/
typedef struct _GdkPredicate GdkPredicate;
struct _GdkPredicate
{
GdkEventFunc func;
gpointer data;
};
typedef struct _GdkThreadsDispatch GdkThreadsDispatch;
struct _GdkThreadsDispatch
+7 -36
View File
@@ -67,10 +67,6 @@
/* Private variable declarations
*/
static GdkEventFunc _gdk_event_func = NULL; /* Callback for events */
static gpointer _gdk_event_data = NULL;
static GDestroyNotify _gdk_event_notify = NULL;
static void gdk_event_constructed (GObject *object);
static void gdk_event_finalize (GObject *object);
@@ -153,14 +149,16 @@ gdk_event_class_init (GdkEventClass *klass)
void
_gdk_event_emit (GdkEvent *event)
{
if (gdk_event_get_event_type (event) == GDK_NOTHING)
{
g_warning ("Ignoring GDK_NOTHING events; they're good for nothing");
return;
}
if (gdk_drag_handle_source_event (event))
return;
if (gdk_surface_handle_event (event))
return;
if (_gdk_event_func)
(*_gdk_event_func) (event, _gdk_event_data);
gdk_surface_handle_event (event);
}
/*********************************************
@@ -415,33 +413,6 @@ _gdk_event_queue_flush (GdkDisplay *display)
}
}
/**
* gdk_event_handler_set:
* @func: the function to call to handle events from GDK.
* @data: user data to pass to the function.
* @notify: the function to call when the handler function is removed, i.e. when
* gdk_event_handler_set() is called with another event handler.
*
* Sets the function to call to handle all events from GDK.
*
* Note that GTK+ uses this to install its own event handler, so it is
* usually not useful for GTK+ applications. (Although an application
* can call this function then call gtk_main_do_event() to pass
* events to GTK+.)
**/
void
gdk_event_handler_set (GdkEventFunc func,
gpointer data,
GDestroyNotify notify)
{
if (_gdk_event_notify)
(*_gdk_event_notify) (_gdk_event_data);
_gdk_event_func = func;
_gdk_event_data = data;
_gdk_event_notify = notify;
}
/**
* gdk_event_new:
* @type: a #GdkEventType
-17
View File
@@ -125,18 +125,6 @@ typedef struct _GdkEventPadGroupMode GdkEventPadGroupMode;
typedef struct _GdkEventSequence GdkEventSequence;
typedef union _GdkEvent GdkEvent;
/**
* GdkEventFunc:
* @event: the #GdkEvent to process.
* @data: (closure): user data set when the event handler was installed with
* gdk_event_handler_set().
*
* Specifies the type of function passed to gdk_event_handler_set() to
* handle all GDK events.
*/
typedef void (*GdkEventFunc) (GdkEvent *event,
gpointer data);
/**
* GdkEventType:
* @GDK_NOTHING: a special code to indicate a null event.
@@ -446,11 +434,6 @@ gboolean gdk_events_get_center (GdkEvent *event1,
gdouble *x,
gdouble *y);
GDK_AVAILABLE_IN_ALL
void gdk_event_handler_set (GdkEventFunc func,
gpointer data,
GDestroyNotify notify);
GDK_AVAILABLE_IN_ALL
void gdk_event_set_display (GdkEvent *event,
GdkDisplay *display);
+46 -2
View File
@@ -99,6 +99,7 @@ enum {
MOVED_TO_RECT,
SIZE_CHANGED,
RENDER,
EVENT,
LAST_SIGNAL
};
@@ -321,6 +322,14 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
G_TYPE_BOOLEAN,
G_TYPE_BOOLEAN);
/**
* GdkSurface::size-changed:
* @surface: the #GdkSurface
* @width: the new width
* @height: the new height
*
* Emitted when the size of @surface is changed.
*/
signals[SIZE_CHANGED] =
g_signal_new (g_intern_static_string ("size-changed"),
G_OBJECT_CLASS_TYPE (object_class),
@@ -334,6 +343,15 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
G_TYPE_INT,
G_TYPE_INT);
/**
* GdkSurface::render:
* @surface: the #GdkSurface
* @region: the region that needs to be redrawn
*
* Emitted when part of the surface needs to be redrawn.
*
* Returns: %TRUE to indicate that the signal has been handled
*/
signals[RENDER] =
g_signal_new (g_intern_static_string ("render"),
G_OBJECT_CLASS_TYPE (object_class),
@@ -345,6 +363,27 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
G_TYPE_BOOLEAN,
1,
CAIRO_GOBJECT_TYPE_REGION);
/**
* GdkSurface::event:
* @surface: the #GdkSurface
* @event: an input event
*
* Emitted when GDK receives an input event for @surface.
*
* Returns: %TRUE to indicate that the event has been handled
*/
signals[EVENT] =
g_signal_new (g_intern_static_string ("event"),
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_true_handled,
NULL,
NULL,
G_TYPE_BOOLEAN,
1,
GDK_TYPE_EVENT);
}
static void
@@ -5462,12 +5501,17 @@ gdk_synthesize_surface_state (GdkSurface *surface,
gboolean
gdk_surface_handle_event (GdkEvent *event)
{
gboolean handled = FALSE;
if (gdk_event_get_event_type (event) == GDK_CONFIGURE)
{
g_signal_emit (gdk_event_get_surface (event), signals[SIZE_CHANGED], 0,
event->configure.width, event->configure.height);
return TRUE;
handled = TRUE;
}
else
{
g_signal_emit (gdk_event_get_surface (event), signals[EVENT], 0, event, &handled);
}
return FALSE;
return handled;
}
+1
View File
@@ -160,6 +160,7 @@ gdkx11_inc = include_directories('x11')
gdkwayland_inc = include_directories('wayland')
wlinc = include_directories('.')
win32rcinc = include_directories('win32/rc')
gdk_gen_headers = [gdkenum_h, gdkmarshal_h, gdkconfig, gdkversionmacros]
-8
View File
@@ -78,14 +78,6 @@
* ]|
*/
typedef struct _GdkPredicate GdkPredicate;
struct _GdkPredicate
{
GdkEventFunc func;
gpointer data;
};
/* non-GDK previous error handler */
typedef int (*GdkXErrorHandler) (Display *, XErrorEvent *);
static GdkXErrorHandler _gdk_old_error_handler;
+105 -53
View File
@@ -765,64 +765,116 @@ render_transform_node (GskGLRenderer *self,
GskRenderNode *node,
RenderOpBuilder *builder)
{
const float scale = ops_get_scale (builder);
const GskMatrixCategory category = gsk_transform_node_get_category (node);
const graphene_matrix_t *node_transform = gsk_transform_node_peek_transform (node);
GskRenderNode *child = gsk_transform_node_get_child (node);
graphene_matrix_t transform, transformed_mv;
graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
graphene_matrix_translate (&transformed_mv,
&(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
/* We just added the offset to the new modelview matrix, so the following
* cases dont' have to care about builder->dx/dy! */
ops_push_modelview (builder, &transformed_mv);
if (ops_modelview_is_simple (builder) ||
node_supports_transform (child))
switch (category)
{
const float dx = builder->dx;
const float dy = builder->dy;
builder->dx = 0;
builder->dy = 0;
case GSK_MATRIX_CATEGORY_IDENTITY:
gsk_gl_renderer_add_render_ops (self, child, builder);
builder->dx = dx;
builder->dy = dy;
}
else
{
const float min_x = node->bounds.origin.x;
const float min_y = node->bounds.origin.y;
const float max_x = min_x + node->bounds.size.width;
const float max_y = min_y + node->bounds.size.height;
const GskQuadVertex vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
break;
{ { max_x, max_y }, { 1, 0 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
};
int texture_id;
gboolean is_offscreen;
/* For non-trivial transforms, we draw everything on a texture and then
* draw the texture transformed. */
/* TODO: We should compute a modelview containing only the "non-trivial"
* part (e.g. the rotation) and use that. We want to keep the scale
* for the texture.
*/
add_offscreen_ops (self, builder,
&node->bounds,
child,
&texture_id, &is_offscreen,
RESET_CLIP | RESET_OPACITY);
ops_set_texture (builder, texture_id);
ops_set_program (builder, &self->blit_program);
ops_draw (builder, vertex_data);
case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
{
const float dx = graphene_matrix_get_value (node_transform, 3, 0);
const float dy = graphene_matrix_get_value (node_transform, 3, 1);
ops_offset (builder, dx, dy);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_offset (builder, -dx, -dy);
}
break;
case GSK_MATRIX_CATEGORY_2D_AFFINE:
{
const float scale = ops_get_scale (builder);
graphene_matrix_t transform, transformed_mv;
const float dx = builder->dx;
const float dy = builder->dy;
graphene_matrix_init_from_matrix (&transform, node_transform);
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
graphene_matrix_translate (&transformed_mv,
&(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
builder->dx = 0;
builder->dy = 0;
ops_push_modelview (builder, &transformed_mv);
gsk_gl_renderer_add_render_ops (self, child, builder);
ops_pop_modelview (builder);
builder->dx = dx;
builder->dy = dy;
}
break;
case GSK_MATRIX_CATEGORY_UNKNOWN:
case GSK_MATRIX_CATEGORY_ANY:
case GSK_MATRIX_CATEGORY_INVERTIBLE:
default:
{
const float scale = ops_get_scale (builder);
graphene_matrix_t transform, transformed_mv;
const float min_x = child->bounds.origin.x;
const float min_y = child->bounds.origin.y;
const float max_x = min_x + child->bounds.size.width;
const float max_y = min_y + child->bounds.size.height;
int texture_id;
gboolean is_offscreen;
graphene_matrix_init_from_matrix (&transform, node_transform);
graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
graphene_matrix_translate (&transformed_mv,
&(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
ops_push_modelview (builder, &transformed_mv);
/* For non-trivial transforms, we draw everything on a texture and then
* draw the texture transformed. */
/* TODO: We should compute a modelview containing only the "non-trivial"
* part (e.g. the rotation) and use that. We want to keep the scale
* for the texture.
*/
add_offscreen_ops (self, builder,
&child->bounds,
child,
&texture_id, &is_offscreen,
RESET_CLIP | RESET_OPACITY);
ops_set_texture (builder, texture_id);
ops_set_program (builder, &self->blit_program);
if (is_offscreen)
{
const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 1 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
{ { max_x, max_y }, { 1, 0 }, },
{ { min_x, max_y }, { 0, 0 }, },
{ { max_x, min_y }, { 1, 1 }, },
};
ops_draw (builder, offscreen_vertex_data);
}
else
{
const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
{ { min_x, min_y }, { 0, 0 }, },
{ { min_x, max_y }, { 0, 1 }, },
{ { max_x, min_y }, { 1, 0 }, },
{ { max_x, max_y }, { 1, 1 }, },
{ { min_x, max_y }, { 0, 1 }, },
{ { max_x, min_y }, { 1, 0 }, },
};
ops_draw (builder, onscreen_vertex_data);
}
ops_pop_modelview (builder);
}
}
ops_pop_modelview (builder);
}
static inline void
@@ -2406,8 +2458,8 @@ add_offscreen_ops (GskGLRenderer *self,
guint flags)
{
const float scale = ops_get_scale (builder);
const float width = bounds->size.width * scale;
const float height = bounds->size.height * scale;
const float width = ceilf (bounds->size.width * scale);
const float height = ceilf (bounds->size.height * scale);
const float dx = builder->dx;
const float dy = builder->dy;
int render_target;
+119 -92
View File
@@ -26,6 +26,8 @@
#include "gtkpango.h"
#include "gtkentryaccessible.h"
#include "gtkentryprivate.h"
#include "gtksearchentryprivate.h"
#include "gtkpasswordentry.h"
#include "gtktextprivate.h"
#include "gtkcomboboxaccessible.h"
#include "gtkstylecontextprivate.h"
@@ -407,7 +409,7 @@ gtk_entry_accessible_get_attributes (AtkObject *accessible)
GtkWidget *widget;
AtkAttributeSet *attributes;
AtkAttribute *placeholder_text;
const gchar *text;
char *text = NULL;
attributes = ATK_OBJECT_CLASS (gtk_entry_accessible_parent_class)->get_attributes (accessible);
@@ -415,13 +417,15 @@ gtk_entry_accessible_get_attributes (AtkObject *accessible)
if (widget == NULL)
return attributes;
text = gtk_entry_get_placeholder_text (GTK_ENTRY (widget));
if (GTK_IS_ENTRY (widget) || GTK_IS_SEARCH_ENTRY (widget))
g_object_get (widget, "placeholder-text", &text, NULL);
if (text == NULL)
return attributes;
placeholder_text = g_malloc (sizeof (AtkAttribute));
placeholder_text->name = g_strdup ("placeholder-text");
placeholder_text->value = g_strdup (text);
placeholder_text->value = text;
attributes = g_slist_append (attributes, placeholder_text);
@@ -432,7 +436,7 @@ static void
gtk_entry_accessible_initialize (AtkObject *obj,
gpointer data)
{
GtkEntry *entry;
GtkWidget *widget;
GtkEntryAccessible *gtk_entry_accessible;
gint start_pos, end_pos;
@@ -440,19 +444,19 @@ gtk_entry_accessible_initialize (AtkObject *obj,
gtk_entry_accessible = GTK_ENTRY_ACCESSIBLE (obj);
entry = GTK_ENTRY (data);
gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos);
widget = GTK_WIDGET (data);
gtk_editable_get_selection_bounds (GTK_EDITABLE (widget), &start_pos, &end_pos);
gtk_entry_accessible->priv->cursor_position = end_pos;
gtk_entry_accessible->priv->selection_bound = start_pos;
/* Set up signal callbacks */
g_signal_connect_after (entry, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (entry, "delete-text", G_CALLBACK (delete_text_cb), NULL);
g_signal_connect_after (widget, "insert-text", G_CALLBACK (insert_text_cb), NULL);
g_signal_connect (widget, "delete-text", G_CALLBACK (delete_text_cb), NULL);
if (gtk_entry_get_visibility (entry))
obj->role = ATK_ROLE_TEXT;
else
if (GTK_IS_PASSWORD_ENTRY (widget))
obj->role = ATK_ROLE_PASSWORD_TEXT;
else
obj->role = ATK_ROLE_TEXT;
}
static void
@@ -655,19 +659,20 @@ static gint
gtk_entry_accessible_get_n_children (AtkObject* obj)
{
GtkWidget *widget;
GtkEntry *entry;
gint count = 0;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget == NULL)
return 0;
entry = GTK_ENTRY (widget);
if (GTK_IS_ENTRY (widget))
{
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
count++;
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
count++;
}
if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
count++;
if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
count++;
return count;
}
@@ -678,29 +683,29 @@ gtk_entry_accessible_ref_child (AtkObject *obj,
GtkEntryAccessible *accessible = GTK_ENTRY_ACCESSIBLE (obj);
GtkEntryAccessiblePrivate *priv = accessible->priv;
GtkWidget *widget;
GtkEntry *entry;
GtkEntryIconPosition pos;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget == NULL)
return NULL;
entry = GTK_ENTRY (widget);
if (!GTK_IS_ENTRY (widget))
return NULL;
switch (i)
{
case 0:
if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) != GTK_IMAGE_EMPTY)
pos = GTK_ENTRY_ICON_PRIMARY;
else if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
else if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) != GTK_IMAGE_EMPTY)
pos = GTK_ENTRY_ICON_SECONDARY;
else
return NULL;
break;
case 1:
if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY)
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_PRIMARY) == GTK_IMAGE_EMPTY)
return NULL;
if (gtk_entry_get_icon_storage_type (entry, GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
if (gtk_entry_get_icon_storage_type (GTK_ENTRY (widget), GTK_ENTRY_ICON_SECONDARY) == GTK_IMAGE_EMPTY)
return NULL;
pos = GTK_ENTRY_ICON_SECONDARY;
break;
@@ -752,10 +757,8 @@ gtk_entry_accessible_init (GtkEntryAccessible *entry)
entry->priv->selection_bound = 0;
}
static gchar *
gtk_entry_accessible_get_text (AtkText *atk_text,
gint start_pos,
gint end_pos)
static GtkText *
get_text (AtkText *atk_text)
{
GtkWidget *widget;
@@ -763,59 +766,82 @@ gtk_entry_accessible_get_text (AtkText *atk_text,
if (widget == NULL)
return NULL;
return gtk_text_get_display_text (gtk_entry_get_text_widget (GTK_ENTRY (widget)), start_pos, end_pos);
if (GTK_IS_ENTRY (widget))
return gtk_entry_get_text_widget (GTK_ENTRY (widget));
else if (GTK_IS_SEARCH_ENTRY (widget))
return gtk_search_entry_get_text_widget (GTK_SEARCH_ENTRY (widget));
else
return NULL; // FIXME;
}
static gchar *
gtk_entry_accessible_get_text_before_offset (AtkText *text,
gtk_entry_accessible_get_text (AtkText *atk_text,
gint start_pos,
gint end_pos)
{
GtkText *text;
text = get_text (atk_text);
if (text == NULL)
return NULL;
return gtk_text_get_display_text (text, start_pos, end_pos);
}
static gchar *
gtk_entry_accessible_get_text_before_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
GtkWidget *widget;
GtkText *text;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return NULL;
return _gtk_pango_get_text_before (gtk_text_get_layout (gtk_entry_get_text_widget (GTK_ENTRY (widget))),
return _gtk_pango_get_text_before (gtk_text_get_layout (text),
boundary_type, offset,
start_offset, end_offset);
}
static gchar *
gtk_entry_accessible_get_text_at_offset (AtkText *text,
gtk_entry_accessible_get_text_at_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
GtkWidget *widget;
GtkText *text;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return NULL;
return _gtk_pango_get_text_at (gtk_text_get_layout (gtk_entry_get_text_widget (GTK_ENTRY (widget))),
return _gtk_pango_get_text_at (gtk_text_get_layout (text),
boundary_type, offset,
start_offset, end_offset);
}
static gchar *
gtk_entry_accessible_get_text_after_offset (AtkText *text,
gtk_entry_accessible_get_text_after_offset (AtkText *atk_text,
gint offset,
AtkTextBoundary boundary_type,
gint *start_offset,
gint *end_offset)
{
GtkWidget *widget;
GtkText *text;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return NULL;
return _gtk_pango_get_text_after (gtk_text_get_layout (gtk_entry_get_text_widget (GTK_ENTRY (widget))),
return _gtk_pango_get_text_after (gtk_text_get_layout (text),
boundary_type, offset,
start_offset, end_offset);
}
@@ -823,21 +849,22 @@ gtk_entry_accessible_get_text_after_offset (AtkText *text,
static gint
gtk_entry_accessible_get_character_count (AtkText *atk_text)
{
GtkWidget *widget;
gchar *text;
glong char_count;
GtkText *text;
char *display_text;
int char_count;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return 0;
text = gtk_text_get_display_text (gtk_entry_get_text_widget (GTK_ENTRY (widget)), 0, -1);
display_text = gtk_text_get_display_text (text, 0, -1);
char_count = 0;
if (text)
if (display_text)
{
char_count = g_utf8_strlen (text, -1);
g_free (text);
char_count = g_utf8_strlen (display_text, -1);
g_free (display_text);
}
return char_count;
@@ -885,23 +912,24 @@ add_text_attribute (AtkAttributeSet *attributes,
}
static AtkAttributeSet *
gtk_entry_accessible_get_run_attributes (AtkText *text,
gtk_entry_accessible_get_run_attributes (AtkText *atk_text,
gint offset,
gint *start_offset,
gint *end_offset)
{
GtkWidget *widget;
GtkText *text;
AtkAttributeSet *attributes;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return NULL;
attributes = NULL;
attributes = add_text_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
gtk_widget_get_direction (widget));
gtk_widget_get_direction (GTK_WIDGET (text)));
attributes = _gtk_pango_get_run_attributes (attributes,
gtk_text_get_layout (gtk_entry_get_text_widget (GTK_ENTRY (widget))),
gtk_text_get_layout (text),
offset,
start_offset,
end_offset);
@@ -910,28 +938,29 @@ gtk_entry_accessible_get_run_attributes (AtkText *text,
}
static AtkAttributeSet *
gtk_entry_accessible_get_default_attributes (AtkText *text)
gtk_entry_accessible_get_default_attributes (AtkText *atk_text)
{
GtkWidget *widget;
GtkText *text;
AtkAttributeSet *attributes;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
text = get_text (atk_text);
if (text == NULL)
return NULL;
attributes = NULL;
attributes = add_text_attribute (attributes, ATK_TEXT_ATTR_DIRECTION,
gtk_widget_get_direction (widget));
gtk_widget_get_direction (GTK_WIDGET (text)));
attributes = _gtk_pango_get_default_attributes (attributes,
gtk_text_get_layout (gtk_entry_get_text_widget (GTK_ENTRY (widget))));
gtk_text_get_layout (text));
attributes = _gtk_style_context_get_attributes (attributes,
gtk_widget_get_style_context (widget));
gtk_widget_get_style_context (GTK_WIDGET (text)));
return attributes;
}
static void
gtk_entry_accessible_get_character_extents (AtkText *text,
gtk_entry_accessible_get_character_extents (AtkText *atk_text,
gint offset,
gint *x,
gint *y,
@@ -939,8 +968,6 @@ gtk_entry_accessible_get_character_extents (AtkText *text,
gint *height,
AtkCoordType coords)
{
GtkWidget *widget;
GtkEntry *entry;
GtkText *textw;
PangoRectangle char_rect;
gchar *entry_text;
@@ -949,12 +976,10 @@ gtk_entry_accessible_get_character_extents (AtkText *text,
gint x_surface, y_surface;
GtkAllocation allocation;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
if (widget == NULL)
return;
textw = get_text (atk_text);
entry = GTK_ENTRY (widget);
textw = gtk_entry_get_text_widget (entry);
if (textw == NULL)
return;
gtk_text_get_layout_offsets (textw, &x_layout, &y_layout);
entry_text = gtk_text_get_display_text (textw, 0, -1);
@@ -964,9 +989,9 @@ gtk_entry_accessible_get_character_extents (AtkText *text,
pango_layout_index_to_pos (gtk_text_get_layout (textw), index, &char_rect);
pango_extents_to_pixels (&char_rect, NULL);
gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (GTK_WIDGET (textw), &allocation);
surface = gtk_widget_get_surface (widget);
surface = gtk_widget_get_surface (GTK_WIDGET (textw));
gdk_surface_get_origin (surface, &x_surface, &y_surface);
*x = x_surface + allocation.x + x_layout + char_rect.x;
@@ -990,8 +1015,6 @@ gtk_entry_accessible_get_offset_at_point (AtkText *atk_text,
gint y,
AtkCoordType coords)
{
GtkWidget *widget;
GtkEntry *entry;
GtkText *textw;
gchar *text;
gint index, x_layout, y_layout;
@@ -1000,16 +1023,14 @@ gtk_entry_accessible_get_offset_at_point (AtkText *atk_text,
GdkSurface *surface;
glong offset;
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
return -1;
textw = get_text (atk_text);
entry = GTK_ENTRY (widget);
textw = gtk_entry_get_text_widget (entry);
if (textw == NULL)
return 1;
gtk_text_get_layout_offsets (textw, &x_layout, &y_layout);
surface = gtk_widget_get_surface (widget);
surface = gtk_widget_get_surface (GTK_WIDGET (textw));
gdk_surface_get_origin (surface, &x_surface, &y_surface);
x_local = x - x_layout - x_surface;
@@ -1158,21 +1179,22 @@ static gunichar
gtk_entry_accessible_get_character_at_offset (AtkText *atk_text,
gint offset)
{
GtkWidget *widget;
GtkText *textw;
gchar *text;
gchar *index;
gunichar result;
result = '\0';
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (atk_text));
if (widget == NULL)
textw = get_text (atk_text);
if (textw == NULL)
return 0;
if (!gtk_text_get_visibility (textw))
return result;
if (!gtk_entry_get_visibility (GTK_ENTRY (widget)))
return result;
text = gtk_text_get_display_text (gtk_entry_get_text_widget (GTK_ENTRY (widget)), 0, -1);
text = gtk_text_get_display_text (textw, 0, -1);
if (offset < g_utf8_strlen (text, -1))
{
index = g_utf8_offset_to_pointer (text, offset);
@@ -1218,7 +1240,7 @@ gtk_entry_accessible_set_text_contents (AtkEditableText *text,
if (!gtk_editable_get_editable (GTK_EDITABLE (widget)))
return;
gtk_entry_set_text (GTK_ENTRY (widget), string);
gtk_editable_set_text (GTK_EDITABLE (widget), string);
}
static void
@@ -1400,14 +1422,19 @@ delete_text_cb (GtkEditable *editable,
gint end)
{
GtkEntryAccessible *accessible;
GtkText *textw;
accessible = GTK_ENTRY_ACCESSIBLE (gtk_widget_get_accessible (GTK_WIDGET (editable)));
textw = get_text (ATK_TEXT (accessible));
if (textw == NULL)
return;
if (end < 0)
{
gchar *text;
text = gtk_text_get_display_text (gtk_entry_get_text_widget (GTK_ENTRY (editable)), 0, -1);
text = gtk_text_get_display_text (textw, 0, -1);
end = g_utf8_strlen (text, -1);
g_free (text);
}
+6 -3
View File
@@ -1,3 +1,4 @@
#include <winuser.h>
#include <winver.h>
GTK_ICON ICON "gtk.ico"
@@ -18,9 +19,9 @@ VS_VERSION_INFO VERSIONINFO
VALUE "CompanyName", "The GTK developer community"
VALUE "FileDescription", "GIMP Toolkit"
VALUE "FileVersion", "@GTK_VERSION@.0"
VALUE "InternalName", "libgtk-win32-@GTK_API_VERSION@-@LT_CURRENT_MINUS_AGE@"
VALUE "LegalCopyright", "Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald. Modified by the GTK+ Team and others 1997-2011."
VALUE "OriginalFilename", "libgtk-win32-@GTK_API_VERSION@-@LT_CURRENT_MINUS_AGE@.dll"
VALUE "InternalName", "libgtk-win32-@GTK_API_VERSION@"
VALUE "LegalCopyright", "Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald. Modified by the GTK+ Team and others 1997-2011."
VALUE "OriginalFilename", "libgtk-win32-@GTK_API_VERSION@.dll"
VALUE "ProductName", "GTK+"
VALUE "ProductVersion", "@GTK_VERSION@"
END
@@ -30,3 +31,5 @@ VS_VERSION_INFO VERSIONINFO
VALUE "Translation", 0x409, 1200
END
END
ISOLATIONAWARE_MANIFEST_RESOURCE_ID RT_MANIFEST libgtk4.manifest
+4 -3
View File
@@ -41,8 +41,9 @@ gtk_drag_dest_realized (GtkWidget *widget)
}
static void
gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
gtk_drag_dest_hierarchy_changed (GtkWidget *widget,
GParamSpec *pspec,
gpointer data)
{
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
@@ -85,7 +86,7 @@ gtk_drag_dest_set_internal (GtkWidget *widget,
g_signal_connect (widget, "realize",
G_CALLBACK (gtk_drag_dest_realized), site);
g_signal_connect (widget, "hierarchy-changed",
g_signal_connect (widget, "notify::root",
G_CALLBACK (gtk_drag_dest_hierarchy_changed), site);
g_object_set_data_full (G_OBJECT (widget), I_("gtk-drag-dest"),
+25 -17
View File
@@ -452,8 +452,8 @@ static void gtk_file_chooser_widget_dispose (GObject *obj
static void gtk_file_chooser_widget_realize (GtkWidget *widget);
static void gtk_file_chooser_widget_map (GtkWidget *widget);
static void gtk_file_chooser_widget_unmap (GtkWidget *widget);
static void gtk_file_chooser_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel);
static void gtk_file_chooser_widget_root (GtkWidget *widget);
static void gtk_file_chooser_widget_unroot (GtkWidget *widget);
static void gtk_file_chooser_widget_style_updated (GtkWidget *widget);
static void gtk_file_chooser_widget_display_changed (GtkWidget *widget,
GdkDisplay *previous_display);
@@ -3573,31 +3573,38 @@ toplevel_set_focus_cb (GtkWindow *window,
* was last focused at the time our should_respond method gets called.
*/
static void
gtk_file_chooser_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
gtk_file_chooser_widget_root (GtkWidget *widget)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (widget);
GtkFileChooserWidgetPrivate *priv = impl->priv;
GtkWidget *toplevel;
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
g_assert (priv->toplevel_set_focus_id == 0);
priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus",
G_CALLBACK (toplevel_set_focus_cb), impl);
priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
}
static void
gtk_file_chooser_widget_unroot (GtkWidget *widget)
{
GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (widget);
GtkFileChooserWidgetPrivate *priv = impl->priv;
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
if (previous_toplevel &&
priv->toplevel_set_focus_id != 0)
if (toplevel && priv->toplevel_set_focus_id != 0)
{
g_signal_handler_disconnect (previous_toplevel,
priv->toplevel_set_focus_id);
g_signal_handler_disconnect (toplevel, priv->toplevel_set_focus_id);
priv->toplevel_set_focus_id = 0;
priv->toplevel_last_focus_widget = NULL;
}
if (gtk_widget_is_toplevel (toplevel))
{
g_assert (priv->toplevel_set_focus_id == 0);
priv->toplevel_set_focus_id = g_signal_connect (toplevel, "set-focus",
G_CALLBACK (toplevel_set_focus_cb), impl);
priv->toplevel_last_focus_widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
}
GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->unroot (widget);
}
/* Changes the icons wherever it is needed */
@@ -7994,7 +8001,8 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
widget_class->realize = gtk_file_chooser_widget_realize;
widget_class->map = gtk_file_chooser_widget_map;
widget_class->unmap = gtk_file_chooser_widget_unmap;
widget_class->hierarchy_changed = gtk_file_chooser_widget_hierarchy_changed;
widget_class->root = gtk_file_chooser_widget_root;
widget_class->unroot = gtk_file_chooser_widget_unroot;
widget_class->style_updated = gtk_file_chooser_widget_style_updated;
widget_class->display_changed = gtk_file_chooser_widget_display_changed;
widget_class->measure = gtk_file_chooser_widget_measure;
+4 -3
View File
@@ -1755,11 +1755,12 @@ surface_state_changed (GtkWidget *widget)
}
static void
gtk_header_bar_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
gtk_header_bar_root (GtkWidget *widget)
{
GtkHeaderBar *bar = GTK_HEADER_BAR (widget);
GTK_WIDGET_CLASS (gtk_header_bar_parent_class)->root (widget);
_gtk_header_bar_update_window_buttons (bar);
}
@@ -1779,7 +1780,7 @@ gtk_header_bar_class_init (GtkHeaderBarClass *class)
widget_class->measure = gtk_header_bar_measure;
widget_class->realize = gtk_header_bar_realize;
widget_class->unrealize = gtk_header_bar_unrealize;
widget_class->hierarchy_changed = gtk_header_bar_hierarchy_changed;
widget_class->root = gtk_header_bar_root;
container_class->add = gtk_header_bar_add;
container_class->remove = gtk_header_bar_remove;
+7 -58
View File
@@ -29,6 +29,7 @@
#include "gtkimcontextime.h"
#include "gtkimmoduleprivate.h"
#include "gtkroot.h"
#include "imm-extra.h"
@@ -121,9 +122,6 @@ gtk_im_context_ime_message_filter (GdkWin32Display *display,
static void get_window_position (GdkSurface *win,
gint *x,
gint *y);
static void cb_client_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *widget2,
GtkIMContextIME *context_ime);
G_DEFINE_TYPE_WITH_CODE (GtkIMContextIME, gtk_im_context_ime, GTK_TYPE_IM_CONTEXT,
gtk_im_module_ensure_extension_point ();
@@ -157,7 +155,6 @@ static void
gtk_im_context_ime_init (GtkIMContextIME *context_ime)
{
context_ime->client_surface = NULL;
context_ime->toplevel = NULL;
context_ime->use_preedit = TRUE;
context_ime->preediting = FALSE;
context_ime->opened = FALSE;
@@ -687,7 +684,6 @@ gtk_im_context_ime_focus_in (GtkIMContext *context)
{
gdk_win32_display_add_filter (gdk_surface_get_display (toplevel),
gtk_im_context_ime_message_filter, context_ime);
context_ime->toplevel = toplevel;
}
else
{
@@ -696,19 +692,6 @@ gtk_im_context_ime_focus_in (GtkIMContext *context)
return;
}
/* trace reparenting (probably no need) */
gdk_surface_get_user_data (context_ime->client_surface, (gpointer) & widget);
if (GTK_IS_WIDGET (widget))
{
g_signal_connect (widget, "hierarchy-changed",
G_CALLBACK (cb_client_widget_hierarchy_changed),
context_ime);
}
else
{
/* warning? */
}
/* restore preedit context */
ImmSetConversionStatus (himc,
context_ime->priv->conversion_mode,
@@ -794,15 +777,6 @@ gtk_im_context_ime_focus_out (GtkIMContext *context)
context_ime->preediting = FALSE;
}
/* remove signal handler */
gdk_surface_get_user_data (context_ime->client_surface, (gpointer) & widget);
if (GTK_IS_WIDGET (widget))
{
g_signal_handlers_disconnect_by_func
(G_OBJECT (widget),
G_CALLBACK (cb_client_widget_hierarchy_changed), context_ime);
}
/* remove event fileter */
toplevel = gdk_surface_get_toplevel (context_ime->client_surface);
if (GDK_IS_SURFACE (toplevel))
@@ -810,7 +784,6 @@ gtk_im_context_ime_focus_out (GtkIMContext *context)
gdk_win32_display_remove_filter (gdk_surface_get_display (toplevel),
gtk_im_context_ime_message_filter,
context_ime);
context_ime->toplevel = NULL;
}
else
{
@@ -906,9 +879,9 @@ gtk_im_context_ime_set_preedit_font (GtkIMContext *context)
if (!context_ime->client_surface)
return;
gdk_surface_get_user_data (context_ime->client_surface, (gpointer) &widget);
if (!GTK_IS_WIDGET (widget))
return;
widget = gtk_root_get_for_surface (context_ime->client_surface);
if (!widget)
return
hwnd = gdk_win32_surface_get_impl_hwnd (context_ime->client_surface);
himc = ImmGetContext (hwnd);
@@ -1017,6 +990,7 @@ gtk_im_context_ime_message_filter (GdkWin32Display *display,
GtkIMContextIME *context_ime;
HWND hwnd;
HIMC himc;
GdkSurface *toplevel;
GdkWin32MessageFilterReturn retval = GDK_WIN32_MESSAGE_FILTER_CONTINUE;
g_return_val_if_fail (GTK_IS_IM_CONTEXT_IME (data), retval);
@@ -1026,7 +1000,8 @@ gtk_im_context_ime_message_filter (GdkWin32Display *display,
if (!context_ime->focus)
return retval;
if (gdk_win32_surface_get_impl_hwnd (context_ime->toplevel) != msg->hwnd)
toplevel = gdk_surface_get_toplevel (context_ime->client_surface);
if (gdk_win32_surface_get_impl_hwnd (toplevel) != msg->hwnd)
return retval;
hwnd = gdk_win32_surface_get_impl_hwnd (context_ime->client_surface);
@@ -1163,29 +1138,3 @@ get_window_position (GdkSurface *surface, gint *x, gint *y)
if (parent && parent != toplevel)
get_window_position (parent, x, y);
}
/*
* probably, this handler isn't needed.
*/
static void
cb_client_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *widget2,
GtkIMContextIME *context_ime)
{
GdkSurface *new_toplevel;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GTK_IS_IM_CONTEXT_IME (context_ime));
if (!context_ime->client_surface)
return;
if (!context_ime->focus)
return;
new_toplevel = gdk_surface_get_toplevel (context_ime->client_surface);
if (context_ime->toplevel == new_toplevel)
return;
context_ime->toplevel = new_toplevel;
}
-1
View File
@@ -37,7 +37,6 @@ struct _GtkIMContextIME
GtkIMContext object;
GdkSurface *client_surface;
GdkSurface *toplevel;
guint use_preedit : 1;
guint preediting : 1;
guint opened : 1;
+4 -22
View File
@@ -22,6 +22,7 @@
#include "gtkimcontextxim.h"
#include "gtkimmoduleprivate.h"
#include "gtkroot.h"
#include "gtk/gtkintl.h"
@@ -1520,38 +1521,19 @@ update_in_toplevel (GtkIMContextXIM *context_xim)
*/
static void
on_client_widget_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel,
GParamSpec *pspec,
GtkIMContextXIM *context_xim)
{
update_in_toplevel (context_xim);
}
/* Finds the GtkWidget that owns the window, or if none, the
* widget owning the nearest parent that has a widget.
*/
static GtkWidget *
widget_for_window (GdkSurface *window)
{
while (window)
{
gpointer user_data;
gdk_surface_get_user_data (window, &user_data);
if (user_data)
return user_data;
window = gdk_surface_get_parent (window);
}
return NULL;
}
/* Called when context_xim->client_surface changes; takes care of
* removing and/or setting up our watches for the toplevel
*/
static void
update_client_widget (GtkIMContextXIM *context_xim)
{
GtkWidget *new_client_widget = widget_for_window (context_xim->client_surface);
GtkWidget *new_client_widget = gtk_root_get_for_surface (context_xim->client_surface);
if (new_client_widget != context_xim->client_widget)
{
@@ -1564,7 +1546,7 @@ update_client_widget (GtkIMContextXIM *context_xim)
context_xim->client_widget = new_client_widget;
if (context_xim->client_widget)
{
g_signal_connect (context_xim->client_widget, "hierarchy-changed",
g_signal_connect (context_xim->client_widget, "notify::root",
G_CALLBACK (on_client_widget_hierarchy_changed),
context_xim);
}
+25 -12
View File
@@ -452,8 +452,8 @@ static void gtk_label_set_markup_internal (GtkLabel *label,
const gchar *str,
gboolean with_uline);
static void gtk_label_recalculate (GtkLabel *label);
static void gtk_label_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel);
static void gtk_label_root (GtkWidget *widget);
static void gtk_label_unroot (GtkWidget *widget);
static void gtk_label_display_changed (GtkWidget *widget,
GdkDisplay *old_display);
static gboolean gtk_label_popup_menu (GtkWidget *widget);
@@ -475,6 +475,7 @@ static void gtk_label_update_active_link (GtkWidget *widget,
static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
static void gtk_label_setup_mnemonic (GtkLabel *label,
GtkWidget *toplevel,
guint last_key);
static void gtk_label_drag_data_get (GtkWidget *widget,
GdkDrag *drag,
@@ -604,7 +605,8 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->realize = gtk_label_realize;
widget_class->unrealize = gtk_label_unrealize;
widget_class->unmap = gtk_label_unmap;
widget_class->hierarchy_changed = gtk_label_hierarchy_changed;
widget_class->root = gtk_label_root;
widget_class->unroot = gtk_label_unroot;
widget_class->display_changed = gtk_label_display_changed;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
widget_class->drag_data_get = gtk_label_drag_data_get;
@@ -1738,12 +1740,12 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
}
static void
gtk_label_setup_mnemonic (GtkLabel *label,
guint last_key)
gtk_label_setup_mnemonic (GtkLabel *label,
GtkWidget *toplevel,
guint last_key)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkWidget *widget = GTK_WIDGET (label);
GtkWidget *toplevel;
GtkWidget *mnemonic_menu;
mnemonic_menu = g_object_get_qdata (G_OBJECT (label), quark_mnemonic_menu);
@@ -1771,8 +1773,7 @@ gtk_label_setup_mnemonic (GtkLabel *label,
connect_mnemonics_visible_notify (GTK_LABEL (widget));
toplevel = gtk_widget_get_toplevel (widget);
if (gtk_widget_is_toplevel (toplevel))
if (toplevel && gtk_widget_is_toplevel (toplevel))
{
GtkWidget *menu_shell;
@@ -1801,13 +1802,25 @@ gtk_label_setup_mnemonic (GtkLabel *label,
}
static void
gtk_label_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel)
gtk_label_root (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gtk_label_setup_mnemonic (label, priv->mnemonic_keyval);
GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (widget), priv->mnemonic_keyval);
}
static void
gtk_label_unroot (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
gtk_label_setup_mnemonic (label, NULL, priv->mnemonic_keyval);
GTK_WIDGET_CLASS (gtk_label_parent_class)->unroot (widget);
}
static void
@@ -2131,7 +2144,7 @@ gtk_label_recalculate (GtkLabel *label)
if (keyval != priv->mnemonic_keyval)
{
gtk_label_setup_mnemonic (label, keyval);
gtk_label_setup_mnemonic (label, gtk_widget_get_toplevel (GTK_WIDGET (label)), keyval);
g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_MNEMONIC_KEYVAL]);
}
-1
View File
@@ -599,7 +599,6 @@ do_pre_parse_initialization (void)
g_error ("GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported");
gdk_pre_parse ();
gdk_event_handler_set ((GdkEventFunc)gtk_main_do_event, NULL, NULL);
#ifdef G_ENABLE_DEBUG
env_string = g_getenv ("GTK_DEBUG");
+19 -12
View File
@@ -91,8 +91,8 @@ static void gtk_menu_bar_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline);
static void gtk_menu_bar_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel);
static void gtk_menu_bar_root (GtkWidget *widget);
static void gtk_menu_bar_unroot (GtkWidget *widget);
static gint gtk_menu_bar_get_popup_delay (GtkMenuShell *menu_shell);
static void gtk_menu_bar_move_current (GtkMenuShell *menu_shell,
GtkMenuDirectionType direction);
@@ -117,7 +117,8 @@ gtk_menu_bar_class_init (GtkMenuBarClass *class)
widget_class->measure = gtk_menu_bar_measure;
widget_class->size_allocate = gtk_menu_bar_size_allocate;
widget_class->hierarchy_changed = gtk_menu_bar_hierarchy_changed;
widget_class->root = gtk_menu_bar_root;
widget_class->unroot = gtk_menu_bar_unroot;
menu_shell_class->submenu_placement = GTK_TOP_BOTTOM;
menu_shell_class->get_popup_delay = gtk_menu_bar_get_popup_delay;
@@ -536,21 +537,27 @@ remove_from_window (GtkWindow *window,
}
static void
gtk_menu_bar_hierarchy_changed (GtkWidget *widget,
GtkWidget *old_toplevel)
gtk_menu_bar_root (GtkWidget *widget)
{
GtkMenuBar *menubar = GTK_MENU_BAR (widget);
GtkWidget *toplevel;
GtkMenuBar *menubar;
menubar = GTK_MENU_BAR (widget);
GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
add_to_window (GTK_WINDOW (toplevel), menubar);
}
if (old_toplevel)
remove_from_window (GTK_WINDOW (old_toplevel), menubar);
if (gtk_widget_is_toplevel (toplevel))
add_to_window (GTK_WINDOW (toplevel), menubar);
static void
gtk_menu_bar_unroot (GtkWidget *widget)
{
GtkMenuBar *menubar = GTK_MENU_BAR (widget);
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
remove_from_window (GTK_WINDOW (toplevel), menubar);
GTK_WIDGET_CLASS (gtk_menu_bar_parent_class)->unroot (widget);
}
/**
+2
View File
@@ -90,6 +90,8 @@ gtk_password_entry_init (GtkPasswordEntry *entry)
gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
priv->entry = gtk_text_new ();
+2 -2
View File
@@ -1685,7 +1685,7 @@ gtk_popover_update_scrollable (GtkPopover *popover)
static void
_gtk_popover_parent_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel,
GParamSpec *pspec,
GtkPopover *popover)
{
GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover);
@@ -1973,7 +1973,7 @@ gtk_popover_update_relative_to (GtkPopover *popover,
GTK_WINDOW (gtk_widget_get_ancestor (priv->widget, GTK_TYPE_WINDOW));
priv->hierarchy_changed_id =
g_signal_connect (priv->widget, "hierarchy-changed",
g_signal_connect (priv->widget, "notify::root",
G_CALLBACK (_gtk_popover_parent_hierarchy_changed),
popover);
priv->size_allocate_id =
+21
View File
@@ -102,3 +102,24 @@ gtk_root_get_surface_transform (GtkRoot *self,
iface = GTK_ROOT_GET_IFACE (self);
return iface->get_surface_transform (self, x, y);
}
/**
* gtk_root_get_for_surface:
* @surface: a #GdkSurface
*
* Finds the GtkRoot associated with the surface.
*
* Returns: (transfer none): the #GtkRoot that is associated with @surface
*/
GtkWidget *
gtk_root_get_for_surface (GdkSurface *surface)
{
gpointer user_data;
gdk_surface_get_user_data (surface, &user_data);
if (user_data && GTK_IS_ROOT (user_data))
return GTK_WIDGET (user_data);
return NULL;
}
+2
View File
@@ -53,6 +53,8 @@ struct _GtkRootInterface
int *y);
};
GDK_AVAILABLE_IN_ALL
GtkWidget * gtk_root_get_for_surface (GdkSurface *surface);
G_END_DECLS
+17 -5
View File
@@ -41,6 +41,8 @@
#include "gtkmarshalers.h"
#include "gtkstylecontext.h"
#include "gtkeventcontrollerkey.h"
#include "a11y/gtkentryaccessible.h"
/**
* SECTION:gtksearchentry
@@ -236,6 +238,17 @@ gtk_search_entry_size_allocate (GtkWidget *widget,
baseline);
}
static AtkObject *
gtk_search_entry_get_accessible (GtkWidget *widget)
{
AtkObject *atk_obj;
atk_obj = GTK_WIDGET_CLASS (gtk_search_entry_parent_class)->get_accessible (widget);
atk_object_set_name (atk_obj, _("Search"));
return atk_obj;
}
static void
gtk_search_entry_grab_focus (GtkWidget *widget)
{
@@ -258,6 +271,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
widget_class->measure = gtk_search_entry_measure;
widget_class->size_allocate = gtk_search_entry_size_allocate;
widget_class->get_accessible = gtk_search_entry_get_accessible;
widget_class->grab_focus = gtk_search_entry_grab_focus;
klass->stop_search = gtk_search_entry_stop_search;
@@ -378,6 +392,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
"stop-search", 0);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("entry"));
}
@@ -485,13 +500,14 @@ static void
gtk_search_entry_init (GtkSearchEntry *entry)
{
GtkSearchEntryPrivate *priv = gtk_search_entry_get_instance_private (entry);
AtkObject *atk_obj;
GtkGesture *press;
gtk_widget_set_has_surface (GTK_WIDGET (entry), FALSE);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
priv->entry = gtk_text_new ();
gtk_widget_set_hexpand (priv->entry, TRUE);
@@ -513,10 +529,6 @@ gtk_search_entry_init (GtkSearchEntry *entry)
g_signal_connect (press, "released", G_CALLBACK (gtk_search_entry_icon_release), entry);
gtk_widget_add_controller (priv->icon, GTK_EVENT_CONTROLLER (press));
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (entry));
if (GTK_IS_ACCESSIBLE (atk_obj))
atk_object_set_name (atk_obj, _("Search"));
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (entry)), I_("search"));
}
+9 -6
View File
@@ -61,6 +61,7 @@ struct _HandleWindow
struct _GtkTextHandlePrivate
{
HandleWindow windows[2];
GtkWidget *toplevel;
GtkWidget *parent;
GtkScrollable *parent_scrollable;
GtkAdjustment *vadj;
@@ -217,7 +218,7 @@ _gtk_text_handle_ensure_widget (GtkTextHandle *handle,
gtk_widget_add_controller (widget, controller);
priv->windows[pos].widget = g_object_ref_sink (widget);
window = gtk_widget_get_ancestor (priv->parent, GTK_TYPE_WINDOW);
priv->toplevel = window = gtk_widget_get_ancestor (priv->parent, GTK_TYPE_WINDOW);
_gtk_window_add_popover (GTK_WINDOW (window), widget, priv->parent, FALSE);
context = gtk_widget_get_style_context (widget);
@@ -468,7 +469,7 @@ gtk_text_handle_lookup_scrollable (GtkTextHandle *handle)
static void
_gtk_text_handle_parent_hierarchy_changed (GtkWidget *widget,
GtkWindow *previous_toplevel,
GParamSpec *pspec,
GtkTextHandle *handle)
{
GtkWidget *toplevel, *scrollable;
@@ -477,11 +478,11 @@ _gtk_text_handle_parent_hierarchy_changed (GtkWidget *widget,
priv = handle->priv;
toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
if (previous_toplevel && !toplevel)
if (priv->toplevel && !toplevel)
{
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
{
_gtk_window_remove_popover (GTK_WINDOW (previous_toplevel),
_gtk_window_remove_popover (GTK_WINDOW (priv->toplevel),
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget = NULL;
@@ -489,11 +490,13 @@ _gtk_text_handle_parent_hierarchy_changed (GtkWidget *widget,
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
{
_gtk_window_remove_popover (GTK_WINDOW (previous_toplevel),
_gtk_window_remove_popover (GTK_WINDOW (priv->toplevel),
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget = NULL;
}
priv->toplevel = NULL;
}
scrollable = gtk_text_handle_lookup_scrollable (handle);
@@ -521,7 +524,7 @@ _gtk_text_handle_set_parent (GtkTextHandle *handle,
if (parent)
{
priv->hierarchy_changed_id =
g_signal_connect (parent, "hierarchy-changed",
g_signal_connect (parent, "notify::root",
G_CALLBACK (_gtk_text_handle_parent_hierarchy_changed),
handle);
+1 -1
View File
@@ -13793,7 +13793,7 @@ gtk_tree_view_search_window_hide (GtkWidget *search_window,
/* send focus-in event */
send_focus_change (GTK_WIDGET (tree_view->priv->search_entry), device, FALSE);
gtk_widget_hide (search_window);
gtk_entry_set_text (GTK_ENTRY (tree_view->priv->search_entry), "");
gtk_editable_set_text (GTK_EDITABLE(tree_view->priv->search_entry), "");
send_focus_change (GTK_WIDGET (tree_view), device, TRUE);
}
}
+28 -147
View File
@@ -681,8 +681,6 @@ static gboolean event_surface_is_still_viewable (const GdkEvent *event);
static void gtk_widget_update_input_shape (GtkWidget *widget);
static gboolean gtk_widget_class_get_visible_by_default (GtkWidgetClass *widget_class);
static void _gtk_widget_propagate_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel);
/* --- variables --- */
@@ -928,7 +926,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->get_request_mode = gtk_widget_real_get_request_mode;
klass->measure = gtk_widget_real_measure;
klass->state_flags_changed = gtk_widget_real_state_flags_changed;
klass->hierarchy_changed = NULL;
klass->direction_changed = gtk_widget_real_direction_changed;
klass->grab_notify = gtk_widget_real_grab_notify;
klass->child_notify = NULL;
@@ -938,7 +935,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
klass->focus = gtk_widget_real_focus;
klass->move_focus = gtk_widget_real_move_focus;
klass->keynav_failed = gtk_widget_real_keynav_failed;
klass->event = NULL;
klass->drag_begin = NULL;
klass->drag_end = NULL;
klass->drag_data_delete = NULL;
@@ -1557,28 +1553,6 @@ gtk_widget_class_init (GtkWidgetClass *klass)
G_TYPE_NONE, 1,
GTK_TYPE_STATE_FLAGS);
/**
* GtkWidget::hierarchy-changed:
* @widget: the object on which the signal is emitted
* @previous_toplevel: (allow-none): the previous toplevel ancestor, or %NULL
* if the widget was previously unanchored
*
* The ::hierarchy-changed signal is emitted when the
* anchored state of a widget changes. A widget is
* anchored when its toplevel
* ancestor is a #GtkWindow. This signal is emitted when
* a widget changes from un-anchored to anchored or vice-versa.
*/
widget_signals[HIERARCHY_CHANGED] =
g_signal_new (I_("hierarchy-changed"),
G_TYPE_FROM_CLASS (gobject_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetClass, hierarchy_changed),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GTK_TYPE_WIDGET);
/**
* GtkWidget::style-updated:
* @widget: the object on which the signal is emitted
@@ -3110,9 +3084,9 @@ gtk_widget_unparent (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GObjectNotifyQueue *nqueue;
GtkWidget *toplevel;
GtkWidget *old_parent;
GtkWidget *old_prev_sibling;
GtkWidget *toplevel;
g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -3151,13 +3125,7 @@ gtk_widget_unparent (GtkWidget *widget)
if (priv->root)
gtk_widget_unroot (widget);
/* If we are unanchoring the child, we save around the toplevel
* to emit hierarchy changed
*/
if (priv->parent->priv->anchored)
g_object_ref (toplevel);
else
toplevel = NULL;
toplevel = NULL;
/* Removing a widget from a container restores the child visible
* flag to the default state, so it doesn't affect the child
@@ -3207,15 +3175,10 @@ gtk_widget_unparent (GtkWidget *widget)
if (old_parent->priv->children_observer)
gtk_list_list_model_item_removed (old_parent->priv->children_observer, old_prev_sibling);
if (toplevel)
_gtk_widget_propagate_hierarchy_changed (widget, toplevel);
g_clear_object (&toplevel);
/* Now that the parent pointer is nullified and the hierarchy-changed
* already passed, go ahead and unset the parent window, if we are unparenting
* an embedded GtkWindow the window will become toplevel again and hierarchy-changed
* will fire again for the new subhierarchy.
/* Now that the parent pointer is nullified and the unroot vfunc already
* called, go ahead and unset the parent window, if we are unparenting
* an embedded GtkWindow the window will become toplevel again and root
* will fire for the new hierarchy.
*/
gtk_widget_set_parent_surface (widget, NULL);
@@ -3792,7 +3755,6 @@ gtk_widget_realize (GtkWidget *widget)
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (priv->anchored || GTK_IS_INVISIBLE (widget));
if (!_gtk_widget_get_realized (widget))
{
@@ -5171,7 +5133,7 @@ gtk_widget_run_controllers (GtkWidget *widget,
return handled;
}
static gboolean
static void
translate_event_coordinates (GdkEvent *event,
GtkWidget *widget);
gboolean
@@ -5189,11 +5151,7 @@ _gtk_widget_captured_event (GtkWidget *widget,
return TRUE;
event_copy = gdk_event_copy (event);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
translate_event_coordinates (event_copy, widget);
return_val = gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_CAPTURE);
@@ -5251,7 +5209,7 @@ event_surface_is_still_viewable (const GdkEvent *event)
}
}
static gboolean
static void
translate_event_coordinates (GdkEvent *event,
GtkWidget *widget)
{
@@ -5260,7 +5218,7 @@ translate_event_coordinates (GdkEvent *event,
graphene_point_t p;
if (!gdk_event_get_coords (event, &x, &y))
return TRUE;
return;
event_widget = gtk_get_event_widget (event);
@@ -5268,11 +5226,11 @@ translate_event_coordinates (GdkEvent *event,
widget,
&GRAPHENE_POINT_INIT (x, y),
&p))
return FALSE;
{
p.x = p.y = 0;
}
gdk_event_set_coords (event, p.x, p.y);
return TRUE;
}
static gboolean
@@ -5295,11 +5253,7 @@ gtk_widget_event_internal (GtkWidget *widget,
event_copy = gdk_event_copy (event);
if (!translate_event_coordinates (event_copy, widget))
{
g_object_unref (event_copy);
return FALSE;
}
translate_event_coordinates (event_copy, widget);
if (widget == gtk_get_event_target (event_copy))
return_val |= gtk_widget_run_controllers (widget, event_copy, GTK_PHASE_TARGET);
@@ -5530,7 +5484,7 @@ gtk_widget_real_style_updated (GtkWidget *widget)
if (has_text && gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_TEXT))
gtk_widget_update_pango_context (widget);
if (priv->anchored)
if (priv->root)
{
if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE) ||
(has_text && gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_TEXT_SIZE)))
@@ -5552,7 +5506,7 @@ gtk_widget_real_style_updated (GtkWidget *widget)
{
gtk_widget_update_pango_context (widget);
if (priv->anchored)
if (priv->root)
gtk_widget_queue_resize (widget);
}
}
@@ -6670,10 +6624,6 @@ gtk_widget_reposition_after (GtkWidget *widget,
gtk_list_list_model_item_added (parent->priv->children_observer, widget);
}
if (priv->parent->priv->anchored && prev_parent == NULL)
{
_gtk_widget_propagate_hierarchy_changed (widget, NULL);
}
if (parent->priv->root && priv->root == NULL)
gtk_widget_root (widget);
@@ -6816,70 +6766,6 @@ do_display_change (GtkWidget *widget,
}
}
static void
gtk_widget_propagate_hierarchy_changed_recurse (GtkWidget *widget,
gpointer client_data)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
HierarchyChangedInfo *info = client_data;
gboolean new_anchored = _gtk_widget_is_toplevel (widget) ||
(priv->parent && priv->parent->priv->anchored);
if (priv->anchored != new_anchored)
{
g_object_ref (widget);
priv->anchored = new_anchored;
g_assert (!priv->realized);
g_signal_emit (widget, widget_signals[HIERARCHY_CHANGED], 0, info->previous_toplevel);
do_display_change (widget, info->previous_display, info->new_display);
gtk_widget_forall (widget, gtk_widget_propagate_hierarchy_changed_recurse, client_data);
g_object_unref (widget);
}
}
/**
* _gtk_widget_propagate_hierarchy_changed:
* @widget: a #GtkWidget
* @previous_toplevel: Previous toplevel
*
* Propagates changes in the anchored state to a widget and all
* children, unsetting or setting the %ANCHORED flag, and
* emitting #GtkWidget::hierarchy-changed.
**/
static void
_gtk_widget_propagate_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
HierarchyChangedInfo info;
info.previous_toplevel = previous_toplevel;
info.previous_display = previous_toplevel ? _gtk_widget_get_display (previous_toplevel) : NULL;
if (_gtk_widget_is_toplevel (widget) ||
(priv->parent && priv->parent->priv->anchored))
info.new_display = _gtk_widget_get_display (widget);
else
info.new_display = NULL;
if (info.previous_display)
g_object_ref (info.previous_display);
if (previous_toplevel)
g_object_ref (previous_toplevel);
gtk_widget_propagate_hierarchy_changed_recurse (widget, &info);
if (previous_toplevel)
g_object_unref (previous_toplevel);
if (info.previous_display)
g_object_unref (info.previous_display);
}
static void
gtk_widget_propagate_display_changed_recurse (GtkWidget *widget,
gpointer client_data)
@@ -11532,6 +11418,16 @@ surface_expose (GdkSurface *surface,
return TRUE;
}
static gboolean
surface_event (GdkSurface *surface,
GdkEvent *event,
GtkWidget *widget)
{
gtk_main_do_event (event);
return TRUE;
}
/**
* gtk_widget_register_surface:
* @widget: a #GtkWidget
@@ -11561,6 +11457,7 @@ gtk_widget_register_surface (GtkWidget *widget,
gdk_surface_set_user_data (surface, widget);
g_signal_connect (surface, "render", G_CALLBACK (surface_expose), widget);
g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget);
}
/**
@@ -11586,6 +11483,7 @@ gtk_widget_unregister_surface (GtkWidget *widget,
gdk_surface_set_user_data (surface, NULL);
g_signal_handlers_disconnect_by_func (surface, surface_expose, widget);
g_signal_handlers_disconnect_by_func (surface, surface_event, widget);
}
/**
@@ -11868,23 +11766,6 @@ gtk_widget_in_destruction (GtkWidget *widget)
return priv->in_destruction;
}
gboolean
_gtk_widget_get_anchored (GtkWidget *widget)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
return priv->anchored;
}
void
_gtk_widget_set_anchored (GtkWidget *widget,
gboolean anchored)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
priv->anchored = anchored;
}
gboolean
_gtk_widget_get_shadowed (GtkWidget *widget)
{
+2 -11
View File
@@ -152,14 +152,11 @@ struct _GtkWidget
* widget is destroyed, which means that gtk_widget_unrealize() has
* been called or the widget has been unmapped (that is, it is going
* to be hidden).
* @root: Called when the widget gets added to a #GtkRoot widget.
* @unroot: Called when the widget is about to be removed from its
* #GtkRoot widget.
* @root: Called when the widget gets added to a #GtkRoot widget. Must chain up
* @unroot: Called when the widget is about to be removed from its #GtkRoot widget. Must chain up
* @size_allocate: Signal emitted to get the widget allocation.
* @state_flags_changed: Signal emitted when the widget state changes,
* see gtk_widget_get_state_flags().
* @hierarchy_changed: Signal emitted when the anchored state of a
* widget changes.
* @direction_changed: Signal emitted when the text direction of a
* widget changes.
* @grab_notify: Signal emitted when a widget becomes shadowed by a
@@ -258,8 +255,6 @@ struct _GtkWidgetClass
int baseline);
void (* state_flags_changed) (GtkWidget *widget,
GtkStateFlags previous_state_flags);
void (* hierarchy_changed) (GtkWidget *widget,
GtkWidget *previous_toplevel);
void (* direction_changed) (GtkWidget *widget,
GtkTextDirection previous_direction);
void (* grab_notify) (GtkWidget *widget,
@@ -292,10 +287,6 @@ struct _GtkWidgetClass
gboolean (* keynav_failed) (GtkWidget *widget,
GtkDirectionType direction);
/* events */
gboolean (* event) (GtkWidget *widget,
GdkEvent *event);
/* Source side drag signals */
void (* drag_begin) (GtkWidget *widget,
GdkDrag *drag);
-4
View File
@@ -58,7 +58,6 @@ struct _GtkWidgetPrivate
#endif
guint in_destruction : 1;
guint anchored : 1;
guint no_surface : 1;
guint no_surface_set : 1;
guint realized : 1;
@@ -195,9 +194,6 @@ struct _GtkWidgetPrivate
GtkCssNode * gtk_widget_get_css_node (GtkWidget *widget);
void _gtk_widget_set_visible_flag (GtkWidget *widget,
gboolean visible);
gboolean _gtk_widget_get_anchored (GtkWidget *widget);
void _gtk_widget_set_anchored (GtkWidget *widget,
gboolean anchored);
gboolean _gtk_widget_get_shadowed (GtkWidget *widget);
void _gtk_widget_set_shadowed (GtkWidget *widget,
gboolean shadowed);
-1
View File
@@ -1866,7 +1866,6 @@ gtk_window_init (GtkWindow *window)
widget = GTK_WIDGET (window);
gtk_widget_set_has_surface (widget, TRUE);
_gtk_widget_set_anchored (widget, TRUE);
priv->title = NULL;
priv->wm_role = NULL;
+1 -1
View File
@@ -158,7 +158,7 @@ gtk_fps_overlay_snapshot (GtkInspectorOverlay *overlay,
double fps;
char *fps_string;
graphene_rect_t bounds;
gboolean has_bounds;
gboolean has_bounds = FALSE;
int width, height;
double overlay_opacity;
+17 -10
View File
@@ -814,28 +814,33 @@ destroy_controller (GtkEventController *controller)
}
static void
on_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
root (GtkWidget *widget)
{
GtkInspectorObjectTree *wt = GTK_INSPECTOR_OBJECT_TREE (widget);
GtkEventController *controller;
GtkWidget *toplevel;
if (previous_toplevel)
g_object_set_data (G_OBJECT (previous_toplevel), "object-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_object_tree_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
if (!GTK_IS_WINDOW (toplevel))
return;
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (toplevel), "object-controller", controller, (GDestroyNotify)destroy_controller);
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), widget);
gtk_widget_add_controller (toplevel, controller);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (wt->priv->search_bar),
toplevel);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (wt->priv->search_bar), toplevel);
}
static void
unroot (GtkWidget *widget)
{
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
g_object_set_data (G_OBJECT (toplevel), "object-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_object_tree_parent_class)->unroot (widget);
}
static gboolean
@@ -1191,6 +1196,9 @@ gtk_inspector_object_tree_class_init (GtkInspectorObjectTreeClass *klass)
object_class->dispose = gtk_inspector_object_tree_dispose;
widget_class->root = root;
widget_class->unroot = unroot;
signals[OBJECT_ACTIVATED] =
g_signal_new ("object-activated",
G_OBJECT_CLASS_TYPE (klass),
@@ -1216,7 +1224,6 @@ gtk_inspector_object_tree_class_init (GtkInspectorObjectTreeClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, type_size_group);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, name_size_group);
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorObjectTree, label_size_group);
gtk_widget_class_bind_template_callback (widget_class, on_hierarchy_changed);
gtk_widget_class_bind_template_callback (widget_class, on_search_changed);
gtk_widget_class_bind_template_callback (widget_class, on_row_activated);
gtk_widget_class_bind_template_callback (widget_class, next_match);
-1
View File
@@ -1,7 +1,6 @@
<interface domain="gtk40">
<template class="GtkInspectorObjectTree" parent="GtkBox">
<property name="orientation">vertical</property>
<signal name="hierarchy-changed" handler="on_hierarchy_changed"/>
<child>
<object class="GtkSearchBar" id="search_bar">
<property name="show-close-button">1</property>
+16 -9
View File
@@ -110,26 +110,31 @@ destroy_controller (GtkEventController *controller)
}
static void
hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
root (GtkWidget *widget)
{
GtkEventController *controller;
GtkWidget *toplevel;
if (previous_toplevel)
g_object_set_data (G_OBJECT (previous_toplevel), "prop-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_prop_list_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
if (!GTK_IS_WINDOW (toplevel))
return;
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (toplevel), "prop-controller", controller, (GDestroyNotify)destroy_controller);
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), widget);
gtk_widget_add_controller (toplevel, controller);
}
static void
unroot (GtkWidget *widget)
{
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
g_object_set_data (G_OBJECT (toplevel), "prop-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_prop_list_parent_class)->unroot (widget);
}
static void
gtk_inspector_prop_list_init (GtkInspectorPropList *pl)
{
@@ -292,6 +297,9 @@ gtk_inspector_prop_list_class_init (GtkInspectorPropListClass *klass)
object_class->set_property = set_property;
object_class->constructed = constructed;
widget_class->root = root;
widget_class->unroot = unroot;
g_object_class_install_property (object_class, PROP_OBJECT_TREE,
g_param_spec_object ("object-tree", "Object Tree", "Object tree",
GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -309,7 +317,6 @@ gtk_inspector_prop_list_class_init (GtkInspectorPropListClass *klass)
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorPropList, tree);
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_callback (widget_class, search_close_clicked);
gtk_widget_class_bind_template_callback (widget_class, hierarchy_changed);
}
/* Like g_strdup_value_contents, but keeps the type name separate */
-1
View File
@@ -12,7 +12,6 @@
</object>
<template class="GtkInspectorPropList" parent="GtkBox">
<property name="orientation">vertical</property>
<signal name="hierarchy-changed" handler="hierarchy_changed"/>
<child>
<object class="GtkScrolledWindow">
<property name="expand">1</property>
+17 -10
View File
@@ -476,28 +476,33 @@ destroy_controller (GtkEventController *controller)
}
static void
on_hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
root (GtkWidget *widget)
{
GtkInspectorResourceList *sl = GTK_INSPECTOR_RESOURCE_LIST (widget);
GtkEventController *controller;
GtkWidget *toplevel;
if (previous_toplevel)
g_object_set_data (G_OBJECT (previous_toplevel), "resource-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_resource_list_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
if (!GTK_IS_WINDOW (toplevel))
return;
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (toplevel), "resource-controller", controller, (GDestroyNotify)destroy_controller);
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), widget);
gtk_widget_add_controller (toplevel, controller);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar),
toplevel);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar), toplevel);
}
static void
unroot (GtkWidget *widget)
{
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
g_object_set_data (G_OBJECT (toplevel), "resource-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_resource_list_parent_class)->unroot (widget);
}
static void
@@ -705,6 +710,9 @@ gtk_inspector_resource_list_class_init (GtkInspectorResourceListClass *klass)
object_class->constructed = constructed;
object_class->finalize = finalize;
widget_class->root = root;
widget_class->unroot = unroot;
g_object_class_install_property (object_class, PROP_BUTTONS,
g_param_spec_object ("buttons", NULL, NULL,
GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -731,7 +739,6 @@ gtk_inspector_resource_list_class_init (GtkInspectorResourceListClass *klass)
gtk_widget_class_bind_template_callback (widget_class, row_activated);
gtk_widget_class_bind_template_callback (widget_class, on_selection_changed);
gtk_widget_class_bind_template_callback (widget_class, on_hierarchy_changed);
gtk_widget_class_bind_template_callback (widget_class, on_search_changed);
gtk_widget_class_bind_template_callback (widget_class, next_match);
gtk_widget_class_bind_template_callback (widget_class, previous_match);
-1
View File
@@ -9,7 +9,6 @@
</object>
<object class="GtkTextBuffer" id="buffer"/>
<template class="GtkInspectorResourceList" parent="GtkBox">
<signal name="hierarchy-changed" handler="on_hierarchy_changed"/>
<child>
<object class="GtkStack" id="stack">
<child>
+17 -10
View File
@@ -327,28 +327,33 @@ destroy_controller (GtkEventController *controller)
}
static void
hierarchy_changed (GtkWidget *widget,
GtkWidget *previous_toplevel)
root (GtkWidget *widget)
{
GtkInspectorStatistics *sl = GTK_INSPECTOR_STATISTICS (widget);
GtkEventController *controller;
GtkWidget *toplevel;
if (previous_toplevel)
g_object_set_data (G_OBJECT (previous_toplevel), "statistics-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->root (widget);
toplevel = gtk_widget_get_toplevel (widget);
if (!GTK_IS_WINDOW (toplevel))
return;
controller = gtk_event_controller_key_new ();
g_object_set_data_full (G_OBJECT (toplevel), "statistics-controller", controller, (GDestroyNotify)destroy_controller);
g_signal_connect (controller, "key-pressed", G_CALLBACK (key_pressed), widget);
gtk_widget_add_controller (toplevel, controller);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar),
toplevel);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (sl->priv->search_bar), toplevel);
}
static void
unroot (GtkWidget *widget)
{
GtkWidget *toplevel;
toplevel = gtk_widget_get_toplevel (widget);
g_object_set_data (G_OBJECT (toplevel), "statistics-controller", NULL);
GTK_WIDGET_CLASS (gtk_inspector_statistics_parent_class)->unroot (widget);
}
static void
@@ -376,7 +381,6 @@ gtk_inspector_statistics_init (GtkInspectorStatistics *sl)
gtk_tree_view_set_search_entry (sl->priv->view, GTK_EDITABLE (sl->priv->search_entry));
gtk_tree_view_set_search_equal_func (sl->priv->view, match_row, sl, NULL);
g_signal_connect (sl, "hierarchy-changed", G_CALLBACK (hierarchy_changed), NULL);
}
static void
@@ -462,6 +466,9 @@ gtk_inspector_statistics_class_init (GtkInspectorStatisticsClass *klass)
object_class->constructed = constructed;
object_class->finalize = finalize;
widget_class->root = root;
widget_class->unroot = unroot;
g_object_class_install_property (object_class, PROP_BUTTON,
g_param_spec_object ("button", NULL, NULL,
GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+17
View File
@@ -850,6 +850,12 @@ gtkversion_cdata.set('GTK_MINOR_VERSION', gtk_minor_version)
gtkversion_cdata.set('GTK_MICRO_VERSION', gtk_micro_version)
gtkversion_cdata.set('GTK_BINARY_AGE', gtk_binary_age)
gtkversion_cdata.set('GTK_INTERFACE_AGE', gtk_interface_age)
gtkversion_cdata.set('GTK_VERSION', gtk_version)
gtkversion_cdata.set('GTK_API_VERSION', gtk_api_version)
if host_machine.system() == 'windows'
gtkversion_cdata.set('EXE_MANIFEST_ARCHITECTURE', '*')
endif
gtkversion = configure_file(input: 'gtkversion.h.in',
output: 'gtkversion.h',
@@ -926,6 +932,17 @@ if win32_enabled
cc.find_library('imm32'),
cc.find_library('setupapi'),
cc.find_library('winmm')]
gtkwin32rc = configure_file(input: 'gtk-win32.rc.body.in',
output: 'gtk-win32.rc.body',
configuration: gtkversion_cdata)
win32_manifest = configure_file(input: 'libgtk4.manifest.in',
output: 'libgtk4.manifest',
configuration: gtkversion_cdata)
win32res = import('windows').compile_resources(gtkwin32rc, include_directories : win32rcinc)
gtk_sources += win32res
else
gtk_deps += [ atkbridge_dep, ]
endif
+1 -1
View File
@@ -901,7 +901,7 @@ if get_option('documentation')
endif
# Keep this in sync with post-install.sh expected arguments
meson.add_install_script('build-aux/meson/post-install.sh',
meson.add_install_script('build-aux/meson/post-install.py',
gtk_api_version,
gtk_binary_version,
gtk_libdir,
+9 -6
View File
@@ -23,6 +23,13 @@ endif
media_subdir = 'gtk-4.0/@0@/media'.format(gtk_binary_version)
media_install_dir = join_paths(get_option('libdir'), media_subdir)
extra_c_args = ['-DGTK_COMPILATION']
# Detect and set symbol visibility
if cc.get_id() == 'msvc'
extra_c_args += ['-D_GLIB_EXTERN=__declspec (dllexport) extern']
endif
if media_backends.contains('ffmpeg')
libavfilter_dep = dependency('libavfilter', version: '>= 6.47.100', required: true)
libavformat_dep = dependency('libavformat', version: '>= 57.41.100', required: true)
@@ -34,9 +41,7 @@ if media_backends.contains('ffmpeg')
shared_module('media-ffmpeg',
'gtkffmediafile.c',
c_args: [
'-DGTK_COMPILATION'
],
c_args: extra_c_args,
dependencies: [ libgtk_dep, ffmpeg_deps ],
install_dir: media_install_dir,
install : true)
@@ -50,9 +55,7 @@ if media_backends.contains('gstreamer')
'gtkgstmediafile.c',
'gtkgstpaintable.c',
'gtkgstsink.c',
c_args: [
'-DGTK_COMPILATION'
],
c_args: extra_c_args,
dependencies: [ libgtk_dep, gstplayer_dep ],
install_dir: media_install_dir,
install : true)
+2415 -4227
View File
File diff suppressed because it is too large Load Diff
+3593 -2387
View File
File diff suppressed because it is too large Load Diff