Compare commits

..

4 Commits

Author SHA1 Message Date
Matthias Clasen
e07f3d6e64 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 19:15:37 +00:00
Matthias Clasen
b844778b5b widget: Update controllers responsiveness
Make controllers unresponsive when their
widget is insensitive. This is the expected
behavior.
2019-05-02 19:15:37 +00:00
Matthias Clasen
fca0f649a0 gesture: Chain up in filter_event
This is the right thing to do.
We want to exclude more events.
2019-05-02 19:15:37 +00:00
Matthias Clasen
da034390f2 event controller: Add a ::responsive property
This lets us 'mute' controllers, for example
when widgets are insensitive. For now, we make
this property readonly and only let GTK itself
update it.
2019-05-02 19:15:37 +00:00
28 changed files with 3260 additions and 5284 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 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
* 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
* 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,13 +70,9 @@ 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. A number of layout managers are available:
- GtkBinLayout
- GtkBoxLayout
- GtkGridLayout
- GtkFixedLayout
- GtkCustomLayout
More layout manager implementations will appear in the future.
properties. GtkBinLayout, GtkBoxLayout, GtkGridLayout, GtkFixedLayout
and GtkCustomLayout are currently available, 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
@@ -86,11 +82,8 @@ 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 or changed to backend APIs.
removed
* GtkBuilder can specify object-valued properties inline.

View File

@@ -1,373 +0,0 @@
<?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>
How widgets draw
The GTK drawing model in detail
</refpurpose>
</refnamediv>

View File

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

View File

@@ -6514,6 +6514,7 @@ GtkEventController
GtkPropagationPhase
gtk_event_controller_get_propagation_phase
gtk_event_controller_set_propagation_phase
gtk_event_controller_get_responsive
gtk_event_controller_handle_event
gtk_event_controller_get_widget
gtk_event_controller_reset

View File

@@ -4,15 +4,15 @@
]>
<refentry id="chap-input-handling">
<refmeta>
<refentrytitle>The GTK Input Model</refentrytitle>
<refentrytitle>The GTK Input and Event Handling Model</refentrytitle>
<manvolnum>3</manvolnum>
<refmiscinfo>GTK Library</refmiscinfo>
</refmeta>
<refnamediv>
<refname>The GTK Input Model</refname>
<refname>The GTK Input and Event Handling Model</refname>
<refpurpose>
input and event handling in detail
GTK input and event handling in detail
</refpurpose>
</refnamediv>
@@ -52,12 +52,13 @@
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 surface - for pointer events,
the surface under the pointer (grabs complicate this), for keyboard events,
the surface with the keyboard focus.
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.
</para>
<para>
GDK translates these raw windowing system events into #GdkEvents.
@@ -80,10 +81,9 @@
</simplelist>
</para>
<para>
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.
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).
</para>
</refsect2>
@@ -91,8 +91,8 @@
<title>Event propagation</title>
<para>
The function which initially receives input events on the GTK
side is gtk_main_do_event(). See its documentation
For widgets which have a #GdkSurface set, events are received from the
windowing system and passed to 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,55 +120,62 @@
<para>
An event is propagated to a widget using gtk_propagate_event().
Propagation goes down and up the widget hierarchy in three phases
(see #GtkPropagationPhase) towards a target widget.
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).
</para>
<para>
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()).
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.
</para>
<para>
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
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
#GtkWindow or grab widget) down to the target #GtkWidget.
<link linkend="event-controllers-and-gestures">Event
controllers</link> that are attached with %GTK_PHASE_CAPTURE
get a chance to react to the event.
<link linkend="event-controllers-and-gestures">Gestures</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 event controllers 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 gestures attached to it with
%GTK_PHASE_TARGET. This is known as the “target” phase, and only
happens on that widget.
</para>
<para>
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.
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.
</para>
<para>
Events are not delivered to a widget which is insensitive or
unmapped.
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.
</para>
<para>
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.
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.
</para>
</refsect2>
@@ -176,10 +183,27 @@
<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.
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.
</para>
</refsect2>
@@ -187,66 +211,43 @@
<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>
<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>
<!-- focus, tab, directional navigation -->
<!-- mnemonics, accelerators, bindings -->
</refsect2>
@@ -254,43 +255,37 @@
<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 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.
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.
</para>
<para>
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
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
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
recognition 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 gesture 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>
@@ -299,39 +294,34 @@
<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,7 +333,6 @@ images = [
]
content_files = [
'actions.xml',
'broadway.xml',
'building.sgml',
'compiling.sgml',
@@ -369,7 +368,6 @@ 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 number of adjustments that you may have to do
that, there's a small 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 using
to help you port your application to GTK 4. If you are still 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
<literal>gdk_window_set_visual (gdk_screen_get_rgba_visual ())</literal>
after creating your window.
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.
</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>
GTK 4 removes these #GtkBox child properties, so you should not use them.
GTK4 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,30 +172,35 @@
<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 application ID</title>
<title>Set a proper app_id</title>
<para>
In GTK 4 we want the application's #GApplication
In GTK4 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 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.
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.
</para>
<para>
The call to g_set_prgname() can be removed once you fully migrated
to GTK 4.
to GTK4.
</para>
</section>
<section>
<title>Stop using GtkBox's pack-type child property</title>
<para>
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.
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.
</para>
</section>
@@ -211,17 +216,6 @@
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>
@@ -307,9 +301,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
@@ -401,10 +395,6 @@
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>
@@ -421,7 +411,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, GTK 4 uses
family of functions. To simplify widget implementations, GTK4 uses
only one virtual function, GtkWidgetClass::measure() that widgets
have to implement.
</para>
@@ -650,7 +640,7 @@
</section>
<section>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry and GtkSpinButton</title>
<title>Adapt to changes in the API of GtkEntry, GtkSearchEntry adn 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,
@@ -685,77 +675,6 @@
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,30 +79,12 @@ 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 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.
windowing systems. GDK provides window system facilities on X11, Windows,
and OS X.
</para></listitem>
</varlistentry>

View File

@@ -1143,18 +1143,8 @@ pack_font_description (GtkCssShorthandProperty *shorthand,
v = (* query_func) (GTK_CSS_PROPERTY_FONT_FAMILY, query_data);
if (v)
{
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);
/* 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)));
}
v = (* query_func) (GTK_CSS_PROPERTY_FONT_SIZE, query_data);

View File

@@ -70,9 +70,6 @@ struct _GtkEmojiChooser
EmojiSection flags;
GVariant *data;
GtkWidget *box;
GVariantIter *iter;
guint populate_idle;
GSettings *settings;
};
@@ -95,9 +92,6 @@ 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);
@@ -405,68 +399,47 @@ add_emoji (GtkWidget *box,
gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
}
static gboolean
populate_emoji_chooser (gpointer data)
static void
populate_emoji_chooser (GtkEmojiChooser *chooser)
{
GtkEmojiChooser *chooser = data;
GBytes *bytes = NULL;
GVariantIter iter;
GVariant *item;
guint64 start, now;
GtkWidget *box;
start = g_get_monotonic_time ();
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));
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)))
g_variant_iter_init (&iter, chooser->data);
box = chooser->people.box;
while ((item = g_variant_iter_next_value (&iter)))
{
const char *name;
g_variant_get_child (item, 1, "&s", &name);
if (strcmp (name, chooser->body.first) == 0)
chooser->box = chooser->body.box;
box = chooser->body.box;
else if (strcmp (name, chooser->nature.first) == 0)
chooser->box = chooser->nature.box;
box = chooser->nature.box;
else if (strcmp (name, chooser->food.first) == 0)
chooser->box = chooser->food.box;
box = chooser->food.box;
else if (strcmp (name, chooser->travel.first) == 0)
chooser->box = chooser->travel.box;
box = chooser->travel.box;
else if (strcmp (name, chooser->activities.first) == 0)
chooser->box = chooser->activities.box;
box = chooser->activities.box;
else if (strcmp (name, chooser->objects.first) == 0)
chooser->box = chooser->objects.box;
box = chooser->objects.box;
else if (strcmp (name, chooser->symbols.first) == 0)
chooser->box = chooser->symbols.box;
box = chooser->symbols.box;
else if (strcmp (name, chooser->flags.first) == 0)
chooser->box = chooser->flags.box;
box = chooser->flags.box;
add_emoji (chooser->box, FALSE, item, 0, chooser);
add_emoji (box, FALSE, item, 0, chooser);
g_variant_unref (item);
now = g_get_monotonic_time ();
if (now > start + 8000)
return G_SOURCE_CONTINUE;
}
/* 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;
g_bytes_unref (bytes);
}
static void
@@ -678,9 +651,11 @@ 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);
chooser->populate_idle = g_idle_add (populate_emoji_chooser, 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);
}
static void

View File

@@ -43,6 +43,7 @@ typedef struct _GtkEventControllerPrivate GtkEventControllerPrivate;
enum {
PROP_WIDGET = 1,
PROP_PROPAGATION_PHASE,
PROP_RESPONSIVE,
LAST_PROP
};
@@ -52,6 +53,7 @@ struct _GtkEventControllerPrivate
{
GtkWidget *widget;
GtkPropagationPhase phase;
gboolean responsive;
};
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkEventController, gtk_event_controller, G_TYPE_OBJECT)
@@ -63,6 +65,7 @@ gtk_event_controller_set_widget (GtkEventController *self,
GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
priv->widget = widget;
priv->responsive = gtk_widget_get_sensitive (widget);
}
static void
@@ -71,6 +74,7 @@ gtk_event_controller_unset_widget (GtkEventController *self)
GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
priv->widget = NULL;
priv->responsive = TRUE;
}
static gboolean
@@ -79,10 +83,7 @@ gtk_event_controller_filter_event_default (GtkEventController *self,
{
GtkEventControllerPrivate *priv = gtk_event_controller_get_instance_private (self);
if (priv->widget)
return !gtk_widget_is_sensitive (priv->widget);
return FALSE;
return !priv->responsive;
}
static gboolean
@@ -128,6 +129,9 @@ gtk_event_controller_get_property (GObject *object,
case PROP_PROPAGATION_PHASE:
g_value_set_enum (value, priv->phase);
break;
case PROP_RESPONSIVE:
g_value_set_enum (value, priv->responsive);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
@@ -170,6 +174,21 @@ gtk_event_controller_class_init (GtkEventControllerClass *klass)
GTK_PHASE_BUBBLE,
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
/**
* GtkEventController:responsive:
*
* Whether the controller handles events.
*
* GTK sets event controllers to be not responsive
* when the widget they are attached to becomes insensitive.
*/
properties[PROP_RESPONSIVE] =
g_param_spec_boolean ("responsive",
P_("Responsive"),
P_("Whether the controller is reponsive"),
TRUE,
GTK_PARAM_READABLE);
g_object_class_install_properties (object_class, LAST_PROP, properties);
}
@@ -180,6 +199,7 @@ gtk_event_controller_init (GtkEventController *controller)
priv = gtk_event_controller_get_instance_private (controller);
priv->phase = GTK_PHASE_BUBBLE;
priv->responsive = TRUE;
}
/**
@@ -311,3 +331,44 @@ gtk_event_controller_set_propagation_phase (GtkEventController *controller,
g_object_notify_by_pspec (G_OBJECT (controller), properties[PROP_PROPAGATION_PHASE]);
}
void
gtk_event_controller_set_responsive (GtkEventController *controller,
gboolean responsive)
{
GtkEventControllerPrivate *priv;
g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
priv = gtk_event_controller_get_instance_private (controller);
if (priv->responsive == responsive)
return;
priv->responsive = responsive;
if (!responsive)
gtk_event_controller_reset (controller);
g_object_notify_by_pspec (G_OBJECT (controller), properties[PROP_RESPONSIVE]);
}
/**
* gtk_event_controller_get_responsive:
* @controller: a #GtkEventController
*
* Returns whether the controller is currently responsive.
*
* Returns: %TRUE if @controller is responsive
*/
gboolean
gtk_event_controller_get_responsive (GtkEventController *controller)
{
GtkEventControllerPrivate *priv;
g_return_val_if_fail (GTK_IS_EVENT_CONTROLLER (controller), TRUE);
priv = gtk_event_controller_get_instance_private (controller);
return priv->responsive;
}

View File

@@ -59,6 +59,9 @@ GDK_AVAILABLE_IN_ALL
void gtk_event_controller_set_propagation_phase (GtkEventController *controller,
GtkPropagationPhase phase);
GDK_AVAILABLE_IN_ALL
gboolean gtk_event_controller_get_responsive (GtkEventController *controller);
G_END_DECLS
#endif /* __GTK_EVENT_CONTROLLER_H__ */

View File

@@ -48,4 +48,8 @@ struct _GtkEventControllerClass
gpointer padding[10];
};
void
gtk_event_controller_set_responsive (GtkEventController *controller,
gboolean responsive);
#endif /* __GTK_EVENT_CONTROLLER_PRIVATE_H__ */

View File

@@ -49,7 +49,6 @@
#include "gtkfilechooserprivate.h"
#include "gtkfilechooserutils.h"
#include "gtkmarshalers.h"
#include "gtkbinlayout.h"
#include "gtkfilechooserbutton.h"
@@ -340,6 +339,41 @@ 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)
{
@@ -363,6 +397,8 @@ 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:
@@ -497,8 +533,6 @@ 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 ());
}
@@ -988,8 +1022,17 @@ gtk_file_chooser_button_finalize (GObject *object)
GtkFileChooserButton *button = GTK_FILE_CHOOSER_BUTTON (object);
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
g_clear_object (&priv->selection_while_inactive);
g_clear_object (&priv->current_folder_while_inactive);
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);
}
gtk_widget_unparent (priv->button);
gtk_widget_unparent (priv->combo_box);
@@ -1023,22 +1066,31 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
GtkFileChooserButtonPrivate *priv = gtk_file_chooser_button_get_instance_private (button);
GSList *l;
if (priv->model)
if (priv->dialog != NULL)
{
model_remove_rows (button, 0, gtk_tree_model_iter_n_children (priv->model, NULL));
g_clear_object (&priv->model);
gtk_widget_destroy (priv->dialog);
priv->dialog = NULL;
}
g_clear_pointer (&priv->dialog, gtk_widget_destroy);
if (priv->native)
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
{
gtk_native_dialog_destroy (GTK_NATIVE_DIALOG (priv->native));
g_clear_object (&priv->native);
}
g_clear_object (&priv->native);
priv->chooser = NULL; /* Was either priv->dialog or priv->native! */
priv->chooser = NULL;
g_clear_pointer (&priv->dnd_select_folder_cancellable, g_cancellable_cancel);
g_clear_pointer (&priv->update_button_cancellable, g_cancellable_cancel);
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;
}
if (priv->change_icon_theme_cancellables)
{
@@ -1051,15 +1103,24 @@ gtk_file_chooser_button_destroy (GtkWidget *widget)
priv->change_icon_theme_cancellables = NULL;
}
g_clear_object (&priv->filter_model);
if (priv->filter_model)
{
g_object_unref (priv->filter_model);
priv->filter_model = NULL;
}
if (priv->fs)
{
g_signal_handler_disconnect (priv->fs, priv->fs_volumes_changed_id);
g_clear_object (&priv->fs);
g_object_unref (priv->fs);
priv->fs = NULL;
}
g_clear_pointer (&priv->bookmarks_manager, _gtk_bookmarks_manager_free);
if (priv->bookmarks_manager)
{
_gtk_bookmarks_manager_free (priv->bookmarks_manager);
priv->bookmarks_manager = NULL;
}
GTK_WIDGET_CLASS (gtk_file_chooser_button_parent_class)->destroy (widget);
}

View File

@@ -107,7 +107,6 @@ 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

@@ -6378,7 +6378,7 @@ gtk_widget_set_sensitive (GtkWidget *widget,
{
GtkEventController *controller = l->data;
gtk_event_controller_reset (controller);
gtk_event_controller_set_responsive (controller, sensitive);
}
if (priv->parent == NULL
@@ -6739,17 +6739,17 @@ gtk_widget_verify_invariants (GtkWidget *widget)
if (!priv->realized)
g_warning ("%s %p is mapped but not realized",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
if (!priv->visible)
g_warning ("%s %p is mapped but not visible",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
if (!GTK_IS_ROOT (widget))
{
if (!priv->child_visible)
g_warning ("%s %p is mapped but not child_visible",
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (widget), widget);
}
}
else
@@ -6799,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 ? gtk_widget_get_name (parent) : "no parent", parent,
gtk_widget_get_name (widget), widget);
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
if (parent &&
@@ -6812,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",
gtk_widget_get_name (parent), parent,
gtk_widget_get_name (widget), widget);
G_OBJECT_TYPE_NAME (parent), parent,
G_OBJECT_TYPE_NAME (widget), widget);
}
else if (!GTK_IS_ROOT (widget))
{
@@ -6821,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",
gtk_widget_get_name (widget), widget,
G_OBJECT_TYPE_NAME (widget), widget,
priv->visible,
priv->child_visible,
parent ? gtk_widget_get_name (parent) : "no parent", parent,
parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
parent ? parent->priv->mapped : FALSE);
}
}
@@ -12986,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", gtk_widget_get_name (widget), widget);
g_warning ("Trying to snapshot %s %p without a current allocation", G_OBJECT_TYPE_NAME (widget), widget);
return;
}

View File

@@ -261,8 +261,6 @@ 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,8 +221,6 @@ 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 "Buhid"
msgstr "Bugui"
#: 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 "Psalter Pahlavi"
msgstr "Inscripcions Pahlavi"
#: gtk/script-names.c:137
msgctxt "Script"

5637
po/eu.po

File diff suppressed because it is too large Load Diff

563
po/pl.po

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,12 +0,0 @@
<?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

@@ -1,12 +0,0 @@
<?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,9 +267,6 @@ 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',