Compare commits

...

27 Commits

Author SHA1 Message Date
Matthias Clasen
eccbd4fe5f gizmo: Set the name
This helps with debugging.
2019-05-04 18:20:27 +00:00
Matthias Clasen
3b967f1242 widget: Improve warning messages
When we print warnings about a widget, using
gtk_widget_get_name() is slightly better than
G_OBJECT_TYPE_NAME(), since it will give us
the widgets unique name when available.
2019-05-04 18:20:20 +00:00
Asier Sarasua Garmendia
1a4c988a22 Update Basque translation 2019-05-04 09:54:08 +00:00
Mohammed Sadiq
d936a9ae89 docs: fix typo in function name 2019-05-04 15:09:35 +05:30
Matthias Clasen
67e6d1087e emoji chooser: populate incrementally
It takes half a second on my system to initially
populate the Emoji chooser. That is too long. Do
the work in 8 millisecond chunks to give GTK a
chance to get some frames done.
2019-05-04 02:12:02 +00:00
Matthias Clasen
29bafd1e15 docs: Add an actions overview
Add an introduction chapter explaining actions
in detail. Most of this content is taken from
the GAction HowDoI page.
2019-05-04 01:26:45 +00:00
Matthias Clasen
65697e3324 docs: Some additions to the overview
Mention graphene and gsk.
2019-05-04 01:26:45 +00:00
Matthias Clasen
bceca277ea docs: Some updates to the input overview
Remove references to no longer existing apis,
and reword some things. Say surface instead of
window. Start filling out the keyboard section.
2019-05-04 01:26:45 +00:00
Jordi Mas
16c8fb52df Update Catalan translation 2019-05-03 20:54:07 +02:00
Timm Bäder
d702bfe7b7 filechooserbutton: Clean up finalize & destroy 2019-05-03 20:06:25 +02:00
Timm Bäder
596c9a3c0b filechooserbutton: Clear model in destroy()
Since we're destroying priv->chooser right after. We can't wait until
finalize() since clearing the model will try to work with priv->chooser.
2019-05-03 20:06:23 +02:00
Timm Bäder
c675d1c9e1 filechooserbutton: Use a bin layout 2019-05-03 20:06:10 +02:00
Daniel Mustieles
bd490ed511 Updated Spanish translation 2019-05-03 14:36:45 +02:00
Piotr Drąg
bcf180642d Update Polish translation 2019-05-03 13:42:45 +02:00
Piotr Drąg
5882e22f89 Update POTFILES.skip 2019-05-03 13:19:12 +02:00
Matthias Clasen
6f25168db3 Make the newly added test a bit more robust
Follow the style of the other tests and provide
style for both the test and ref.
2019-05-03 02:15:07 +00:00
Matthias Clasen
2a4b5862ae Merge branch 'font-families' into 'master'
Font families

Closes #1854

See merge request GNOME/gtk!813
2019-05-03 01:50:45 +00:00
Matthias Clasen
7037ff8f3d Add a reftest for multiple font families
This tests that listing multiple font
families in the css font-family property
works as expected.
2019-05-03 01:44:29 +00:00
Matthias Clasen
1c9a486d60 css: Use multiple font-family values
Pango API to support this, so we can implement
this very easily.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1854
2019-05-03 01:44:02 +00:00
Matthias Clasen
eb9284e9ca migration guide: Updates
Add recent changes here.
2019-05-02 23:44:57 +00:00
Matthias Clasen
77e3b72b15 NEWS: Updates 2019-05-02 22:20:31 +00:00
Matthias Clasen
05cb7e7412 Merge branch 'event-controller-sensitive' into 'master'
Event controller sensitive

Closes #1861

See merge request GNOME/gtk!812
2019-05-02 21:03:41 +00:00
Matthias Clasen
299422994a fixup! event controller: Don't deliver events to insensitive widgets 2019-05-02 20:20:20 +00:00
Matthias Clasen
b1d90cc171 spin button: Listen for ::cancel on gestures
Otherwise, we keep spinning when we should stop.

Closes: https://gitlab.gnome.org/GNOME/gtk/issues/1861
2019-05-02 15:54:17 -04:00
Matthias Clasen
af2207bc0b widget: Reset controllers when going numb
Reset event controllers when their
widget is going insensitive. This is
the expected behavior.
2019-05-02 15:53:30 -04:00
Matthias Clasen
522bbc182d gesture: Chain up in filter_event
This is the right thing to do.
We want to exclude more events.
2019-05-02 15:53:30 -04:00
Matthias Clasen
65233726f8 event controller: Don't deliver events to insensitive widgets
This is another way to avoid delivering events
to insensitive widgets.
2019-05-02 15:50:44 -04:00
27 changed files with 5334 additions and 3208 deletions

39
NEWS
View File

@@ -12,13 +12,13 @@ Overview of Changes in GTK+ 3.96.0
* The use of global coordinates in GDK apis has been reduced. This
work is still incomplete
* Events have been simplified and are just used for input
- expose events have been replaced by a GdkSurface::render signal
- configure events have been replaced by a GdkSurface::size-changed signal
- map events have been replaced by a GdkSurface::mapped property
- gdk_event_handler_set has been replaced by a GdkSurface::event signal
- key events no longer contain a string
- events on unmapped widgets are ignored
* Events have been simplified and are used just for input
- expose events have been replaced by a GdkSurface::render signal
- configure events have been replaced by a GdkSurface::size-changed signal
- map events have been replaced by a GdkSurface::mapped property
- gdk_event_handler_set has been replaced by a GdkSurface::event signal
- key events no longer contain a string
- events on unmapped widgets are ignored
* Warping the pointer is no longer supported
@@ -36,11 +36,11 @@ Overview of Changes in GTK+ 3.96.0
* A number of list models have been introduced, for internal use
and as public api:
- GtkMapListModel
- GtkSliceListModel
- GtkSortListModel
- GtkSelectionModel
- GtkSingleSelection
- GtkMapListModel
- GtkSliceListModel
- GtkSortListModel
- GtkSelectionModel
- GtkSingleSelection
* Support for tabular menus and combo boxes has been dropped
@@ -70,9 +70,13 @@ Overview of Changes in GTK+ 3.96.0
* GtkWidget can now use a GtkLayoutManager for size allocation.
Layout managers can optionally use layout children holding layout
properties. GtkBinLayout, GtkBoxLayout, GtkGridLayout, GtkFixedLayout
and GtkCustomLayout are currently available, more layout manager
implementations will appear in the future.
properties. A number of layout managers are available:
- GtkBinLayout
- GtkBoxLayout
- GtkGridLayout
- GtkFixedLayout
- GtkCustomLayout
More layout manager implementations will appear in the future.
* GtkAssistant, GtkStack and GtkNotebook now have publicly
accessible page objects for their children. The page objects
@@ -82,8 +86,11 @@ Overview of Changes in GTK+ 3.96.0
child properties have been removed, converted to regular properties,
moved to layout properties or moved to child meta objects.
* GtkListBox has gained a ::show-separators property that gets
translated into a CSS style class.
* A number of X11-specific GtkWindow and GdkSurface apis have been
removed
removed or changed to backend APIs.
* GtkBuilder can specify object-valued properties inline.

View File

@@ -0,0 +1,373 @@
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
]>
<refentry id="chap-actions">
<refmeta>
<refentrytitle>The GTK Action Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>The GTK Action Model</refname>
<refpurpose>
How actions are used in GTK
</refpurpose>
</refnamediv>
<refsect1 id="actions-overview">
<title>Overview of actions in GTK</title>
<para>
This chapter describes in detail how GTK uses actions to connect
activatable UI elements to callbacks. GTK inherits the underlying
architecture of GAction and GMenu for describing abstract actions
and menus from the GIO library.
</para>
<refsect2>
<title>Basics about actions</title>
<para>
A GAction is essentially a way to tell the toolkit about a
piece of functionality in your program, and to give it a name.
</para>
<para>
Actions are purely functional. They do not contain any
presentational information.
</para>
<para>
An action has four pieces of information associated with it:
<itemizedlist>
<listitem><para>
a name as an identifier (usually all-lowercase, untranslated
English string)
</para></listitem>
<listitem><para>
an enabled flag indicating if the action can be activated or
not (like the "sensitive" property on widgets)
</para></listitem>
<listitem><para>
an optional state value, for stateful actions (like a boolean
for toggles)
</para></listitem>
<listitem><para>
an optional parameter type, used when activating the action
</para></listitem>
</itemizedlist>
</para>
<para>
An action supports two operations. You can activate it, which
requires passing a parameter of the correct type
And you can request to change the actions state (for stateful
actions) to a new state value of the correct type.
</para>
<para>
Here are some rules about an action:
<itemizedlist>
<listitem><para>
the name is immutable (in the sense that it will never
change) and it is never %NULL
</para></listitem>
<listitem><para>
the enabled flag can change
</para></listitem>
<listitem><para>
the parameter type is immutable
</para></listitem>
<listitem><para>
the parameter type is optional: it can be %NULL
</para></listitem>
<listitem><para>
if the parameter type is %NULL then action activation must
be done without a parameter (ie: a %NULL GVariant pointer)
</para></listitem>
<listitem><para>
if the parameter type is non-%NULL then the parameter must
have this type
</para></listitem>
<listitem><para>
the state can change, but it cannot change type
</para></listitem>
<listitem><para>
if the action was stateful when it was created, it will
always have a state and it will always have exactly the same
type (such as boolean or string)
</para></listitem>
<listitem><para>
if the action was stateless when it was created, it can never
have a state
</para></listitem>
<listitem><para>
you can only request state changes on stateful actions and it
is only possible to request that the state change to a value
of the same type as the existing state
</para></listitem>
</itemizedlist>
</para>
<para>
An action does not have any sort of presentational information
such as a label, an icon or a way of creating a widget from it.
</para>
</refsect2>
<refsect2>
<title>Action state and parameters</title>
<para>
Most actions in your application will be stateless actions with
no parameters. These typically appear as menu items with no
special decoration. An example is "quit".
</para>
<para>
Stateful actions are used to represent an action which has a
closely-associated state of some kind. A good example is a
"fullscreen" action. For this case, you'd expect to see a
checkmark next to the menu item when the fullscreen option
is active. This is usually called a toggle action, and it has
a boolean state. By convention, toggle actions have no parameter
type for activation: activating the action always toggles the
state.
</para>
<para>
Another common case is to have an action representing a
enumeration of possible values of a given type (typically
string). This is often called a radio action and is usually
represented in the user interface with radio buttons or radio
menu items, or sometimes a combobox. A good example is
"text-justify" with possible values "left", "center", and
"right". By convention, these types of actions have a parameter
type equal to their state type, and activating them with a
particular parameter value is equivalent to changing their
state to that value.
</para>
<para>
This approach to handling radio buttons is different than many
other action systems such as GtkAction. With GAction, there is
only one action for "text-justify" and "left", "center" and
"right" are possible states on that action. There are not three
separate "justify-left", "justify-center" and "justify-right"
actions.
</para>
<para>
The final common type of action is a stateless action with a
parameter. This is typically used for actions like
"open-bookmark" where the parameter to the action would be
the identifier of the bookmark to open.
</para>
<para>
Because some types of actions cannot be invoked without a
parameter, it is often important to specify a parameter when
referring to the action from a place where it will be invoked
(such as from a radio button that sets the state to a particular
value or from a menu item that opens a specific bookmark). In
these contexts, the value used for the action parameter is
typically called the target of the action.
</para>
<para>
Even though toggle actions have a state, they do not have a
parameter. Therefore, a target value is not needed when
referring to them — they will always be toggled on activation.
</para>
<para>
Most APIs that allow using a GAction (such as GMenuModel and
GtkActionable) allow use of detailed action names. This is a
convenient way of specifying an action name and an action target
with a single string.
</para>
<para>
In the case that the action target is a string with no unusual
characters (ie: only alpha-numeric, plus '-' and '.') then you
can use a detailed action name of the form "justify::left" to
specify the justify action with a target of left.
</para>
<para>
In the case that the action target is not a string, or contains
unusual characters, you can use the more general format
"action-name(5)", where the "5" here is any valid text-format
GVariant (ie: a string that can be parsed by g_variant_parse()).
Another example is "open-bookmark('http://gnome.org/')".
</para>
<para>
You can convert between detailed action names and split-out
action names and target values using g_action_parse_detailed_action_name()
and g_action_print_detailed_action_name() but usually you will
not need to. Most APIs will provide both ways of specifying
actions with targets.
</para>
</refsect2>
<refsect2>
<title>Action scopes</title>
<para>
Actions are always scoped to a particular object on which they
operate.
</para>
<para>
In GTK, actions are typically scoped to either an application
or a window, but any widget can have actions associated with it.
</para>
<para>
Actions scoped to windows should be the actions that
specifically impact that window. These are actions like
"fullscreen" and "close", or in the case that a window contains
a document, "save" and "print".
</para>
<para>
Actions that impact the application as a whole rather than one
specific window are scoped to the application. These are actions
like "about" and "preferences".
</para>
<para>
If a particular action is scoped to a window then it is scoped
to a specific window. Another way of saying this: if your
application has a "fullscreen" action that applies to windows
and it has three windows, then it will have three fullscreen
actions: one for each window.
</para>
<para>
Having a separate action per-window allows for each window to
have a separate state for each instance of the action as well
as being able to control the enabled state of the action on a
per-window basis.
</para>
<para>
Actions are added to their relevant scope (application or
window) either using the GActionMap interface, or by using
gtk_widget_insert_action_group().
</para>
</refsect2>
<refsect2>
<title>Action groups and action maps</title>
<para>
Actions rarely occurs in isolation. It is common to have groups
of related actions, which are represented by instances of the
GActionGroup interface.
</para>
<para>
Action maps are a variant of action groups that allow to change
the name of the action as it is looked up. In GTK, the convention
is to add a prefix to the action name to indicate the scope of
the actions, such as "app." for the actions with application scope
or "win." for those with window scope.
</para>
<para>
When referring to actions on a GActionMap only the name of the
action itself is used (ie: "quit", not "app.quit"). The
"app.quit" form is only used when referring to actions from
places like a GMenu or GtkActionable widget where the scope
of the action is not already known.
</para>
<para>
GtkApplication and GtkApplicationWindow implement the GActionMap
interface, so you can just add actions directly to them. For
other widgets, use gtk_widget_insert_action_group() to add
actions to it.
</para>
<para>
If you want to insert several actions at the same time, it is
typically faster and easier to use GActionEntry.
</para>
</refsect2>
<refsect2>
<title>Connecting actions to widgets</title>
<para>
Any widget that implements the GtkActionable interface can
be connected to an action just by setting the ::action-name
property. If the action has a parameter, you will also need
to set the ::action-target property.
Widgets that implement GtkAction include GtkSwitch, GtkButton,
GtkMenuItem and their respective subclasses.
</para>
<para>
Another of obtaining widgets that are connected to actions is
to create a menu using a GMenu menu model. GMenu provides an
abstract way to describe typical menus: nested groups of items
where each item can have a label, and icon, and an action.
</para>
<para>
Typical uses of GMenu inside GTK are to set up an application
menu or menubar with gtk_application_set_app_menu() or
gtk_application_set_menubar(). Another, maybe more common use
is to create a popover for a menubutton, using
gtk_menu_button_set_menu_model().
</para>
<para>
Unlike traditional menus, those created from menu models don't
have keyboard accelerators associated with menu items. Instead,
GtkApplication offers the gtk_application_set_accels_for_action()
API to associate keyboard shortcuts with actions.
</para>
</refsect2>
<refsect2>
<title>Activation</title>
<para>
When a widget with a connected action is activated, GTK finds
the action to activate by walking up the widget hierarchy,
looking for a matching action, ending up at the GtkApplication.
</para>
</refsect2>
<refsect2>
<title>Built-in Actions</title>
<para>
GTK uses actions for its own purposes in a number places. These
built-in actions can sometimes be activated by applications, and
you should avoid naming conflicts with them when creating your
own actions.
<variablelist>
<varlistentry>
<term>default.activate</term>
<listitem><para>Activates the default widget in a context
(typically a GtkWindow, GtkDialog or GtkPopover)
</para></listitem>
</varlistentry>
</variablelist>
</para>
</refsect2>
</refsect1>
</refentry>

View File

@@ -12,7 +12,7 @@
<refnamediv>
<refname>The GTK Drawing Model</refname>
<refpurpose>
The GTK drawing model in detail
How widgets draw
</refpurpose>
</refnamediv>

View File

@@ -24,8 +24,9 @@
<xi:include href="xml/getting_started.xml"/>
<xi:include href="resources.sgml" />
<xi:include href="xml/question_index.sgml" />
<xi:include href="drawing-model.xml" />
<xi:include href="xml/drawing-model.xml" />
<xi:include href="xml/input-handling.xml" />
<xi:include href="xml/actions.xml" />
</part>
<part id="gtkobjects">

View File

@@ -4,15 +4,15 @@
]>
<refentry id="chap-input-handling">
<refmeta>
<refentrytitle>The GTK Input and Event Handling Model</refentrytitle>
<refentrytitle>The GTK Input Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>The GTK Input and Event Handling Model</refname>
<refname>The GTK Input Model</refname>
<refpurpose>
GTK input and event handling in detail
input and event handling in detail
</refpurpose>
</refnamediv>
@@ -52,13 +52,12 @@
with any pointing device or keyboard.
</para>
<!-- input events: button, touch, key, motion, etc -->
<para>
When a user interacts with an input device (e.g. moves a mouse or presses
a key on the keyboard), GTK receives events from the windowing system.
These are typically directed at a specific window - for pointer events,
the window under the pointer (grabs complicate this), for keyboard events,
the window with the keyboard focus.
These are typically directed at a specific surface - for pointer events,
the surface under the pointer (grabs complicate this), for keyboard events,
the surface with the keyboard focus.
</para>
<para>
GDK translates these raw windowing system events into #GdkEvents.
@@ -81,9 +80,10 @@
</simplelist>
</para>
<para>
When GTK is initialized, it sets up an event handler function with
gdk_event_handler_set(), which receives all of these input events
(as well as others, for instance window management related events).
When GTK creates a GdkSurface, it connects to the ::event signal
on it, which receives all of these input events. Surfaces have
have signals and properties, e.g. to deal with window management
related events.
</para>
</refsect2>
@@ -91,8 +91,8 @@
<title>Event propagation</title>
<para>
For widgets which have a #GdkSurface set, events are received from the
windowing system and passed to gtk_main_do_event(). See its documentation
The function which initially receives input events on the GTK
side is gtk_main_do_event(). See its documentation
for details of what it does: compression of enter/leave events,
identification of the widget receiving the event, pushing the event onto a
stack for gtk_get_current_event(), and propagating the event to the
@@ -120,62 +120,55 @@
<para>
An event is propagated to a widget using gtk_propagate_event().
Propagation differs between event types: key events (%GDK_KEY_PRESS,
%GDK_KEY_RELEASE) are delivered to the top-level #GtkWindow; other events
are propagated down and up the widget hierarchy in three phases (see
#GtkPropagationPhase).
Propagation goes down and up the widget hierarchy in three phases
(see #GtkPropagationPhase) towards a target widget.
</para>
<para>
For key events, the top-level windows default #GtkWindow::key-press-event
and #GtkWindow::key-release-event signal handlers handle mnemonics and
accelerators first. Other key presses are then passed to
gtk_window_propagate_key_event() which propagates the event upwards from
the windows current focus widget (gtk_window_get_focus()) to the
top-level.
For key events, the top-level window gets a first shot at activating
mnemonics and accelerators. If that does not consume the events,
the target widget for event propagation is window's current focus
widget (see gtk_window_get_focus()).
</para>
<para>
For other events, in the first phase (the “capture” phase) the event is
delivered to each widget from the top-most (for example, the top-level
For pointer events, the target widget is determined by picking
the widget at the events coordinates (see gtk_window_pick()).
</para>
<para>In the first phase (the “capture” phase) the event is
delivered to each widget from the top-most (the top-level
#GtkWindow or grab widget) down to the target #GtkWidget.
<link linkend="event-controllers-and-gestures">Gestures</link> that are
attached with %GTK_PHASE_CAPTURE get a chance to react to the event.
<link linkend="event-controllers-and-gestures">Event
controllers</link> that are attached with %GTK_PHASE_CAPTURE
get a chance to react to the event.
</para>
<para>
After the “capture” phase, the widget that was intended to be the
destination of the event will run gestures attached to it with
%GTK_PHASE_TARGET. This is known as the “target” phase, and only
happens on that widget.
destination of the event will run event controllers attached to
it with %GTK_PHASE_TARGET. This is known as the “target” phase,
and only happens on that widget.
</para>
<para>
Next, the #GtkWidget::event signal is emitted.
Handling these signals was the primary way to handle input in GTK widgets
before gestures were introduced. The signal is emitted from
the target widget up to the top-level, as part of the “bubble” phase.
In the last phase (the “bubble” phase), the event is delivered
to each widget from the target to the top-most, and event
controllers attached with %GTK_PHASE_BUBBLE are run.
</para>
<para>
The default handlers for the event signals send the event
to gestures that are attached with %GTK_PHASE_BUBBLE. Therefore,
gestures in the “bubble” phase are only used if the widget does
not have its own event handlers, or takes care to chain up to the
default #GtkWidget handlers.
Events are not delivered to a widget which is insensitive or
unmapped.
</para>
<para>
Events are not delivered to a widget which is insensitive or unmapped.
</para>
<para>
Any time during the propagation phase, a widget may indicate that a
received event was consumed and propagation should therefore be stopped.
In traditional event handlers, this is hinted by returning %GDK_EVENT_STOP.
If gestures are used, this may happen when the widget tells the gesture
to claim the event touch sequence (or the pointer events) for its own. See the
"gesture states" section below to know more of the latter.
Any time during the propagation phase, a controller may indicate
that a received event was consumed and propagation should
therefore be stopped. If gestures are used, this may happen
when the gesture claims the event touch sequence (or the
pointer events) for its own. See the “gesture states” section
below to learn more about gestures and sequences.
</para>
</refsect2>
@@ -183,27 +176,10 @@
<title>Touch events</title>
<para>
Touch events are emitted as events of type %GDK_TOUCH_BEGIN, %GDK_TOUCH_UPDATE or
%GDK_TOUCH_END, those events contain an “event sequence” that univocally identifies
the physical touch until it is lifted from the device.
</para>
<para>
On some windowing platforms, multitouch devices perform pointer emulation, this works
by granting a “pointer emulating” hint to one of the currently interacting touch
sequences, which will be reported on every #GdkEventTouch event from that sequence. By
default, if a widget didn't request touch events by setting %GDK_TOUCH_MASK on its
event mask and didn't override #GtkWidget::touch-event, GTK will transform these
“pointer emulating” events into semantically similar #GdkEventButton and #GdkEventMotion
events. Depending on %GDK_TOUCH_MASK being in the event mask or not, non-pointer-emulating
sequences could still trigger gestures or just get filtered out, regardless of the widget
not handling those directly.
</para>
<para>
If the widget sets %GDK_TOUCH_MASK on its event mask and doesn't chain up on
#GtkWidget::touch-event, only touch events will be received, and no pointer emulation
will be performed.
Touch events are emitted as events of type %GDK_TOUCH_BEGIN,
%GDK_TOUCH_UPDATE or %GDK_TOUCH_END, those events contain an
“event sequence” that univocally identifies the physical touch
until it is lifted from the device.
</para>
</refsect2>
@@ -211,43 +187,66 @@
<title>Grabs</title>
<para>
Grabs are a method to claim all input events from a device, they happen
either implicitly on pointer and touch devices, or explicitly. Implicit grabs
happen on user interaction, when a #GdkEventButtonPress happens, all events from
then on, until after the corresponding #GdkEventButtonRelease, will be reported
to the widget that got the first event. Likewise, on touch events, every
#GdkEventSequence will deliver only events to the widget that received its
%GDK_TOUCH_BEGIN event.
Grabs are a method to claim all input events from a device,
they happen either implicitly on pointer and touch devices,
or explicitly. Implicit grabs happen on user interaction, when
a #GdkEventButtonPress happens, all events from then on, until
after the corresponding #GdkEventButtonRelease, will be reported
to the widget that got the first event. Likewise, on touch events,
every #GdkEventSequence will deliver only events to the widget
that received its %GDK_TOUCH_BEGIN event.
</para>
<para>
Explicit grabs happen programatically (both activation and deactivation),
and can be either system-wide (GDK grabs) or application-wide (GTK grabs).
On the windowing platforms that support it, GDK grabs will prevent any
interaction with any other application/window/widget than the grabbing one,
whereas GTK grabs will be effective only within the application (across all
its windows), still allowing for interaction with other applications.
Explicit grabs happen programatically (both activation and
deactivation), and can be either system-wide (GDK grabs) or
application-wide (GTK grabs). On the windowing platforms that
support it, GDK grabs will prevent any interaction with any other
application/window/widget than the grabbing one, whereas GTK grabs
will be effective only within the application (across all its
windows), still allowing for interaction with other applications.
</para>
<para>
But one important aspect of grabs is that they may potentially happen at any
point somewhere else, even while the pointer/touch device is already grabbed.
This makes it necessary for widgets to handle the cancellation of any ongoing
interaction. Depending on whether a GTK or GDK grab is causing this, the
widget will respectively receive a #GtkWidget::grab-notify signal, or a
But one important aspect of grabs is that they may potentially
happen at any point somewhere else, even while the pointer/touch
device is already grabbed. This makes it necessary for widgets to
handle the cancellation of any ongoing interaction. Depending on
whether a GTK or GDK grab is causing this, the widget will
respectively receive a #GtkWidget::grab-notify signal, or a
#GdkEventGrabBroken event.
</para>
<para>
On gestures, these signals are handled automatically, causing the gesture
to cancel all tracked pointer/touch events, and signal the end of recognition.
On gestures, these signals are handled automatically, causing the
gesture to cancel all tracked pointer/touch events, and signal
the end of recognition.
</para>
</refsect2>
<refsect2>
<title>Keyboard input</title>
<!-- focus, tab, directional navigation -->
<para>
Every #GtkWindow maintains a single focus location (in
the ::focus-widget property). The focus widget is the
target widget for key events sent to the window. Only
widgets which have ::can-focus set to %TRUE can become
the focus. Typically these are input controls such as
entries or text fields, but e.g. buttons can take the
focus too.
</para>
<para>
Input widgets can be given the focus by clicking on them,
but focus can also be moved around with certain key
events (this is known as “keyboard navigation”). GTK
reserves the Tab key to move the focus to the next location,
and Shift-Tab to move it back to the previous one. In addition
many containers allow “directional navigation” with the
arrow keys.
</para>
<!-- mnemonics, accelerators, bindings -->
</refsect2>
@@ -255,37 +254,43 @@
<title>Event controllers and gestures</title>
<para>
Event controllers are standalone objects that can perform specific actions
upon received #GdkEvents. These are tied to a #GtkWidget, and can be told of
the event propagation phase at which they will manage the events.
Event controllers are standalone objects that can perform
specific actions upon received #GdkEvents. These are tied
to a #GtkWidget, and can be told of the event propagation
phase at which they will manage the events.
</para>
<para>
Gestures are a set of specific controllers that are prepared to handle pointer
and/or touch events, each gestures implementation attempts to recognize specific
actions out the received events, notifying of the state/progress accordingly to
let the widget react to those. On multi-touch gestures, every interacting touch
sequence will be tracked independently.
Gestures are a set of specific controllers that are prepared
to handle pointer and/or touch events, each gesture
implementation attempts to recognize specific actions out the
received events, notifying of the state/progress accordingly to
let the widget react to those. On multi-touch gestures, every
interacting touch sequence will be tracked independently.
</para>
<para>
Being gestures “simple” units, it is not uncommon to tie several together to
perform higher level actions, grouped gestures handle the same event sequences
simultaneously, and those sequences share a same state across all grouped
Since gestures are “simple” units, it is not uncommon to tie
several together to perform higher level actions, grouped
gestures handle the same event sequences simultaneously, and
those sequences share a same state across all grouped
gestures. Some examples of grouping may be:
<simplelist>
<member>
A “drag” and a “swipe” gestures may want grouping. The former will report
events as the dragging happens, the latter will tell the swipe X/Y velocities
only after gesture has finished.
A “drag” and a “swipe” gestures may want grouping.
The former will report events as the dragging happens,
the latter will tell the swipe X/Y velocities only after
recognition has finished.
</member>
<member>
Grouping a “drag” gesture with a “pan” gesture will only effectively allow
dragging in the panning orientation, as both gestures share state.
Grouping a “drag” gesture with a “pan” gesture will only
effectively allow dragging in the panning orientation, as
both gestures share state.
</member>
<member>
If “press” and “long press” are wanted simultaneously, those would need grouping.
If “press” and “long press” are wanted simultaneously,
those would need grouping.
</member>
</simplelist>
</para>
@@ -294,34 +299,39 @@
<refsect2>
<title>Gesture states</title>
<para>
Gestures have a notion of “state” for each individual touch sequence. When events
from a touch sequence are first received, the touch sequence will have “none” state,
this means the touch sequence is being handled by the gesture to possibly trigger
Gestures have a notion of “state” for each individual touch
sequence. When events from a touch sequence are first received,
the touch sequence will have “none” state, this means the touch
sequence is being handled by the gesture to possibly trigger
actions, but the event propagation will not be stopped.
</para>
<para>
When the gesture enters recognition, or at a later point in time, the widget may
choose to claim the touch sequences (individually or as a group), hence stopping
event propagation after the event is run through every gesture in that widget and
propagation phase. Anytime this happens, the touch sequences are cancelled downwards
the propagation chain, to let these know that no further events will be sent.
When the gesture enters recognition, or at a later point in time,
the widget may choose to claim the touch sequences (individually
or as a group), hence stopping event propagation after the event
is run through every gesture in that widget and propagation phase.
Anytime this happens, the touch sequences are cancelled downwards
the propagation chain, to let these know that no further events
will be sent.
</para>
<para>
Alternatively, or at a later point in time, the widget may choose to deny the touch
sequences, thus letting those go through again in event propagation. When this happens
in the capture phase, and if there are no other claiming gestures in the widget,
Alternatively, or at a later point in time, the widget may choose
to deny the touch sequences, thus letting those go through again
in event propagation. When this happens in the capture phase, and
if there are no other claiming gestures in the widget,
a %GDK_TOUCH_BEGIN/%GDK_BUTTON_PRESS event will be emulated and
propagated downwards, in order to preserve consistency.
</para>
<para>
Grouped gestures always share the same state for a given touch sequence, so setting
the state on one does transfer the state to the others. They also are mutually exclusive,
within a widget there may be only one gesture group claiming a given sequence. If
another gesture group claims later that same sequence, the first group will deny the
sequence.
Grouped gestures always share the same state for a given touch
sequence, so setting the state on one does transfer the state to
the others. They also are mutually exclusive, within a widget
there may be only one gesture group claiming a given sequence.
If another gesture group claims later that same sequence, the
first group will deny the sequence.
</para>
</refsect2>

View File

@@ -333,6 +333,7 @@ images = [
]
content_files = [
'actions.xml',
'broadway.xml',
'building.sgml',
'compiling.sgml',
@@ -368,6 +369,7 @@ content_files = [
]
expand_content_files = [
'actions.xml',
'compiling.sgml',
'drawing-model.xml',
'glossary.xml',

View File

@@ -11,7 +11,7 @@
compared to GTK 3.x. Thankfully, most of the changes are not hard
to adapt to and there are a number of steps that you can take to
prepare your GTK 3.x application for the switch to GTK 4. After
that, there's a small number of adjustments that you may have to do
that, there's a number of adjustments that you may have to do
when you actually switch your application to build against GTK 4.
</para>
@@ -22,7 +22,7 @@
The steps outlined in the following sections assume that your
application is working with GTK 3.24, which is the final stable
release of GTK 3.x. It includes all the necessary APIs and tools
to help you port your application to GTK 4. If you are still using
to help you port your application to GTK 4. If you are using
an older version of GTK 3.x, you should first get your application
to build and work with the latest minor release in the 3.24 series.
</para>
@@ -84,9 +84,9 @@
</para>
<para>
GTK 4 also removes the GDK_WA_VISUAL flag, and always uses
an RGBA visual for windows. To prepare your code for this,
use gdk_window_set_visual (gdk_screen_get_rgba_visual ()) after
creating your window.
an RGBA visual for windows. To prepare your code for this, use
<literal>gdk_window_set_visual (gdk_screen_get_rgba_visual ())</literal>
after creating your window.
</para>
<para>
GTK 4 also removes the GDK_WA_WMCLASS flag. If you need this
@@ -110,7 +110,7 @@
<section>
<title>Stop using GtkBox:padding, GtkBox:fill and GtkBox:expand</title>
<para>
GTK4 removes these #GtkBox child properties, so you should not use them.
GTK 4 removes these #GtkBox child properties, so you should not use them.
You can replace GtkBox:padding using the #GtkWidget:margin properties
on your #GtkBox child widgets.
</para>
@@ -172,35 +172,30 @@
<section>
<title>Stop using GtkWidget event signals</title>
<para>
Event controllers and #GtkGestures replace event signals in GTK 4. They
have been backported to GTK 3.x so you can prepare for this change.
Event controllers and #GtkGestures replace event signals in GTK 4.
They have been backported to GTK 3.x so you can prepare for this change.
</para>
</section>
<section>
<title>Set a proper app_id</title>
<title>Set a proper application ID</title>
<para>
In GTK4 we want the application's #GApplication
In GTK 4 we want the application's #GApplication
'application-id' (and therefore the D-Bus name), the desktop
file basename and Wayland's xdg-shell app_id to match. In
order to achieve this with GTK3 call g_set_prgname() with the same
application id you passed to #GtkApplication. Rename your
desktop files to match the application id if needed.
order to achieve this with GTK 3.x call g_set_prgname() with the same
application ID you passed to #GtkApplication. Rename your
desktop files to match the application ID if needed.
</para>
<para>
The call to g_set_prgname() can be removed once you fully migrated
to GTK4.
to GTK 4.
</para>
</section>
<section>
<title>Stop using GtkBox's pack-type child property</title>
<para>
In order to improve performance and simplify the widget, GtkBox lost its
'pack-type' child property. In GTK4, every GtkBox instance has a simple
list of child widgets that it allocates from start to end.
The old behavior of pack-type=END can be emulated by simply making the
box child in the center hexpand and right-align the ones at the end.
You should be aware that changing the application ID makes your
application appear as a new, different app to application installers.
You should consult the appstream documentation for best practices
around renaming applications.
</para>
</section>
@@ -216,6 +211,17 @@
have been either impossible or impractical.
</para>
<section>
<title>Convert your ui files</title>
<para>
A number of the changes outlined below affect .ui files. The
gtk4-builder-tool simplify command can perform many of the
necessary changes automatically, when called with the --3to4
option. You should always review the resulting changes.
</para>
</section>
<section>
<title>Stop using GdkScreen</title>
<para>
@@ -301,9 +307,9 @@
</section>
<section>
<title>Adapt to coordinate api changes</title>
<title>Adapt to coordinate API changes</title>
<para>
A number of coordinate apis in GTK 3 had _double variants:
A number of coordinate APIs in GTK 3 had _double variants:
gdk_device_get_position(), gdk_device_get_surface_at_position(),
gdk_surface_get_device_position(). These have been changed to use
doubles, and the _double variants have been removed. Update your
@@ -395,6 +401,10 @@
their #GError argument. If you want to handle CSS loading errors,
use the #GtkCssProvider::parsing-error signal instead.
</para>
<para>
gtk_css_provider_get_named() has been replaced by
gtk_css_provider_load_named().
</para>
</section>
<section>
@@ -411,7 +421,7 @@
<para>
GTK 3 used five different virtual functions in GtkWidget to
implement size requisition, namely the gtk_widget_get_preferred_width()
family of functions. To simplify widget implementations, GTK4 uses
family of functions. To simplify widget implementations, GTK 4 uses
only one virtual function, GtkWidgetClass::measure() that widgets
have to implement.
</para>
@@ -640,7 +650,7 @@
</section>
<section>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry adn GtkSpinButton</title>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry and GtkSpinButton</title>
<para>
The GtkEditable has been made more useful, and the core functionality of
GtkEntry has been broken out as a GtkText widget. GtkEntry, GtkSearchEntry,
@@ -675,6 +685,77 @@
of the existing GtkFixed container widget.
</para>
</section>
<section>
<title>Adapt to search entry changes</title>
<para>
The way search entries are connected to global events has changed;
gtk_search_entry_handle_event() has been dropped and replaced by
gtk_search_entry_set_key_capture_widget() and
gtk_event_controller_key_forward().
</para>
</section>
<section>
<title>Stop using child properties</title>
<para>
GtkContainer no longer provides facilities for defining and using
child properties. If you have custom widgets using child properties,
they will have to be converted either to layout properties provided
by a layout manager (if they are layout-related), or handled in
some other way. One possibility is to use child meta objects,
as seen with GtkAssistantPage, GtkStackPage and the like.
</para>
</section>
<section>
<title>Stop using tabular menus</title>
<para>
Tabular menus were rarely used and complicated the menu code,
so they have been removed. If you need complex layout in menu-like
popups, consider using a #GtkPopover instead.
</para>
</section>
<section>
<title>Stop using gtk_menu_set_display()</title>
<para>
This function has been removed. Menus should always be
attached to a widget and get their display that way.
</para>
</section>
<section>
<title>Stop using gtk_window_activate_default()</title>
<para>
The handling of default widgets has been changed, and activating
the default now works by calling gtk_widget_activate_default()
on the widget that caused the activation.
</para>
<para>
If you have a custom widget that wants to override the default
handling, you can provide an implementation of the default.activate
action in your widgets' action groups.
</para>
</section>
<section>
<title>Stop setting ::has-default and ::has-focus in .ui files</title>
<para>
The special handling for the ::has-default and ::has-focus properties
has been removed. If you want to define the initial focus or the
the default widget in a .ui file, set the ::default-widget or
::focus-widget properties of the toplevel window.
</para>
</section>
<section>
<title>Stop using the GtkWidget::display-changed signal</title>
<para>
To track the current display, use the GtkWidget::root property
instead.
</para>
</section>
</section>
</chapter>

View File

@@ -79,12 +79,30 @@ Use a GdkPixbuf in combination with GtkImage to display images.
</para></listitem>
</varlistentry>
<varlistentry>
<term>graphene</term>
<listitem><para>
This is a small library which provides vector and matrix datatypes
and operations. graphene provides optimized implementations using
various SIMD instruction sets such as SSE.
</para></listitem>
</varlistentry>
<varlistentry>
<term>GDK</term>
<listitem><para>
GDK is the abstraction layer that allows GTK to support multiple
windowing systems. GDK provides window system facilities on X11, Windows,
and OS X.
windowing systems. GDK provides window system facilities on Wayland,
X11, Windows, and OS X.
</para></listitem>
</varlistentry>
<varlistentry>
<term>GSK</term>
<listitem><para>
GSK is a library for creating a scene graph from render nodes,
and rendering it using different rendering APIs. GSK provides renderers
for OpenGL, Vulkan and cairo.
</para></listitem>
</varlistentry>

View File

@@ -1143,8 +1143,18 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
v = (* query_func) (GTK_CSS_PROPERTY_FONT_FAMILY, query_data);
if (v)
{
/* xxx: Can we set all the families here somehow? */
pango_font_description_set_family (description, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0)));
int i;
GString *s = g_string_new ("");
for (i = 0; i < _gtk_css_array_value_get_n_values (v); i++)
{
if (i > 0)
g_string_append (s, ",");
g_string_append (s, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, i)));
}
pango_font_description_set_family (description, s->str);
g_string_free (s, TRUE);
}
v = (* query_func) (GTK_CSS_PROPERTY_FONT_SIZE, query_data);

View File

@@ -70,6 +70,9 @@ struct _GtkEmojiChooser
EmojiSection flags;
GVariant *data;
GtkWidget *box;
GVariantIter *iter;
guint populate_idle;
GSettings *settings;
};
@@ -92,6 +95,9 @@ gtk_emoji_chooser_finalize (GObject *object)
{
GtkEmojiChooser *chooser = GTK_EMOJI_CHOOSER (object);
if (chooser->populate_idle)
g_source_remove (chooser->populate_idle);
g_variant_unref (chooser->data);
g_object_unref (chooser->settings);
@@ -399,47 +405,68 @@ add_emoji (GtkWidget *box,
gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
}
static void
populate_emoji_chooser (GtkEmojiChooser *chooser)
static gboolean
populate_emoji_chooser (gpointer data)
{
GBytes *bytes = NULL;
GVariantIter iter;
GtkEmojiChooser *chooser = data;
GVariant *item;
GtkWidget *box;
guint64 start, now;
bytes = g_resources_lookup_data ("/org/gtk/libgtk/emoji/emoji.data", 0, NULL);
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(auss)"), bytes, TRUE));
start = g_get_monotonic_time ();
g_variant_iter_init (&iter, chooser->data);
box = chooser->people.box;
while ((item = g_variant_iter_next_value (&iter)))
if (!chooser->data)
{
GBytes *bytes = g_resources_lookup_data ("/org/gtk/libgtk/emoji/emoji.data", 0, NULL);
chooser->data = g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE ("a(auss)"), bytes, TRUE));
g_bytes_unref (bytes);
}
if (!chooser->iter)
{
chooser->iter = g_variant_iter_new (chooser->data);
chooser->box = chooser->people.box;
}
while ((item = g_variant_iter_next_value (chooser->iter)))
{
const char *name;
g_variant_get_child (item, 1, "&s", &name);
if (strcmp (name, chooser->body.first) == 0)
box = chooser->body.box;
chooser->box = chooser->body.box;
else if (strcmp (name, chooser->nature.first) == 0)
box = chooser->nature.box;
chooser->box = chooser->nature.box;
else if (strcmp (name, chooser->food.first) == 0)
box = chooser->food.box;
chooser->box = chooser->food.box;
else if (strcmp (name, chooser->travel.first) == 0)
box = chooser->travel.box;
chooser->box = chooser->travel.box;
else if (strcmp (name, chooser->activities.first) == 0)
box = chooser->activities.box;
chooser->box = chooser->activities.box;
else if (strcmp (name, chooser->objects.first) == 0)
box = chooser->objects.box;
chooser->box = chooser->objects.box;
else if (strcmp (name, chooser->symbols.first) == 0)
box = chooser->symbols.box;
chooser->box = chooser->symbols.box;
else if (strcmp (name, chooser->flags.first) == 0)
box = chooser->flags.box;
chooser->box = chooser->flags.box;
add_emoji (box, FALSE, item, 0, chooser);
add_emoji (chooser->box, FALSE, item, 0, chooser);
g_variant_unref (item);
now = g_get_monotonic_time ();
if (now > start + 8000)
return G_SOURCE_CONTINUE;
}
g_bytes_unref (bytes);
/* We scroll to the top on show, so check the right button for the 1st time */
gtk_widget_set_state_flags (chooser->recent.button, GTK_STATE_FLAG_CHECKED, FALSE);
g_variant_iter_free (chooser->iter);
chooser->iter = NULL;
chooser->box = NULL;
chooser->populate_idle = 0;
return G_SOURCE_REMOVE;
}
static void
@@ -651,11 +678,9 @@ gtk_emoji_chooser_init (GtkEmojiChooser *chooser)
setup_section (chooser, &chooser->symbols, "ATM sign", "emoji-symbols-symbolic");
setup_section (chooser, &chooser->flags, "chequered flag", "emoji-flags-symbolic");
populate_emoji_chooser (chooser);
populate_recent_section (chooser);
/* We scroll to the top on show, so check the right button for the 1st time */
gtk_widget_set_state_flags (chooser->recent.button, GTK_STATE_FLAG_CHECKED, FALSE);
chooser->populate_idle = g_idle_add (populate_emoji_chooser, chooser);
}
static void

View File

@@ -73,6 +73,18 @@ gtk_event_controller_unset_widget (GtkEventController *self)
priv->widget = NULL;
}
static gboolean
gtk_event_controller_filter_event_default (GtkEventController *self,
const GdkEvent *event)
{
GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
if (priv->widget)
return !gtk_widget_is_sensitive (priv->widget);
return FALSE;
}
static gboolean
gtk_event_controller_handle_event_default (GtkEventController *self,
const GdkEvent *event)
@@ -128,7 +140,7 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
klass->set_widget = gtk_event_controller_set_widget;
klass->unset_widget = gtk_event_controller_unset_widget;
klass->filter_event = gtk_event_controller_handle_event_default;
klass->filter_event = gtk_event_controller_filter_event_default;
klass->handle_event = gtk_event_controller_handle_event_default;
object_class->set_property = gtk_event_controller_set_property;

View File

@@ -49,6 +49,7 @@
#include "gtkfilechooserprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkmarshalers.h"
#include "gtkbinlayout.h"
#include "gtkfilechooserbutton.h"
@@ -339,41 +340,6 @@ G_DEFINE_TYPE_WITH_CODE (GtkFileChooserButton, gtk_file_chooser_button, GTK_TYPE
G_IMPLEMENT_INTERFACE (GTK_TYPE_FILE_CHOOSER,
gtk_file_chooser_button_file_chooser_iface_init))
static void
gtk_file_chooser_button_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
gtk_widget_measure (priv->child, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
gtk_file_chooser_button_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (widget);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
gtk_widget_size_allocate (priv->child,
&(GtkAllocation) {
0, 0,
width, height
}, baseline);
}
static void
gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
{
@@ -397,8 +363,6 @@ gtk_file_chooser_button_class_init (GtkFileChooserButtonClass * class)
widget_class->root = gtk_file_chooser_button_root;
widget_class->mnemonic_activate = gtk_file_chooser_button_mnemonic_activate;
widget_class->state_flags_changed = gtk_file_chooser_button_state_flags_changed;
widget_class->measure = gtk_file_chooser_button_measure;
widget_class->size_allocate = gtk_file_chooser_button_size_allocate;
/**
* GtkFileChooserButton::file-set:
@@ -533,6 +497,8 @@ gtk_file_chooser_button_init (GtkFileChooserButton *button)
target_list,
GDK_ACTION_COPY);
gdk_content_formats_unref (target_list);
gtk_widget_set_layout_manager (GTK_WIDGET (button), gtk_bin_layout_new ());
}
@@ -1022,17 +988,8 @@ gtk_file_chooser_button_finalize (GObject *object)
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
if (priv->selection_while_inactive)
g_object_unref (priv->selection_while_inactive);
if (priv->current_folder_while_inactive)
g_object_unref (priv->current_folder_while_inactive);
if (priv->model)
{
model_remove_rows (button, 0, gtk_tree_model_iter_n_children (priv->model, NULL));
g_object_unref (priv->model);
}
g_clear_object (&priv->selection_while_inactive);
g_clear_object (&priv->current_folder_while_inactive);
gtk_widget_unparent (priv->button);
gtk_widget_unparent (priv->combo_box);
@@ -1066,31 +1023,22 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
GSList *l;
if (priv->dialog != NULL)
if (priv->model)
{
gtk_widget_destroy (priv->dialog);
priv->dialog = NULL;
model_remove_rows (button, 0, gtk_tree_model_iter_n_children (priv->model, NULL));
g_clear_object (&priv->model);
}
g_clear_pointer (&priv->dialog, gtk_widget_destroy);
if (priv->native)
{
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
g_clear_object (&priv->native);
}
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
priv->chooser = NULL;
g_clear_object (&priv->native);
priv->chooser = NULL; /* Was either priv->dialog or priv->native! */
if (priv->dnd_select_folder_cancellable)
{
g_cancellable_cancel (priv->dnd_select_folder_cancellable);
priv->dnd_select_folder_cancellable = NULL;
}
if (priv->update_button_cancellable)
{
g_cancellable_cancel (priv->update_button_cancellable);
priv->update_button_cancellable = NULL;
}
g_clear_pointer (&priv->dnd_select_folder_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->update_button_cancellable, g_cancellable_cancel);
if (priv->change_icon_theme_cancellables)
{
@@ -1103,24 +1051,15 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
priv->change_icon_theme_cancellables = NULL;
}
if (priv->filter_model)
{
g_object_unref (priv->filter_model);
priv->filter_model = NULL;
}
g_clear_object (&priv->filter_model);
if (priv->fs)
{
g_signal_handler_disconnect (priv->fs, priv->fs_volumes_changed_id);
g_object_unref (priv->fs);
priv->fs = NULL;
g_clear_object (&priv->fs);
}
if (priv->bookmarks_manager)
{
_gtk_bookmarks_manager_free (priv->bookmarks_manager);
priv->bookmarks_manager = NULL;
}
g_clear_pointer (&priv->bookmarks_manager, _gtk_bookmarks_manager_free);
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->destroy (widget);
}

View File

@@ -628,7 +628,10 @@ gtk_gesture_filter_event (GtkEventController *controller,
* subclasses which punch the holes in for the events
* they can possibly handle.
*/
return EVENT_IS_TOUCHPAD_GESTURE (event);
if (EVENT_IS_TOUCHPAD_GESTURE (event))
return FALSE;
return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_parent_class)->filter_event (controller, event);
}
static gboolean

View File

@@ -107,6 +107,7 @@ gtk_gizmo_new (const char *css_name,
{
GtkGizmo *gizmo = GTK_GIZMO (g_object_new (GTK_TYPE_GIZMO,
"css-name", css_name,
"name", css_name,
NULL));
gizmo->measure_func = measure_func;

View File

@@ -809,6 +809,14 @@ button_released_cb (GtkGestureMultiPress *gesture,
}
}
static void
button_cancel_cb (GtkGesture *gesture,
GdkEventSequence *sequence,
GtkSpinButton *spin_button)
{
gtk_spin_button_stop_spinning (spin_button);
}
static void
key_controller_key_released (GtkEventControllerKey *key,
guint keyval,
@@ -886,6 +894,7 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
GTK_PHASE_CAPTURE);
g_signal_connect (gesture, "pressed", G_CALLBACK (button_pressed_cb), spin_button);
g_signal_connect (gesture, "released", G_CALLBACK (button_released_cb), spin_button);
g_signal_connect (gesture, "cancel", G_CALLBACK (button_cancel_cb), spin_button);
gtk_widget_add_controller (GTK_WIDGET (priv->down_button), GTK_EVENT_CONTROLLER (gesture));
priv->up_button = gtk_button_new ();
@@ -902,6 +911,7 @@ gtk_spin_button_init (GtkSpinButton *spin_button)
GTK_PHASE_CAPTURE);
g_signal_connect (gesture, "pressed", G_CALLBACK (button_pressed_cb), spin_button);
g_signal_connect (gesture, "released", G_CALLBACK (button_released_cb), spin_button);
g_signal_connect (gesture, "cancel", G_CALLBACK (button_cancel_cb), spin_button);
gtk_widget_add_controller (GTK_WIDGET (priv->up_button), GTK_EVENT_CONTROLLER (gesture));
gtk_spin_button_set_adjustment (spin_button, NULL);

View File

@@ -6363,6 +6363,7 @@ gtk_widget_set_sensitive (GtkWidget *widget,
gboolean sensitive)
{
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GList *l;
g_return_if_fail (GTK_IS_WIDGET (widget));
@@ -6373,6 +6374,13 @@ gtk_widget_set_sensitive (GtkWidget *widget,
priv->sensitive = sensitive;
for (l = priv->event_controllers; l; l = l->next)
{
GtkEventController *controller = l->data;
gtk_event_controller_reset (controller);
}
if (priv->parent == NULL
|| gtk_widget_is_sensitive (priv->parent))
{
@@ -6731,17 +6739,17 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->realized)
g_warning ("%s %p is mapped but not realized",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
if (!priv->visible)
g_warning ("%s %p is mapped but not visible",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
if (!GTK_IS_ROOT (widget))
{
if (!priv->child_visible)
g_warning ("%s %p is mapped but not child_visible",
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (widget), widget);
}
}
else
@@ -6791,8 +6799,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->realized)
g_warning ("%s %p is not realized but child %s %p is realized",
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
G_OBJECT_TYPE_NAME (widget), widget);
parent ? gtk_widget_get_name (parent) : "no parent", parent,
gtk_widget_get_name (widget), widget);
}
if (parent &&
@@ -6804,8 +6812,8 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->mapped)
g_warning ("%s %p is mapped but visible child %s %p is not mapped",
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
gtk_widget_get_name (parent), parent,
gtk_widget_get_name (widget), widget);
}
else if (!GTK_IS_ROOT (widget))
{
@@ -6813,10 +6821,10 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (priv->mapped)
g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
G_OBJECT_TYPE_NAME (widget), widget,
gtk_widget_get_name (widget), widget,
priv->visible,
priv->child_visible,
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
parent ? gtk_widget_get_name (parent) : "no parent", parent,
parent ? parent->priv->mapped : FALSE);
}
}
@@ -12978,7 +12986,7 @@ gtk_widget_snapshot (GtkWidget *widget,
if (_gtk_widget_get_alloc_needed (widget))
{
g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
g_warning ("Trying to snapshot %s %p without a current allocation", gtk_widget_get_name (widget), widget);
return;
}

View File

@@ -261,6 +261,8 @@ testsuite/reftests/label-ellipsize-small.ref.ui
testsuite/reftests/label-ellipsize-small.ui
testsuite/reftests/label-ellipsize-with-big.ref.ui
testsuite/reftests/label-ellipsize-with-big.ui
testsuite/reftests/label-fonts.ref.ui
testsuite/reftests/label-fonts.ui
testsuite/reftests/label-shadows.ref.ui
testsuite/reftests/label-shadows.ui
testsuite/reftests/label-sizing.ref.ui

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -221,6 +221,8 @@ testsuite/reftests/label-ellipsize-small.ref.ui
testsuite/reftests/label-ellipsize-small.ui
testsuite/reftests/label-ellipsize-with-big.ref.ui
testsuite/reftests/label-ellipsize-with-big.ui
testsuite/reftests/label-fonts.ref.ui
testsuite/reftests/label-fonts.ui
testsuite/reftests/label-shadows.ref.ui
testsuite/reftests/label-shadows.ui
testsuite/reftests/label-sizing.ref.ui

View File

@@ -6024,7 +6024,7 @@ msgstr "Hanunoo"
#: gtk/script-names.c:58
msgctxt "Script"
msgid "Buhid"
msgstr "Bugui"
msgstr "Buhid"
#: gtk/script-names.c:59
msgctxt "Script"
@@ -6414,7 +6414,7 @@ msgstr "Pau Cin Hau"
#: gtk/script-names.c:136
msgctxt "Script"
msgid "Psalter Pahlavi"
msgstr "Inscripcions Pahlavi"
msgstr "Psalter Pahlavi"
#: gtk/script-names.c:137
msgctxt "Script"

5699
po/eu.po

File diff suppressed because it is too large Load Diff

541
po/pl.po

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
#label {
font-family: nonexisting,Sans;
}
#reference {
font-family: Sans;
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="type">popup</property>
<child>
<object class="GtkLabel" id="label3">
<property name="name">reference</property>
<property name="label" translatable="yes">abcdefg</property>
</object>
</child>
</object>
</interface>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window1">
<property name="type">popup</property>
<child>
<object class="GtkLabel" id="label3">
<property name="name">label</property>
<property name="label" translatable="yes">abcdefg</property>
</object>
</child>
</object>
</interface>

View File

@@ -267,6 +267,9 @@ testdata = [
'label-ellipsize-small.ui',
'label-ellipsize-with-big.ref.ui',
'label-ellipsize-with-big.ui',
'label-fonts.css',
'label-fonts.ref.ui',
'label-fonts.ui',
'label-shadows.css',
'label-shadows.ref.ui',
'label-shadows.ui',