forked from AuroraMiddleware/gtk
wip: Include markdown content, via pandoc
Use pandoc to convert freestanding markdown files to docbook for inclusion in the generated docs, and use bits and pieces of gtk-doc code to continue expanding typical gtk-doc abbreviations. The new tool for markdown -> docbook is a python script called gtk-markdown-to-docbook. The markdown dialect is specified via a list of pandoc extension in gtk-markdown-to-docbook. It includes header annocations, definition lists and tables, among other things. This commit converts the 3 overview chapters (drawing, input handling and actions) and the migration guide to markdown syntax. Other files that are still listed in content_files can be converted later. This commit adds a pandoc dependency.
This commit is contained in:
parent
2127cc1943
commit
10cd539104
222
docs/reference/gtk/actions.md
Normal file
222
docs/reference/gtk/actions.md
Normal file
@ -0,0 +1,222 @@
|
||||
# Overview of actions in GTK {#actions-overview}
|
||||
|
||||
This chapter describes in detail how GTK uses actions to connect
|
||||
activatable UI elements to callbacks. GTK inherits the underlying
|
||||
architecture of GAction and GMe:u for describing abstract actions
|
||||
and menus from the GIO library.
|
||||
|
||||
## Basics about actions
|
||||
|
||||
A GAction is essentially a way to tell the toolkit about a piece of
|
||||
functionality in your program, and to give it a name.
|
||||
|
||||
Actions are purely functional. They do not contain any presentational
|
||||
information.
|
||||
|
||||
An action has four pieces of information associated with it:
|
||||
|
||||
- a name as an identifier (usually all-lowercase, untranslated
|
||||
English string)
|
||||
- an enabled flag indicating if the action can be activated or not
|
||||
(like the "sensitive" property on widgets)
|
||||
- an optional state value, for stateful actions (like a boolean for
|
||||
toggles)
|
||||
- an optional parameter type, used when activating the action
|
||||
|
||||
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.
|
||||
|
||||
Here are some rules about an action:
|
||||
|
||||
- the name is immutable (in the sense that it will never change) and
|
||||
it is never %NULL
|
||||
- the enabled flag can change
|
||||
- the parameter type is immutable
|
||||
- the parameter type is optional: it can be %NULL
|
||||
- if the parameter type is %NULL then action activation must be done
|
||||
without a parameter (ie: a %NULL GVariant pointer)
|
||||
- if the parameter type is non-%NULL then the parameter must have this
|
||||
type
|
||||
- the state can change, but it cannot change type
|
||||
- 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)
|
||||
- if the action was stateless when it was created, it can never have a
|
||||
state
|
||||
- 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
|
||||
|
||||
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.
|
||||
|
||||
## Action state and parameters
|
||||
|
||||
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".
|
||||
|
||||
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 would 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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/')".
|
||||
|
||||
You can convert between detailed action names and split-out action names
|
||||
and target values using g_action_parse_detailed_name() and
|
||||
g_action_print_detailed_name() but usually you will not need to. Most APIs
|
||||
will provide both ways of specifying actions with targets.
|
||||
|
||||
## Action scopes
|
||||
|
||||
Actions are always scoped to a particular object on which they operate.
|
||||
|
||||
In GTK, actions are typically scoped to either an application or a window,
|
||||
but any widget can have actions associated with it.
|
||||
|
||||
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".
|
||||
|
||||
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".
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Actions are added to their relevant scope (application, window or widget)
|
||||
either using the GActionMap interface, or by using
|
||||
gtk_widget_insert_action_group(). Actions that will be the same for all
|
||||
instances of a widget class can be added globally using
|
||||
gtk_widget_class_install_action().
|
||||
|
||||
## Action groups and action maps
|
||||
|
||||
Actions rarely occurs in isolation. It is common to have groups
|
||||
of related actions, which are represented by instances of the
|
||||
GActionGroup interface.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
If you want to insert several actions at the same time, it is
|
||||
typically faster and easier to use GActionEntry.
|
||||
|
||||
## Connecting actions to widgets
|
||||
|
||||
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 GtkActionable include GtkSwitch, GtkButton,
|
||||
and their respective subclasses.
|
||||
|
||||
Another way 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.
|
||||
|
||||
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().
|
||||
|
||||
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.
|
||||
|
||||
## Activation
|
||||
|
||||
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.
|
||||
|
||||
## Built-in Actions
|
||||
|
||||
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.
|
||||
|
||||
default.activate
|
||||
: Activates the default widget in a context (typically a GtkWindow,
|
||||
GtkDialog or GtkPopover)
|
||||
clipboard.cut, clipboard.copy, clipboard.paste
|
||||
: Clipboard operations on entries, text view and labels, typically
|
||||
used in the context menu
|
||||
selection.delete, selection.select-all
|
||||
: Selection operations on entries, text view and labels
|
||||
color.select, color.customize:
|
||||
: Operate on colors in a #GtkColorChooserWidget. These actions are
|
||||
unusual in that they have the non-trivial parameter type (dddd):
|
@ -1,394 +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_name()
|
||||
and g_action_print_detailed_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,
|
||||
window or widget) either using the GActionMap interface,
|
||||
or by using gtk_widget_insert_action_group(). Actions that
|
||||
will be the same for all instances of a widget class can
|
||||
be added globally using gtk_widget_class_install_action().
|
||||
</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 GtkActionable include GtkSwitch, GtkButton,
|
||||
and their respective subclasses.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Another way 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>
|
||||
<varlistentry>
|
||||
<term>clipboard.cut, clipboard.copy, clipboard.paste</term>
|
||||
<listitem><para>Clipboard operations on entries, text view
|
||||
and labels, typically used in the context menu
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>selection.delete, selection.select-all</term>
|
||||
<listitem><para>Selection operations on entries, text view
|
||||
and labels
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>color.select, color.customize</term>
|
||||
<listitem><para>Operations on colors in GtkColorChooserWidget.
|
||||
These actions are unusual in that they have the non-trivial
|
||||
parameter type (dddd).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
</refentry>
|
157
docs/reference/gtk/drawing-model.md
Normal file
157
docs/reference/gtk/drawing-model.md
Normal file
@ -0,0 +1,157 @@
|
||||
# Overview of the drawing model {#drawing-overview}
|
||||
|
||||
This chapter describes the GTK drawing model in detail. If you
|
||||
are interested in the procedure which GTK follows to draw its
|
||||
widgets and windows, you should read this chapter; this will be
|
||||
useful to know if you decide to implement your own widgets. This
|
||||
chapter will also clarify the reasons behind the ways certain
|
||||
things are done in GTK.
|
||||
|
||||
## Windows and events {#drawing-windows}
|
||||
|
||||
Applications that use a windowing system generally create
|
||||
rectangular regions in the screen called _surfaces_ (GTK is
|
||||
following the Wayland terminology, other windowing systems
|
||||
such as X11 may call these _windows_). Traditional windowing
|
||||
systems do not automatically save the graphical content of
|
||||
surfaces, and instead ask applications to provide new content
|
||||
whenever it is needed. For example, if a window that is stacked
|
||||
below other windows gets raised to the top, then the application
|
||||
has to repaint it, so the previously obscured area can be shown.
|
||||
When the windowing system asks an application to redraw a window,
|
||||
it sends a _frame event_ (_expose event_ in X11 terminology)
|
||||
for that window.
|
||||
|
||||
Each GTK toplevel window or dialog is associated with a
|
||||
windowing system surface. Child widgets such as buttons or
|
||||
entries don't have their own surface; they use the surface
|
||||
of their toplevel.
|
||||
|
||||
Generally, the drawing cycle begins when GTK receives
|
||||
a frame event from the underlying windowing system: if the
|
||||
user drags a window over another one, the windowing system will
|
||||
tell the underlying surface that it needs to repaint itself. The
|
||||
drawing cycle can also be initiated when a widget itself decides
|
||||
that it needs to update its display. For example, when the user
|
||||
types a character in an entry widget, the entry asks GTK to queue
|
||||
a redraw operation for itself.
|
||||
|
||||
The windowing system generates frame events for surfaces. The GDK
|
||||
interface to the windowing system translates such events into
|
||||
emissions of the ::render signal on the affected surfaces. The GTK
|
||||
toplevel window connects to that signal, and reacts appropriately.
|
||||
|
||||
The following sections describe how GTK decides which widgets
|
||||
need to be repainted in response to such events, and how widgets
|
||||
work internally in terms of the resources they use from the
|
||||
windowing system.
|
||||
|
||||
## The frame clock {#frameclock}
|
||||
|
||||
All GTK applications are mainloop-driven, which means that most
|
||||
of the time the app is idle inside a loop that just waits for
|
||||
something to happen and then calls out to the right place when
|
||||
it does. On top of this GTK has a frame clock that gives a
|
||||
“pulse” to the application. This clock beats at a steady rate,
|
||||
which is tied to the framerate of the output (this is synced to
|
||||
the monitor via the window manager/compositor). A typical
|
||||
refresh rate is 60 frames per second, so a new “pulse” happens
|
||||
roughly every 16 milliseconds.
|
||||
|
||||
The clock has several phases:
|
||||
|
||||
- Events
|
||||
- Update
|
||||
- Layout
|
||||
- Paint
|
||||
|
||||
The phases happens in this order and we will always run each
|
||||
phase through before going back to the start.
|
||||
|
||||
The Events phase is a stretch of time between each redraw where
|
||||
GTK processes input events from the user and other events
|
||||
(like e.g. network I/O). Some events, like mouse motion are
|
||||
compressed so that only a single mouse motion event per clock
|
||||
cycle needs to be handled.
|
||||
|
||||
Once the Events phase is over, external events are paused and
|
||||
the redraw loop is run. First is the Update phase, where all
|
||||
animations are run to calculate the new state based on the
|
||||
estimated time the next frame will be visible (available via
|
||||
the frame clock). This often involves geometry changes which
|
||||
drive the next phase, Layout. If there are any changes in
|
||||
widget size requirements the new layout is calculated for the
|
||||
widget hierarchy (i.e. sizes and positions for all widgets are
|
||||
determined). Then comes the Paint phase, where we redraw the
|
||||
regions of the window that need redrawing.
|
||||
|
||||
If nothing requires the Update/Layout/Paint phases we will
|
||||
stay in the Events phase forever, as we don’t want to redraw
|
||||
if nothing changes. Each phase can request further processing
|
||||
in the following phases (e.g. the Update phase will cause there
|
||||
to be layout work, and layout changes cause repaints).
|
||||
|
||||
There are multiple ways to drive the clock, at the lowest level you
|
||||
can request a particular phase with gdk_frame_clock_request_phase()
|
||||
which will schedule a clock beat as needed so that it eventually
|
||||
reaches the requested phase. However, in practice most things
|
||||
happen at higher levels:
|
||||
|
||||
- If you are doing an animation, you can use
|
||||
gtk_widget_add_tick_callback() which will cause a regular
|
||||
beating of the clock with a callback in the Update phase
|
||||
until you stop the tick.
|
||||
- If some state changes that causes the size of your widget to
|
||||
change you call gtk_widget_queue_resize() which will request
|
||||
a Layout phase and mark your widget as needing relayout.
|
||||
- If some state changes so you need to redraw some area of
|
||||
your widget you use the normal gtk_widget_queue_draw()
|
||||
set of functions. These will request a Paint phase and
|
||||
mark the region as needing redraw.
|
||||
|
||||
There are also a lot of implicit triggers of these from the
|
||||
CSS layer (which does animations, resizes and repaints as needed).
|
||||
|
||||
## The scene graph {#scene-graph}
|
||||
|
||||
The first step in “drawing” a window is that GTK creates
|
||||
_render nodes_ for all the widgets in the window. The render
|
||||
nodes are combined into a tree that you can think of as a
|
||||
_scene graph_ describing your window contents.
|
||||
|
||||
Render nodes belong to the GSK layer, and there are various kinds
|
||||
of them, for the various kinds of drawing primitives you are likely
|
||||
to need when translating widget content and CSS styling. Typical
|
||||
examples are text nodes, gradient nodes, texture nodes or clip nodes.
|
||||
|
||||
In the past, all drawing in GTK happened via cairo. It is still possible
|
||||
to use cairo for drawing your custom widget contents, by using a cairo
|
||||
render node.
|
||||
|
||||
A GSK _renderer_ takes these render nodes, transforms them into
|
||||
rendering commands for the drawing API it targets, and arranges
|
||||
for the resulting drawing to be associated with the right surface.
|
||||
GSK has renderers for OpenGL, Vulkan and cairo.
|
||||
|
||||
## Hierarchical drawing {#hierarchical-drawing}
|
||||
|
||||
During the Paint phase GTK receives a single #GdkSurface::render
|
||||
signal on the toplevel surface. The signal handler will create a
|
||||
snapshot object (which is a helper for creating a scene graph) and
|
||||
call the #GtkWidget::snapshot() vfunc, which will propagate down
|
||||
the widget hierarchy. This lets each widget snapshot its content
|
||||
at the right place and time, correctly handling things like partial
|
||||
transparencies and overlapping widgets.
|
||||
|
||||
During the snapshotting of each widget, GTK automatically handles
|
||||
the CSS rendering according to the CSS box model. It snapshots first
|
||||
the background, then the border, then the widget content itself, and
|
||||
finally the outline.
|
||||
|
||||
To avoid excessive work when generating scene graphs, GTK caches render
|
||||
nodes. Each widget keeps a reference to its render node (which in turn,
|
||||
will refer to the render nodes of children, and grandchildren, and so
|
||||
on), and will reuse that node during the Paint phase. Invalidating a
|
||||
widget (by calling gtk_widget_queue_draw()) discards the cached render
|
||||
node, forcing the widget to regenerate it the next time it needs to
|
||||
produce a snapshot.
|
@ -1,232 +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-drawing-model">
|
||||
<refmeta>
|
||||
<refentrytitle>The GTK Drawing Model</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo>GTK Library</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>The GTK Drawing Model</refname>
|
||||
<refpurpose>
|
||||
How widgets draw
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
|
||||
<refsect1 id="drawing-overview">
|
||||
<title>Overview of the drawing model</title>
|
||||
|
||||
<para>
|
||||
This chapter describes the GTK drawing model in detail. If you
|
||||
are interested in the procedure which GTK follows to draw its
|
||||
widgets and windows, you should read this chapter; this will be
|
||||
useful to know if you decide to implement your own widgets. This
|
||||
chapter will also clarify the reasons behind the ways certain
|
||||
things are done in GTK.
|
||||
</para>
|
||||
|
||||
<refsect2 id="drawing model windows">
|
||||
|
||||
<title>Windows and events</title>
|
||||
|
||||
<para>
|
||||
Applications that use a windowing system generally create
|
||||
rectangular regions in the screen called <firstterm>surfaces</firstterm>
|
||||
(GTK is following the Wayland terminology, other windowing systems
|
||||
such as X11 may call these <firstterm>windows</firstterm>).
|
||||
Traditional windowing systems do not automatically save the
|
||||
graphical content of surfaces, and instead ask applications to
|
||||
provide new content whenever it is needed.
|
||||
For example, if a window that is stacked below other
|
||||
windows gets raised to the top, then the application has to
|
||||
repaint it, so the previously obscured area can be shown.
|
||||
When the windowing system asks an application to redraw
|
||||
a window, it sends a <firstterm>frame event</firstterm>
|
||||
(<firstterm>expose event</firstterm> in X11 terminology)
|
||||
for that window.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Each GTK toplevel window or dialog is associated with a
|
||||
windowing system surface. Child widgets such as buttons or
|
||||
entries don't have their own surface; they use the surface
|
||||
of their toplevel.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Generally, the drawing cycle begins when GTK receives
|
||||
a frame event from the underlying windowing system: if the
|
||||
user drags a window over another one, the windowing system will
|
||||
tell the underlying surface that it needs to repaint itself. The
|
||||
drawing cycle can also be initiated when a widget itself decides
|
||||
that it needs to update its display. For example, when the user
|
||||
types a character in an entry widget, the entry asks GTK to queue
|
||||
a redraw operation for itself.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The windowing system generates frame events for surfaces. The GDK
|
||||
interface to the windowing system translates such events into
|
||||
emissions of the ::render signal on the affected surfaces.
|
||||
The GTK toplevel window connects to that signal, and reacts appropriately.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following sections describe how GTK decides which widgets
|
||||
need to be repainted in response to such events, and how widgets
|
||||
work internally in terms of the resources they use from the
|
||||
windowing system.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="frameclock">
|
||||
<title>The frame clock</title>
|
||||
|
||||
<para>
|
||||
All GTK applications are mainloop-driven, which means that most
|
||||
of the time the app is idle inside a loop that just waits for
|
||||
something to happen and then calls out to the right place when
|
||||
it does. On top of this GTK has a frame clock that gives a
|
||||
“pulse” to the application. This clock beats at a steady rate,
|
||||
which is tied to the framerate of the output (this is synced to
|
||||
the monitor via the window manager/compositor). A typical
|
||||
refresh rate is 60 frames per second, so a new “pulse” happens
|
||||
roughly every 16 milliseconds.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The clock has several phases:
|
||||
<itemizedlist>
|
||||
<listitem><para>Events</para></listitem>
|
||||
<listitem><para>Update</para></listitem>
|
||||
<listitem><para>Layout</para></listitem>
|
||||
<listitem><para>Paint</para></listitem>
|
||||
</itemizedlist>
|
||||
The phases happens in this order and we will always run each
|
||||
phase through before going back to the start.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Events phase is a stretch of time between each redraw where
|
||||
GTK processes input events from the user and other events
|
||||
(like e.g. network I/O). Some events, like mouse motion are
|
||||
compressed so that only a single mouse motion event per clock
|
||||
cycle needs to be handled.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once the Events phase is over, external events are paused and
|
||||
the redraw loop is run. First is the Update phase, where all
|
||||
animations are run to calculate the new state based on the
|
||||
estimated time the next frame will be visible (available via
|
||||
the frame clock). This often involves geometry changes which
|
||||
drive the next phase, Layout. If there are any changes in
|
||||
widget size requirements the new layout is calculated for the
|
||||
widget hierarchy (i.e. sizes and positions for all widgets are
|
||||
determined). Then comes the Paint phase, where we redraw the
|
||||
regions of the window that need redrawing.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If nothing requires the Update/Layout/Paint phases we will
|
||||
stay in the Events phase forever, as we don’t want to redraw
|
||||
if nothing changes. Each phase can request further processing
|
||||
in the following phases (e.g. the Update phase will cause there
|
||||
to be layout work, and layout changes cause repaints).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
There are multiple ways to drive the clock, at the lowest level
|
||||
you can request a particular phase with
|
||||
gdk_frame_clock_request_phase() which will schedule a clock beat
|
||||
as needed so that it eventually reaches the requested phase.
|
||||
However, in practice most things happen at higher levels:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
If you are doing an animation, you can use
|
||||
gtk_widget_add_tick_callback() which will cause a regular
|
||||
beating of the clock with a callback in the Update phase
|
||||
until you stop the tick.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
If some state changes that causes the size of your widget
|
||||
to change you call gtk_widget_queue_resize() which will
|
||||
request a Layout phase and mark your widget as needing
|
||||
relayout.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
If some state changes so you need to redraw some area of
|
||||
your widget you use the normal gtk_widget_queue_draw()
|
||||
set of functions. These will request a Paint phase and
|
||||
mark the region as needing redraw.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
There are also a lot of implicit triggers of these from the
|
||||
CSS layer (which does animations, resizes and repaints as needed).
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="scene-graph">
|
||||
<title>The scene graph</title>
|
||||
|
||||
<para>
|
||||
The first step in “drawing” a window is that GTK creates
|
||||
<firstterm>render nodes</firstterm> for all the widgets
|
||||
in the window. The render nodes are combined into a tree
|
||||
that you can think of as a <firstterm>scene graph</firstterm>
|
||||
describing your window contents.
|
||||
</para>
|
||||
<para>
|
||||
Render nodes belong to the GSK layer, and there are various kinds
|
||||
of them, for the various kinds of drawing primitives you are likely
|
||||
to need when translating widget content and CSS styling. Typical
|
||||
examples are text nodes, gradient nodes, texture nodes or clip nodes.
|
||||
<para>
|
||||
<para>
|
||||
In the past, all drawing in GTK happened via cairo. It is still possible
|
||||
to use cairo for drawing your custom widget contents, by using a cairo
|
||||
render node.
|
||||
</para>
|
||||
</para>
|
||||
A GSK <firstterm>renderer</firstterm> takes these render nodes, transforms
|
||||
them into rendering commands for the drawing API it targets, and arranges
|
||||
for the resulting drawing to be associated with the right surface. GSK has
|
||||
renderers for OpenGL, Vulkan and cairo.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="hierarchical-drawing">
|
||||
<title>Hierarchical drawing</title>
|
||||
|
||||
<para>
|
||||
During the Paint phase GTK receives a single #GdkSurface::render signal on
|
||||
the toplevel surface. The signal handler will create a snapshot object
|
||||
(which is a helper for creating a scene graph) and call the
|
||||
#GtkWidget::snapshot() vfunc, which will propagate down the widget hierarchy.
|
||||
This lets each widget snapshot its content at the right place and time,
|
||||
correctly handling things like partial transparencies and overlapping widgets.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
During the snapshotting of each widget, GTK automatically handles the CSS
|
||||
rendering according to the CSS box model. It snapshots first the background,
|
||||
then the border, then the widget content itself, and finally the outline.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To avoid excessive work when generating scene graphs, GTK caches render nodes.
|
||||
Each widget keeps a reference to its render node (which in turn, will refer to
|
||||
the render nodes of children, and grandchildren, and so on), and will reuse
|
||||
that node during the Paint phase. Invalidating a widget (by calling
|
||||
gtk_widget_queue_draw()) discards the cached render node, forcing the widget
|
||||
to regenerate it the next time it needs to produce a snapshot.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
184
docs/reference/gtk/gtk-markdown-to-docbook
Executable file
184
docs/reference/gtk/gtk-markdown-to-docbook
Executable file
@ -0,0 +1,184 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Call pandoc to convert markdown to docbook, then expand gtk-doc
|
||||
# abbreviations (|[ ]|, function(), #object, %constant, etc)
|
||||
|
||||
import sys
|
||||
import re
|
||||
import tempfile
|
||||
import os.path
|
||||
import subprocess
|
||||
|
||||
# The following code is taken from gtk-doc
|
||||
|
||||
def ExpandAbbreviations(symbol, text):
|
||||
# Convert '@param()'
|
||||
text = re.sub(r'(\A|[^\\])\@(\w+((\.|->)\w+)*)\s*\(\)', r'\1<parameter>\2()</parameter>', text)
|
||||
|
||||
# Convert 'function()' or 'macro()'.
|
||||
# if there is abc_*_def() we don't want to make a link to _def()
|
||||
# FIXME: also handle abc(def(....)) : but that would need to be done recursively :/
|
||||
def f1(m):
|
||||
return m.group(1) + MakeXRef(m.group(2), tagify(m.group(2) + "()", "function"))
|
||||
text = re.sub(r'([^\*.\w])(\w+)\s*\(\)', f1, text)
|
||||
# handle #Object.func()
|
||||
text = re.sub(r'(\A|[^\\])#([\w\-:\.]+[\w]+)\s*\(\)', f1, text)
|
||||
|
||||
# Convert '@param', but not '\@param'.
|
||||
text = re.sub(r'(\A|[^\\])\@(\w+((\.|->)\w+)*)', r'\1<parameter>\2</parameter>', text)
|
||||
text = re.sub(r'/\\\@', r'\@', text)
|
||||
|
||||
# Convert '%constant', but not '\%constant'.
|
||||
# Also allow negative numbers, e.g. %-1.
|
||||
def f2(m):
|
||||
return m.group(1) + MakeXRef(m.group(2), tagify(m.group(2), "literal"))
|
||||
|
||||
text = re.sub(r'(\A|[^\\])\%(-?\w+)', f2, text)
|
||||
text = re.sub(r'\\\%', r'\%', text)
|
||||
|
||||
# Convert '#symbol', but not '\#symbol'.
|
||||
def f3(m):
|
||||
return m.group(1) + MakeHashXRef(m.group(2), "type")
|
||||
|
||||
text = re.sub(r'(\A|[^\\])#([\w\-:\.]+[\w]+)', f3, text)
|
||||
text = re.sub(r'\\#', '#', text)
|
||||
|
||||
return text
|
||||
|
||||
# Standard C preprocessor directives, which we ignore for '#' abbreviations.
|
||||
PreProcessorDirectives = {
|
||||
'assert', 'define', 'elif', 'else', 'endif', 'error', 'if', 'ifdef', 'ifndef',
|
||||
'include', 'line', 'pragma', 'unassert', 'undef', 'warning'
|
||||
}
|
||||
|
||||
def MakeHashXRef(symbol, tag):
|
||||
text = symbol
|
||||
|
||||
# Check for things like '#include', '#define', and skip them.
|
||||
if symbol in PreProcessorDirectives:
|
||||
return "#%s" % symbol
|
||||
|
||||
# Get rid of special suffixes ('-struct','-enum').
|
||||
text = re.sub(r'-struct$', '', text)
|
||||
text = re.sub(r'-enum$', '', text)
|
||||
|
||||
# If the symbol is in the form "Object::signal", then change the symbol to
|
||||
# "Object-signal" and use "signal" as the text.
|
||||
if '::' in symbol:
|
||||
o, s = symbol.split('::', 1)
|
||||
symbol = '%s-%s' % (o, s)
|
||||
text = u'“' + s + u'”'
|
||||
|
||||
# If the symbol is in the form "Object:property", then change the symbol to
|
||||
# "Object--property" and use "property" as the text.
|
||||
if ':' in symbol:
|
||||
o, p = symbol.split(':', 1)
|
||||
symbol = '%s--%s' % (o, p)
|
||||
text = u'“' + p + u'”'
|
||||
|
||||
if tag != '':
|
||||
text = tagify(text, tag)
|
||||
|
||||
return MakeXRef(symbol, text)
|
||||
|
||||
def MakeXRef(symbol, text=None):
|
||||
"""This returns a cross-reference link to the given symbol.
|
||||
|
||||
Though it doesn't try to do this for a few standard C types that it knows
|
||||
won't be in the documentation.
|
||||
|
||||
Args:
|
||||
symbol (str): the symbol to try to create a XRef to.
|
||||
text (str): text to put inside the XRef, defaults to symbol
|
||||
|
||||
Returns:
|
||||
str: a docbook link
|
||||
"""
|
||||
symbol = symbol.strip()
|
||||
if not text:
|
||||
text = symbol
|
||||
|
||||
# Get rid of special suffixes ('-struct','-enum').
|
||||
text = re.sub(r'-struct$', '', text)
|
||||
text = re.sub(r'-enum$', '', text)
|
||||
|
||||
if ' ' in symbol:
|
||||
return text
|
||||
|
||||
symbol_id = CreateValidSGMLID(symbol)
|
||||
return "<link linkend=\"%s\">%s</link>" % (symbol_id, text)
|
||||
|
||||
def CreateValidSGMLID(xml_id):
|
||||
"""Creates a valid SGML 'id' from the given string.
|
||||
|
||||
According to http://www.w3.org/TR/html4/types.html#type-id "ID and NAME
|
||||
tokens must begin with a letter ([A-Za-z]) and may be followed by any number
|
||||
of letters, digits ([0-9]), hyphens ("-"), underscores ("_"), colons (":"),
|
||||
and periods (".")."
|
||||
|
||||
When creating SGML IDS, we append ":CAPS" to all all-caps identifiers to
|
||||
prevent name clashes (SGML ids are case-insensitive). (It basically never is
|
||||
the case that mixed-case identifiers would collide.)
|
||||
|
||||
Args:
|
||||
id (str): The text to be converted into a valid SGML id.
|
||||
|
||||
Returns:
|
||||
str: The converted id.
|
||||
"""
|
||||
|
||||
# Special case, '_' would end up as '' so we use 'gettext-macro' instead.
|
||||
if xml_id == '_':
|
||||
return "gettext-macro"
|
||||
|
||||
xml_id = re.sub(r'[,;]', '', xml_id)
|
||||
xml_id = re.sub(r'[_ ]', '-', xml_id)
|
||||
xml_id = re.sub(r'^-+', '', xml_id)
|
||||
xml_id = xml_id.replace('::', '-')
|
||||
xml_id = xml_id.replace(':', '--')
|
||||
|
||||
# Append ":CAPS" to all all-caps identifiers
|
||||
# FIXME: there are some inconsistencies here, we have index files containing e.g. TRUE--CAPS
|
||||
if xml_id.isupper() and not xml_id.endswith('-CAPS'):
|
||||
xml_id += ':CAPS'
|
||||
|
||||
return xml_id
|
||||
|
||||
def tagify(text, elem):
|
||||
# Adds a tag around some text.
|
||||
# e.g tagify("Text", "literal") => "<literal>Text</literal>".
|
||||
return '<' + elem + '>' + text + '</' + elem + '>'
|
||||
|
||||
# End of gtk-doc excerpts
|
||||
|
||||
MarkdownExtensions = {
|
||||
'-auto_identifiers', # we use explicit identifiers where needed
|
||||
'+header_attributes', # for explicit identifiers
|
||||
'+blank_before_header', # helps with gtk-doc #Object abbreviations
|
||||
'+compact_definition_lists', # to replace <variablelist>
|
||||
'+pipe_tables',
|
||||
'+backtick_code_blocks', # to replace |[ ]|
|
||||
'+fenced_code_attributes', # to add language annotations
|
||||
'-raw_html', # to escape literal tags like <child> in input
|
||||
}
|
||||
|
||||
def ConvertToDocbook(infile, outfile):
|
||||
basename = os.path.basename(infile)
|
||||
input_format = "markdown" + "".join(MarkdownExtensions)
|
||||
output_format = "docbook"
|
||||
subprocess.check_call(["pandoc", infile, "-o", outfile,
|
||||
"--from=" + input_format,
|
||||
"--to=" + output_format,
|
||||
"--top-level-division=chapter"])
|
||||
|
||||
def ExpandGtkDocAbbreviations(infile, outfile):
|
||||
contents = open(infile, 'r', encoding='utf-8').read()
|
||||
with open(outfile, 'w', encoding='utf-8') as out:
|
||||
out.write(ExpandAbbreviations("file", contents))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
tmp = tempfile.mktemp()
|
||||
ConvertToDocbook(sys.argv[1], tmp)
|
||||
ExpandGtkDocAbbreviations(tmp, sys.argv[2])
|
||||
os.remove(tmp)
|
@ -6,7 +6,7 @@
|
||||
<!ENTITY pi "π">
|
||||
<!ENTITY solidus "⁄">
|
||||
]>
|
||||
<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||
<book xmlns="http://docbook.org/ns/docbook" id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
|
||||
<bookinfo>
|
||||
<title>GTK 4 Reference Manual</title>
|
||||
<releaseinfo>
|
||||
@ -28,9 +28,9 @@
|
||||
|
||||
<part id="concepts">
|
||||
<title>GTK Concepts</title>
|
||||
<xi:include href="xml/drawing-model.xml" />
|
||||
<xi:include href="xml/input-handling.xml" />
|
||||
<xi:include href="xml/actions.xml" />
|
||||
<xi:include href="drawing-model.xml" />
|
||||
<xi:include href="input-handling.xml" />
|
||||
<xi:include href="actions.xml" />
|
||||
</part>
|
||||
|
||||
<part id="gtkobjects">
|
||||
@ -397,8 +397,8 @@
|
||||
</para>
|
||||
</partintro>
|
||||
|
||||
<xi:include href="xml/migrating-2to4.xml" />
|
||||
<xi:include href="xml/migrating-3to4.xml" />
|
||||
<xi:include href="migrating-2to4.xml" />
|
||||
<xi:include href="migrating-3to4.xml" />
|
||||
</part>
|
||||
|
||||
<part>
|
||||
|
206
docs/reference/gtk/input-handling.md
Normal file
206
docs/reference/gtk/input-handling.md
Normal file
@ -0,0 +1,206 @@
|
||||
# Overview of GTK input and event handling {#input-overview}
|
||||
|
||||
This chapter describes in detail how GTK handles input. If you are interested
|
||||
in what happens to translate a key press or mouse motion of the users into a
|
||||
change of a GTK widget, you should read this chapter. This knowledge will also
|
||||
be useful if you decide to implement your own widgets.
|
||||
|
||||
Devices and events
|
||||
|
||||
The most basic input devices that every computer user has interacted with are
|
||||
keyboards and mice; beyond these, GTK supports touchpads, touchscreens and
|
||||
more exotic input devices such as graphics tablets. Inside GTK, every such
|
||||
input device is represented by a #GdkDevice object.
|
||||
|
||||
To simplify dealing with the variability between these input devices, GTK
|
||||
has a concept of master and slave devices. The concrete physical devices that
|
||||
have many different characteristics (mice may have 2 or 3 or 8 buttons,
|
||||
keyboards have different layouts and may or may not have a separate number
|
||||
block, etc) are represented as slave devices. Each slave device is
|
||||
associated with a virtual master device. Master devices always come in
|
||||
pointer/keyboard pairs - you can think of such a pair as a 'seat'.
|
||||
|
||||
GTK widgets generally deal with the master devices, and thus can be used
|
||||
with any pointing device or keyboard.
|
||||
|
||||
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.
|
||||
|
||||
GDK translates these raw windowing system events into #GdkEvents.
|
||||
Typical input events are button clicks, pointer motion, key presses
|
||||
or touch events. These are all represented as #GdkEvents, but you can
|
||||
differentiate between different events by looking at their type, using
|
||||
gdk_event_get_event_type().
|
||||
|
||||
Some events, such as touch events or button press-release pairs,
|
||||
are connected in to each other in an “event sequence” that
|
||||
univocally identifies events that are related to the same
|
||||
interaction.
|
||||
|
||||
When GTK creates a GdkSurface, it connects to the #GdkSurface::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.
|
||||
|
||||
## Event propagation {#event-propagation}
|
||||
|
||||
The function which initially receives input events on the GTK
|
||||
side is responsible for a number of tasks.
|
||||
|
||||
1. Find the widget which got the event.
|
||||
2. Generate crossing (i.e. enter and leave) events when the focus or
|
||||
hover location change from one widget to another.
|
||||
3. Send the event to widgets.
|
||||
|
||||
An event is propagated down and up the widget hierarchy in three phases
|
||||
(see #GtkPropagationPhase) towards a target widget.
|
||||
|
||||
![Event propagation phases](capture-bubble.png)
|
||||
|
||||
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 pointer events, the target widget is determined by picking
|
||||
the widget at the events coordinates (see gtk_window_pick()).
|
||||
|
||||
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.
|
||||
[Event controllers](event-controllers-and-gestures) that are attached
|
||||
with %GTK_PHASE_CAPTURE get a chance to react to the event.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Events are not delivered to a widget which is insensitive or unmapped.
|
||||
|
||||
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.
|
||||
|
||||
## Keyboard input
|
||||
|
||||
Every #GtkWindow maintains a single focus location (in
|
||||
the #GtkWindow:focus-widget property). The focus widget is the
|
||||
target widget for key events sent to the window. Only widgets which
|
||||
have #GtkWidget: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.
|
||||
|
||||
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.
|
||||
|
||||
Many widgets can be “activated” to trigger and action. E.g., you can
|
||||
activate a button or switch by clicking on them, but you can also
|
||||
activate them with the keyboard, by using the Enter or Space keys.
|
||||
|
||||
Apart from keyboard navigation, activation and directly typing into
|
||||
entries or text views, GTK widgets can use key events for activating
|
||||
“shortcuts”. Shortcuts generally act as a quick way to move the focus
|
||||
around or to activate a widget that does not currently have the focus.
|
||||
|
||||
GTK has traditionally supported different kinds of shortcuts:
|
||||
|
||||
Accelerators
|
||||
: Accelerators are any other shortcuts that can be activated regardless
|
||||
of where the focus is, and typically trigger global actions, such as
|
||||
Ctrl-Q to quit an application.
|
||||
Mnmemonics
|
||||
: Mnemonics are usually triggered using Alt as a modifier for a letter.
|
||||
They are used in places where a label is associated with a control,
|
||||
and are indicated by underlining the letter in the label. As a special
|
||||
case, inside menus (i.e. inside #GtkPopoverMenu), mnemonics can be
|
||||
trigered without the modifier.
|
||||
Key bindings
|
||||
: Key bindings are specific to individual widgets, such as Ctrl-C or
|
||||
Ctrl-V in an entry copy to or paste from the clipboard. They are only
|
||||
triggered when the widget has focus.
|
||||
|
||||
GTK handles accelerators and mnemonics in a global scope, during the
|
||||
capture phase, and key bindings locally, during the target phase.
|
||||
|
||||
Under the hood, all shortcuts are represented as instances of #GtkShortcut,
|
||||
and they are managed by #GtkShortcutController.
|
||||
|
||||
## Event controllers and gestures {#event-controllers-and-gestures}
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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:
|
||||
|
||||
- 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.
|
||||
- Grouping a “drag” gesture with a “pan” gesture will only
|
||||
effectively allow dragging in the panning orientation, as
|
||||
both gestures share state.
|
||||
- If “press” and “long press” are wanted simultaneously,
|
||||
those would need grouping.
|
||||
|
||||
Shortcuts are handled by #GtkShortcutController, which is
|
||||
a complex event handler that can either activate shortcuts
|
||||
itself, or propagate them to another controller, depending
|
||||
on its #GtkShortcutController:scope.
|
||||
|
||||
## Gesture states
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
where 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:
|
@ -1,332 +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-input-handling">
|
||||
<refmeta>
|
||||
<refentrytitle>The GTK Input Model</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
<refmiscinfo>GTK Library</refmiscinfo>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>The GTK Input Model</refname>
|
||||
<refpurpose>
|
||||
input and event handling in detail
|
||||
</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
|
||||
<refsect1 id="input-overview">
|
||||
<title>Overview of GTK input and event handling</title>
|
||||
|
||||
<para>
|
||||
This chapter describes in detail how GTK handles input. If you are interested
|
||||
in what happens to translate a key press or mouse motion of the users into a
|
||||
change of a GTK widget, you should read this chapter. This knowledge will also
|
||||
be useful if you decide to implement your own widgets.
|
||||
</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Devices and events</title>
|
||||
|
||||
<!-- input devices: master/slave, keyboard/pointer/touch -->
|
||||
<para>
|
||||
The most basic input devices that every computer user has interacted with are
|
||||
keyboards and mice; beyond these, GTK supports touchpads, touchscreens and
|
||||
more exotic input devices such as graphics tablets. Inside GTK, every such
|
||||
input device is represented by a #GdkDevice object.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To simplify dealing with the variability between these input devices, GTK
|
||||
has a concept of master and slave devices. The concrete physical devices that
|
||||
have many different characteristics (mice may have 2 or 3 or 8 buttons,
|
||||
keyboards have different layouts and may or may not have a separate number
|
||||
block, etc) are represented as slave devices. Each slave device is
|
||||
associated with a virtual master device. Master devices always come in
|
||||
pointer/keyboard pairs - you can think of such a pair as a 'seat'.
|
||||
</para>
|
||||
<para>
|
||||
GTK widgets generally deal with the master devices, and thus can be used
|
||||
with any pointing device or keyboard.
|
||||
</para>
|
||||
|
||||
<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.
|
||||
</para>
|
||||
<para>
|
||||
GDK translates these raw windowing system events into #GdkEvents.
|
||||
Typical input events are button clicks, pointer motion, key presses
|
||||
or touch events. These are all represented as #GdkEvents, but you can
|
||||
differentiate between different events by looking at their type, using
|
||||
gdk_event_get_event_type().
|
||||
</para>
|
||||
<para>
|
||||
Some events, such as touch events or button press-release pairs,
|
||||
are connected in to each other in an “event sequence” that
|
||||
univocally identifies events that are related to the same
|
||||
interaction.
|
||||
</para>
|
||||
<para>
|
||||
When GTK creates a GdkSurface, it connects to the #GdkSurface::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>
|
||||
|
||||
<refsect2 id="event-propagation">
|
||||
<title>Event propagation</title>
|
||||
|
||||
<para>
|
||||
The function which initially receives input events on the GTK
|
||||
side is responsible for a number of tasks.
|
||||
</para>
|
||||
<orderedlist>
|
||||
<listitem><para>
|
||||
Find the widget which got the event.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
Generate crossing (i.e. enter and leave) events when the focus or hover
|
||||
location change from one widget to another.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
The event is sent to widgets.
|
||||
</para></listitem>
|
||||
</orderedlist>
|
||||
|
||||
<para>
|
||||
An event is propagated down and up the widget hierarchy in three phases
|
||||
(see #GtkPropagationPhase) towards a target widget.
|
||||
</para>
|
||||
|
||||
<informalfigure>
|
||||
<mediaobject>
|
||||
<imageobject>
|
||||
<imagedata fileref="capture-bubble.png" format="PNG"/>
|
||||
</imageobject>
|
||||
</mediaobject>
|
||||
</informalfigure>
|
||||
|
||||
<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()).
|
||||
</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
|
||||
#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.
|
||||
</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.
|
||||
</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.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Events are not delivered to a widget which is insensitive or
|
||||
unmapped.
|
||||
</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.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2>
|
||||
<title>Keyboard input</title>
|
||||
|
||||
<para>
|
||||
Every #GtkWindow maintains a single focus location (in the
|
||||
#GtkWindow:focus-widget property). The focus widget is the target
|
||||
widget for key events sent to the window. Only widgets which have
|
||||
#GtkWidget: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>
|
||||
|
||||
<para>
|
||||
Many widgets can be “activated” to trigger and action. E.g., you can
|
||||
activate a button or switch by clicking on them, but you can also
|
||||
activate them with the keyboard, by using the Enter or Space keys.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Apart from keyboard navigation, activation and directly typing into
|
||||
entries or text views, GTK widgets can use key events for activating
|
||||
“shortcuts”. Shortcuts generally act as a quick way to move the focus
|
||||
around or to activate a widget that does not currently have the focus.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
GTK has traditionally supported different kinds of shortcuts:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Accelerators</term>
|
||||
<listitem><para>
|
||||
Accelerators are any other shortcuts that can be activated regardless
|
||||
of where the focus is, and typically trigger global actions, such as
|
||||
Ctrl-Q to quit an application.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Mnmemonics</term>
|
||||
<listitem><para>
|
||||
Mnemonics are usually triggered using Alt as a modifier for a letter.
|
||||
They are used in places where a label is associated with a control,
|
||||
and are indicated by underlining the letter in the label. As a special
|
||||
case, inside menus (i.e. inside #GtkPopoverMenu), mnemonics can be
|
||||
trigered without the modifier.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Key bindings</term>
|
||||
<listitem><para>
|
||||
Key bindings are specific to individual widgets, such as Ctrl-C or
|
||||
Ctrl-V in an entry copy to or paste from the clipboard. They are only
|
||||
triggered when the widget has focus.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
GTK traditionally handles accelerators and mnemonics in a global scope,
|
||||
during the capture phase, and key bindings locally, during the target phase.
|
||||
</para>
|
||||
<para>
|
||||
Under the hood, all shortcuts are represented as instances of #GtkShortcut,
|
||||
and they are managed by #GtkShortcutController.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="event-controllers-and-gestures">
|
||||
<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.
|
||||
</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.
|
||||
</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
|
||||
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.
|
||||
</member>
|
||||
<member>
|
||||
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.
|
||||
</member>
|
||||
</simplelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Shortcuts are handled by #GtkShortcutController, which is
|
||||
a complex event handler that can either activate shortcuts
|
||||
itself, or propagate them to another controller, depending
|
||||
on its #GtkShortcutController:scope.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<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
|
||||
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.
|
||||
</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,
|
||||
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.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
</refentry>
|
101
docs/reference/gtk/lists-overview.md
Normal file
101
docs/reference/gtk/lists-overview.md
Normal file
@ -0,0 +1,101 @@
|
||||
# List widgets
|
||||
|
||||
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
|
||||
|
||||
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
|
||||
|
||||
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
|
||||
|
||||
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
|
||||
|
||||
## Terminology
|
||||
|
||||
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
|
||||
|
||||
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
|
||||
|
||||
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
|
||||
|
||||
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
|
||||
|
||||
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
|
||||
|
||||
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
|
||||
|
||||
The same model can be used in multiple different views and wrapped with multiple different models at once.
|
||||
|
||||
The elements in a model are called **_items_**. All items are #GObjects.
|
||||
|
||||
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
|
||||
|
||||
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
|
||||
|
||||
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
|
||||
|
||||
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
|
||||
|
||||
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
|
||||
|
||||
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection. The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible. The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
|
||||
|
||||
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
|
||||
|
||||
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
|
||||
|
||||
## Behind the scenes
|
||||
|
||||
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
|
||||
|
||||
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
|
||||
|
||||
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
|
||||
|
||||
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
|
||||
|
||||
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
|
||||
|
||||
## Displaying trees
|
||||
|
||||
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
|
||||
|
||||
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
|
||||
|
||||
Developers should refer to those objects' API reference for more discussion on the topic.
|
||||
|
||||
## comparison to GtkTreeView
|
||||
|
||||
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
|
||||
|
||||
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
|
||||
|
||||
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
|
||||
|
||||
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once. The goal here is of course to encourage implementation of custom list models.
|
||||
|
||||
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
|
||||
|
||||
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
|
||||
|
||||
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
|
||||
|
||||
| old | new |
|
||||
| ------------------- | ----------------------------------- |
|
||||
| #GtkTreeModel | #GListModel |
|
||||
| #GtkTreePath | #guint position, #GtkTreeListRow |
|
||||
| #GtkTreeIter | #guint position |
|
||||
| GtkTreeRowReference | #GObject item |
|
||||
| #GtkListStore | #GListStore |
|
||||
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
|
||||
| #GtkTreeSelection | #GtkSelectionModel |
|
||||
| #GtkTreeViewColumn | FIXME: ColumnView |
|
||||
| #GtkTreeView | #GtkListView, FIXME: ColumnView |
|
||||
| #GtkCellView | ? |
|
||||
| #GtkComboBox | FIXME |
|
||||
| #GtkIconView | #GtkGridView |
|
||||
| #GtkTreeSortable | FIXME: ColumnView? |
|
||||
| #GtkTreeModelSort | #GtkSortListModel |
|
||||
| #GtkTreeModelFilter | #GtkFilterListModel |
|
||||
| #GtkCellLayout | #GtkListItemFactory |
|
||||
| #GtkCellArea | #GtkWidget |
|
||||
| #GtkCellRenderer | #GtkWidget |
|
||||
|
@ -1,3 +1,5 @@
|
||||
fs = import('fs')
|
||||
|
||||
private_headers = [
|
||||
'imm-extra.h',
|
||||
'gtkbitmaskprivateimpl.h',
|
||||
@ -338,12 +340,10 @@ images = [
|
||||
]
|
||||
|
||||
content_files = [
|
||||
'actions.xml',
|
||||
'broadway.xml',
|
||||
'building.xml',
|
||||
'compiling.xml',
|
||||
'css-overview.xml',
|
||||
'drawing-model.xml',
|
||||
'glossary.xml',
|
||||
'gtk4-broadwayd.xml',
|
||||
'gtk4-builder-tool.xml',
|
||||
@ -355,9 +355,6 @@ content_files = [
|
||||
'gtk4-query-settings.xml',
|
||||
'gtk4-update-icon-cache.xml',
|
||||
'gtk4-widget-factory.xml',
|
||||
'input-handling.xml',
|
||||
'migrating-2to4.xml',
|
||||
'migrating-3to4.xml',
|
||||
'osx.xml',
|
||||
'other_software.xml',
|
||||
'overview.xml',
|
||||
@ -373,18 +370,21 @@ content_files = [
|
||||
]
|
||||
|
||||
expand_content_files = [
|
||||
'actions.xml',
|
||||
'compiling.xml',
|
||||
'drawing-model.xml',
|
||||
'glossary.xml',
|
||||
'input-handling.xml',
|
||||
'migrating-2to4.xml',
|
||||
'migrating-3to4.xml',
|
||||
'question_index.xml',
|
||||
'text_widget.xml',
|
||||
'tree_widget.xml',
|
||||
]
|
||||
|
||||
expand_content_md_files = [
|
||||
'migrating-2to4.md',
|
||||
'migrating-3to4.md',
|
||||
'actions.md',
|
||||
'input-handling.md',
|
||||
'drawing-model.md'
|
||||
]
|
||||
|
||||
types_conf = configuration_data()
|
||||
if os_win32
|
||||
types_conf.set('DISABLE_ON_W32', '%')
|
||||
@ -402,6 +402,15 @@ if get_option('gtk_doc')
|
||||
configure_file(input: 'version.xml.in', output: 'version.xml', configuration: version_conf)
|
||||
configure_file(input: 'getting_started.xml.in', output: 'getting_started.xml', configuration: src_dir_conf)
|
||||
|
||||
expand_md = find_program('gtk-markdown-to-docbook')
|
||||
expand_md_targets = []
|
||||
foreach t : expand_content_md_files
|
||||
expand_md_targets += custom_target(t,
|
||||
input: [ t ],
|
||||
output: [ fs.replace_suffix(t, '.xml') ],
|
||||
command: [ expand_md, '@INPUT@', '@OUTPUT@'])
|
||||
endforeach
|
||||
|
||||
gnome.gtkdoc('gtk4',
|
||||
mode: 'none',
|
||||
main_xml: 'gtk4-docs.xml',
|
||||
@ -431,7 +440,7 @@ if get_option('gtk_doc')
|
||||
'--extra-dir=../gdk',
|
||||
'--extra-dir=../gsk',
|
||||
],
|
||||
content_files: content_files,
|
||||
content_files: content_files + expand_md_targets,
|
||||
expand_content_files: expand_content_files,
|
||||
html_assets: images,
|
||||
install: true)
|
||||
|
5
docs/reference/gtk/migrating-2to4.md
Normal file
5
docs/reference/gtk/migrating-2to4.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Migrating from GTK 2.x to GTK 4 {#gtk-migrating-2-to-4}
|
||||
|
||||
If your application is still using GTK 2, you should first convert it to GTK 3,
|
||||
by following the [migration guide](https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html)
|
||||
in the GTK 3 documentation, and then follow [these instructions](#gtk-migrating-3-to-4).
|
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
||||
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
|
||||
]>
|
||||
<chapter id="gtk-migrating-2-to-4">
|
||||
<title>Migrating from GTK 2.x to GTK 4</title>
|
||||
|
||||
<para>
|
||||
If your application is still using GTK 2, you should first convert it to
|
||||
GTK 3, by following the <ulink url="https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html">migration guide</ulink> in the GTK 3
|
||||
documentation, and then follow <xref linkend="gtk-migrating-3-to-4"/>.
|
||||
</para>
|
||||
|
||||
</chapter>
|
928
docs/reference/gtk/migrating-3to4.md
Normal file
928
docs/reference/gtk/migrating-3to4.md
Normal file
@ -0,0 +1,928 @@
|
||||
# Migrating from GTK 3.x to GTK 4 {#gtk-migrating-3-to-4}
|
||||
|
||||
GTK 4 is a major new version of GTK that breaks both API and ABI
|
||||
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
|
||||
when you actually switch your application to build against GTK 4.
|
||||
|
||||
## Preparation in GTK 3.x
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
### Do not use deprecated symbols
|
||||
|
||||
Over the years, a number of functions, and in some cases, entire
|
||||
widgets have been deprecated. These deprecations are clearly spelled
|
||||
out in the API reference, with hints about the recommended replacements.
|
||||
The API reference for GTK 3 also includes an
|
||||
[index](https://developer.gnome.org/gtk3/3.24/api-index-deprecated.html)
|
||||
of all deprecated symbols.
|
||||
|
||||
To verify that your program does not use any deprecated symbols,
|
||||
you can use defines to remove deprecated symbols from the header files,
|
||||
as follows:
|
||||
```
|
||||
make CFLAGS+="-DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED"
|
||||
```
|
||||
|
||||
Note that some parts of our API, such as enumeration values, are
|
||||
not well covered by the deprecation warnings. In most cases, using
|
||||
them will require you to also use deprecated functions, which will
|
||||
trigger warnings.
|
||||
|
||||
### Enable diagnostic warnings
|
||||
|
||||
Deprecations of properties and signals cannot be caught at compile
|
||||
time, as both properties and signals are installed and used after
|
||||
types have been instantiated. In order to catch deprecations and
|
||||
changes in the run time components, you should use the
|
||||
`G_ENABLE_DIAGNOSTIC` environment variable when running your
|
||||
application, e.g.:
|
||||
```
|
||||
G_ENABLE_DIAGNOSTIC=1 ./your-app
|
||||
```
|
||||
|
||||
### Do not use widget style properties
|
||||
|
||||
Style properties do not exist in GTK 4. You should stop using them in
|
||||
your custom CSS and in your code.
|
||||
|
||||
### Review your window creation flags
|
||||
|
||||
GTK 4 removes the `GDK_WA_CURSOR` flag. Instead, just use
|
||||
gdk_window_set_cursor() to set a cursor on the window after
|
||||
creating it. 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. GTK 4 also removes the `GDK_WA_WMCLASS`
|
||||
flag. If you need this X11-specific functionality, use XSetClassHint()
|
||||
directly.
|
||||
|
||||
### Stop using direct access to GdkEvent structs
|
||||
|
||||
In GTK 4, event structs are opaque and immutable. Many fields already
|
||||
have accessors in GTK 3, and you should use those to reduce the amount
|
||||
of porting work you have to do at the time of the switch.
|
||||
|
||||
### Stop using gdk_pointer_warp()
|
||||
|
||||
Warping the pointer is disorienting and unfriendly to users.
|
||||
GTK 4 does not support it. In special circumstances (such as when
|
||||
implementing remote connection UIs) it can be necessary to
|
||||
warp the pointer; in this case, use platform APIs such as
|
||||
XWarpPointer() directly.
|
||||
|
||||
### Stop using non-RGBA visuals
|
||||
|
||||
GTK 4 always uses RGBA visuals for its windows; you should make
|
||||
sure that your code works with such visuals. At the same time,
|
||||
you should stop using GdkVisual APIs, since this object not longer
|
||||
exists in GTK 4. Most of its APIs are deprecated already and not
|
||||
useful when dealing with RGBA visuals.
|
||||
|
||||
### Stop using GtkBox padding, fill and expand child properties
|
||||
|
||||
GTK 4 removes these #GtkBox child properties, so you should stop using
|
||||
them. You can replace GtkBox:padding using the #GtkWidget:margin properties
|
||||
on your #GtkBox child widgets.
|
||||
|
||||
The fill child property can be replaced by setting appropriate values
|
||||
for the #GtkWidget:halign and #GtkWidget:valign properties of the child
|
||||
widgets. If you previously set the fill child property to %TRUE, you can
|
||||
achieve the same effect by setting the halign or valign properties to
|
||||
%GTK_ALIGN_FILL, depending on the parent box -- halign for a horizontal
|
||||
box, valign for a vertical one.
|
||||
|
||||
\#GtkBox also uses the expand child property. It can be replaced by setting
|
||||
#GtkWidget:hexpand or #GtkWidget:vexpand on the child widgets. To match the
|
||||
old behavior of the #GtkBox's expand child property, you need to set
|
||||
#GtkWidget:hexpand on the child widgets of a horizontal #GtkBox and
|
||||
#GtkWidget:vexpand on the child widgets of a vertical #GtkBox.
|
||||
|
||||
Note that there's a subtle but important difference between #GtkBox's
|
||||
expand and fill child properties and the ones in #GtkWidget: setting
|
||||
#GtkWidget:hexpand or #GtkWidget:vexpand to %TRUE will propagate up
|
||||
the widget hierarchy, so a pixel-perfect port might require you to reset
|
||||
the expansion flags to %FALSE in a parent widget higher up the hierarchy.
|
||||
|
||||
### Stop using the state argument of GtkStyleContext getters
|
||||
|
||||
The getters in the GtkStyleContext API, such as
|
||||
gtk_style_context_get_property(), gtk_style_context_get(),
|
||||
or gtk_style_context_get_color() only accept the context's current
|
||||
state for their state argument. You should update all callers to pass
|
||||
the current state.
|
||||
|
||||
### Stop using gdk_pixbuf_get_from_window() and gdk_cairo_set_source_surface()
|
||||
|
||||
These functions are not supported in GTK 4. Instead, either use
|
||||
backend-specific APIs, or render your widgets using
|
||||
#GtkWidgetClass.snapshot() (once you are using GTK 4).
|
||||
|
||||
Stop using GtkButton's image-related API
|
||||
|
||||
The functions and properties related to automatically add a GtkImage
|
||||
to a GtkButton, and using a GtkSetting to control its visibility, are
|
||||
not supported in GTK 4. Instead, you can just pack a GtkImage inside
|
||||
a GtkButton, and control its visibility like you would for any other
|
||||
widget. If you only want to add a named icon to a GtkButton, you can
|
||||
use gtk_button_new_from_icon_name().
|
||||
|
||||
### Stop using GtkWidget event signals
|
||||
|
||||
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.
|
||||
|
||||
### Set a proper application ID
|
||||
|
||||
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 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.
|
||||
|
||||
The call to g_set_prgname() can be removed once you fully migrated to GTK 4.
|
||||
|
||||
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.
|
||||
|
||||
### Stop using gtk_main() and related APIs
|
||||
|
||||
GTK 4 removes the gtk_main_ family of APIs. The recommended replacement
|
||||
is GtkApplication, but you can also iterate the GLib mainloop directly,
|
||||
using GMainContext APIs. The replacement for gtk_events_pending() is
|
||||
g_main_context_pending(), the replacement for gtk_main_iteration() is
|
||||
g_main_context_iteration().
|
||||
|
||||
### Reduce the use of gtk_widget_destroy()
|
||||
|
||||
GTK 4 introduces a gtk_window_destroy() api. While that is not available
|
||||
in GTK 3, you can prepare for the switch by using gtk_widget_destroy()
|
||||
only on toplevel windows, and replace all other uses with
|
||||
gtk_container_remove() or g_object_unref().
|
||||
|
||||
### Reduce the use of generic container APIs</title>
|
||||
|
||||
GTK 4 removes gtk_container_add() and gtk_container_remove(). While there
|
||||
is not always a replacement for gtk_container_remove() in GTK 3, you can
|
||||
replace many uses of gtk_container_add() with equivalent container-specific
|
||||
APIs such as gtk_box_pack_start() or gtk_grid_attach(), and thereby reduce
|
||||
the amount of work you have to do at the time of the switch.
|
||||
|
||||
## Changes that need to be done at the time of the switch
|
||||
|
||||
This section outlines porting tasks that you need to tackle when
|
||||
you get to the point that you actually build your application against
|
||||
GTK 4. Making it possible to prepare for these in GTK 3 would
|
||||
have been either impossible or impractical.
|
||||
|
||||
### Stop using GdkScreen
|
||||
|
||||
The GdkScreen object has been removed in GTK 4. Most of its APIs already
|
||||
had replacements in GTK 3 and were deprecated, a few remaining replacements
|
||||
have been added to GdkDisplay.
|
||||
|
||||
### Stop using the root window
|
||||
|
||||
The root window is an X11-centric concept that is no longer exposed in the
|
||||
backend-neutral GDK API. If you need to interact with the X11 root window,
|
||||
you can use gdk_x11_display_get_xrootwindow() to get its XID.
|
||||
|
||||
### Stop using GdkVisual
|
||||
|
||||
This object is not useful with current GTK drawing APIs and has been removed
|
||||
without replacement.
|
||||
|
||||
### Stop using GdkDeviceManager
|
||||
|
||||
The GdkDeviceManager object has been removed in GTK 4. Most of its APIs already
|
||||
had replacements in GTK 3 and were deprecated in favor of GdkSeat.
|
||||
|
||||
### Adapt to GdkWindow API changes
|
||||
|
||||
GdkWindow has been renamed to GdkSurface.
|
||||
|
||||
In GTK 4, the two roles of a standalone toplevel window and of a popup
|
||||
that is placed relative to a parent window have been separated out into
|
||||
two interfaces, #GdkToplevel and #GdkPopup. Surfaces implementing these
|
||||
interfaces are created with gdk_surface_new_toplevel() and
|
||||
gdk_surface_new_popup(), respectively, and they are presented on screen
|
||||
using gdk_toplevel_present() and gdk_popup_present(). The present()
|
||||
functions take parameters in the form of an auxiliary layout struct,
|
||||
#GdkPopupLayout or #GdkToplevelLayout. If your code is dealing directly
|
||||
with surfaces, you may have to change it to call the API in these
|
||||
interfaces, depending on whether the surface you are dealing with
|
||||
is a toplevel or a popup.
|
||||
|
||||
As part of this reorganization, X11-only concepts such as sticky or
|
||||
keep-below have been removed. If you need to use them on your X11 windows,
|
||||
you will have to set the corresponding X11 properties (as specified in the
|
||||
EWMH) yourself. Subsurfaces are only supported with the Wayland backend,
|
||||
using gdk_wayland_surface_new_subsurface(). Native and foreign subwindows
|
||||
are no longer supported. These concepts were complicating the code and
|
||||
could not be supported across backends.
|
||||
|
||||
gdk_window_reparent() is no longer available.
|
||||
|
||||
A number of minor API cleanups have happened in GdkSurface
|
||||
as well. For example, gdk_surface_input_shape_combine_region()
|
||||
has been renamed to gdk_surface_set_input_region(), and
|
||||
gdk_surface_begin_resize_drag() has been renamed to
|
||||
gdk_toplevel_begin_resize().
|
||||
|
||||
### The "iconified" window state has been renamed to "minimized"
|
||||
|
||||
The %GDK_SURFACE_STATE_ICONIFIED value of the
|
||||
#GdkSurfaceState enumeration is now %GDK_SURFACE_STATE_MINIMIZED.
|
||||
|
||||
The #GdkWindow functions <function>gdk_window_iconify()</function>
|
||||
and <function>gdk_window_deiconify()</function> have been renamed to
|
||||
gdk_toplevel_minimize() and gdk_toplevel_present(), respectively.
|
||||
|
||||
The behavior of the minimization and unminimization operations have
|
||||
not been changed, and they still require support from the underlying
|
||||
windowing system.
|
||||
|
||||
### Adapt to GdkEvent API changes
|
||||
|
||||
Direct access to GdkEvent structs is no longer possible in GTK 4.
|
||||
GdkEvent is now a strictly read-only type, and you can no longer
|
||||
change any of its fields, or construct new events. All event fields
|
||||
have accessors that you will have to use.
|
||||
|
||||
Event compression is always enabled in GTK 4. If you need to see
|
||||
the uncoalesced motion history, use gdk_motion_event_get_history()
|
||||
on the latest motion event.
|
||||
|
||||
### Stop using grabs
|
||||
|
||||
GTK 4 no longer provides the gdk_device_grab() or gdk_seat_grab()
|
||||
apis. If you need to dismiss a popup when the user clicks outside
|
||||
(the most common use for grabs), you can use the GdkPopup
|
||||
#GdkPopup:autohide property instead. GtkPopover also has a
|
||||
#GtkPopover:autohide property for this. If you need to prevent
|
||||
the user from interacting with a window while a dialog is open,
|
||||
use the #GtkWindow:modal property of the dialog.
|
||||
|
||||
### Adapt to coordinate API changes
|
||||
|
||||
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
|
||||
code accordingly.
|
||||
|
||||
Any APIs that deal with global (or root) coordinates have been
|
||||
removed in GTK 4, since not all backends support them. You should
|
||||
replace your use of such APIs with surface-relative equivalents.
|
||||
Examples of this are gdk_surface_get_origin(), gdk_surface_move()
|
||||
or gdk_event_get_root_coords().
|
||||
|
||||
### Adapt to GdkKeymap API changes
|
||||
|
||||
GdkKeymap no longer exists as an independent object.
|
||||
|
||||
If you need access to keymap state, it is now exposed as properties
|
||||
on the #GdkDevice representing the keyboard: #GdkDevice:direction,
|
||||
#GdkDevice:has-bidi-layouts, #GdkDevice:caps-lock-state,
|
||||
#GdkDevice:num-lock-state, #GdkDevice:scroll-lock-state and
|
||||
#GdkDevice:modifier-state. To obtain the keyboard device, you can use
|
||||
`gdk_seat_get_keyboard (gdk_display_get_default_seat (display)`.
|
||||
|
||||
If you need access to translated keys for event handling, #GdkEvent
|
||||
now includes all of the translated key state, including consumed
|
||||
modifiers, group and shift level, so there should be no need to
|
||||
manually call gdk_keymap_translate_keyboard_state() (which has
|
||||
been removed).
|
||||
|
||||
If you need to do forward or backward mapping between key codes
|
||||
and key values, use gdk_display_map_keycode() and gdk_display_map_keyval(),
|
||||
which are the replacements for gdk_keymap_get_entries_for_keycode()
|
||||
and gdk_keymap_get_entries_for_keyval().
|
||||
|
||||
### Adapt to changes in keyboard modifier handling
|
||||
|
||||
GTK 3 has the idea that use of modifiers may differ between different
|
||||
platforms, and has a #GdkModifierIntent api to let platforms provide
|
||||
hint about how modifiers are expected to be used. It also promoted
|
||||
the use of <Primary> instead of <Control> to specify accelerators that
|
||||
adapt to platform conventions.
|
||||
|
||||
In GTK 4, the meaning of modifiers has been fixed, and backends are
|
||||
expected to map the platform conventions to the existing modifiers.
|
||||
The expected use of modifiers in GTK 4 is:
|
||||
|
||||
GDK_CONTROL_MASK
|
||||
: Primary accelerators
|
||||
GDK_ALT_MASK
|
||||
: Mnemonics
|
||||
GDK_SHIFT_MASK
|
||||
: Extending selections
|
||||
GDK_CONTROL_MASK
|
||||
: Modifying selections
|
||||
GDK_CONTROL_MASK|GDK_ALT_MASK
|
||||
: Prevent text input
|
||||
|
||||
Consequently, #GdkModifierIntent and related APIs have been removed,
|
||||
and <Control> is preferred over <Primary> in accelerators.
|
||||
|
||||
A related change is that GTK 4 no longer supports the use of archaic
|
||||
X11 'real' modifiers with the names Mod1,..., Mod5, and %GDK_MOD1_MASK
|
||||
has been renamed to %GDK_ALT_MASK.
|
||||
|
||||
### Stop using gtk_get_current_... APIs
|
||||
|
||||
The function gtk_get_current_event() and its variants have been
|
||||
replaced by equivalent event controller APIs:
|
||||
gtk_event_controller_get_current_event(), etc.
|
||||
|
||||
### Convert your ui files
|
||||
|
||||
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.
|
||||
|
||||
### Adapt to event controller API changes
|
||||
|
||||
A few changes to the event controller and #GtkGesture APIs
|
||||
did not make it back to GTK 3, and have to be taken into account
|
||||
when moving to GTK 4. One is that the #GtkEventControllerMotion::enter
|
||||
and #GtkEventControllerMotion::leave signals have gained new arguments.
|
||||
Another is that #GtkGestureMultiPress has been renamed to #GtkGestureClick,
|
||||
and has lost its area property. A #GtkEventControllerFocus has been
|
||||
split off from #GtkEventcontrollerKey.
|
||||
|
||||
### Focus handling changes
|
||||
|
||||
The semantics of the #GtkWidget:can-focus property have changed.
|
||||
In GTK 3, this property only meant that the widget itself would not
|
||||
accept keyboard input, but its children still might (in the case of
|
||||
containers). In GTK 4, if :can-focus is %FALSE, the focus cannot enter
|
||||
the widget or any of its descendents, and the default value has changed
|
||||
from %FALSE to %TRUE. In addition, there is a #GtkWidget:focusable
|
||||
property, which controls whether an individual widget can receive
|
||||
the input focus.
|
||||
|
||||
The feature to automatically keep the focus widget scrolled into view
|
||||
with gtk_container_set_focus_vadjustment() has been removed together with
|
||||
GtkContainer, and is provided by scrollable widgets instead. In the common
|
||||
case that the scrollable is a #GtkViewport, use #GtkViewport:scroll-to-focus.
|
||||
|
||||
### Stop using GtkEventBox
|
||||
|
||||
GtkEventBox is no longer needed and has been removed.
|
||||
All widgets receive all events.
|
||||
|
||||
### Stop using GtkButtonBox
|
||||
|
||||
GtkButtonBox has been removed. Use a GtkBox instead.
|
||||
|
||||
### Adapt to GtkBox API changes
|
||||
|
||||
The GtkBox pack-start and -end methods have been replaced by gtk_box_prepend()
|
||||
and gtk_box_append(). You can also reorder box children as necessary.
|
||||
|
||||
### Adapt to GtkHeaderBar and GtkActionBar API changes
|
||||
|
||||
The gtk_header_bar_set_show_close_button() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_show_title_buttons(). The
|
||||
corresponding getter and the property itself have also been renamed.
|
||||
|
||||
The gtk_header_bar_set_custom_title() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_title_widget(). The
|
||||
corresponding getter and the property itself have also been renamed.
|
||||
|
||||
The gtk_header_bar_set_title() function has been removed along with its
|
||||
corresponding getter and the property. By default #GtkHeaderBar shows
|
||||
the title of the window, so if you were setting the title of the header
|
||||
bar, consider setting the window title instead. If you need to show a
|
||||
title that's different from the window title, use the
|
||||
#GtkHeaderBar:title-widget property to add a #GtkLabel as shown in the
|
||||
example in #GtkHeaderBar documentation.
|
||||
|
||||
The gtk_header_bar_set_subtitle() function has been removed along with
|
||||
its corresponding getter and the property. The old "subtitle" behavior
|
||||
can be replicated by setting the #GtkHeaderBar:title-widget property to
|
||||
a #GtkBox with two labels inside, with the title label matching the
|
||||
example in #GtkHeaderBar documentation, and the subtitle label being
|
||||
similar, but with "subtitle" style class instead of "title".
|
||||
|
||||
The gtk_header_bar_set_has_subtitle() function has been removed along
|
||||
with its corresponding getter and the property. Its behavior can be
|
||||
replicated by setting the #GtkHeaderBar:title-widget property to a
|
||||
#GtkStack with #GtkStack:vhomogeneous property set to %TRUE and two
|
||||
pages, each with a #GtkBox with title and subtitle as described above.
|
||||
|
||||
The ::pack-type child properties of GtkHeaderBar and GtkActionBar have
|
||||
been removed. If you need to programmatically place children, use the
|
||||
pack_start() and pack_end() APIs. In ui files, use the type attribute
|
||||
on the child element.
|
||||
|
||||
gtk4-builder-tool can help with this conversion, with the --3to4 option
|
||||
of the simplify command.
|
||||
|
||||
### Adapt to GtkStack, GtkAssistant and GtkNotebook API changes
|
||||
|
||||
The child properties of GtkStack, GtkAssistant and GtkNotebook have been
|
||||
converted into child meta objects.
|
||||
Instead of gtk_container_child_set (stack, child, …), you can now use
|
||||
g_object_set (gtk_stack_get_page (stack, child), …). In .ui files, the
|
||||
GtkStackPage objects must be created explicitly, and take the child widget
|
||||
as property. GtkNotebook and GtkAssistant are similar.
|
||||
|
||||
gtk4-builder-tool can help with this conversion, with the --3to4 option
|
||||
of the simplify command.
|
||||
|
||||
### Adapt to GtkBin removal
|
||||
|
||||
The abstract base class GtkBin for single-child containers has been
|
||||
removed. The former subclasses are now derived directly from GtkWidget,
|
||||
and have a "child" property for their child widget. To add a child, use
|
||||
the setter for the "child" property (e.g. gtk_frame_set_child()) instead
|
||||
of gtk_container_add(). Adding a child in a ui file with <child> still works.
|
||||
|
||||
The affected classes are:
|
||||
|
||||
- GtkAspectFrame
|
||||
- GtkButton (and subclasses)
|
||||
- GtkComboBox
|
||||
- GtkFlowBoxChild
|
||||
- GtkFrame
|
||||
- GtkListBoxRow
|
||||
- GtkOverlay
|
||||
- GtkPopover
|
||||
- GtkRevealer
|
||||
- GtkScrolledWindow
|
||||
- GtkSearchBar
|
||||
- GtkViewport
|
||||
- GtkWindow (and subclasses)
|
||||
|
||||
If you have custom widgets that were derived from GtkBin, you should
|
||||
port them to derive from GtkWidget. Notable vfuncs that you will have
|
||||
to implement include dispose() (to unparent your child), compute_expand()
|
||||
(if you want your container to propagate expand flags) and
|
||||
get_request_mode() (if you want your container to support height-for-width.
|
||||
|
||||
You may also want to implement the GtkBuildable interface, to support
|
||||
adding children with <child> in ui files.
|
||||
|
||||
### Adapt to GtkContainer removal
|
||||
|
||||
The abstract base class GtkContainer for general containers has been
|
||||
removed. The former subclasses are now derived directly from GtkWidget,
|
||||
and have class-specific add() and remove() functions.
|
||||
The most noticable change is the use of gtk_box_append() or gtk_box_prepend()
|
||||
instead of gtk_container_add() for adding children to GtkBox, and the change
|
||||
to use container-specific remove functions, such as gtk_stack_remove() instead
|
||||
of gtk_container_remove(). Adding a child in a ui file with <child> still works.
|
||||
|
||||
The affected classes are:
|
||||
|
||||
- GtkActionBar
|
||||
- GtkBox (and subclasses)
|
||||
- GtkExpander
|
||||
- GtkFixed
|
||||
- GtkFlowBox
|
||||
- GtkGrid
|
||||
- GtkHeaderBar
|
||||
- GtkIconView
|
||||
- GtkInfoBar
|
||||
- GtkListBox
|
||||
- GtkNotebook
|
||||
- GtkPaned
|
||||
- GtkStack
|
||||
- GtkTextView
|
||||
- GtkTreeView
|
||||
|
||||
Without GtkContainer, there are no longer 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.
|
||||
|
||||
### Stop using GtkContainer::border-width
|
||||
|
||||
GTK 4 has removed the #GtkContainer::border-width property (together
|
||||
with the rest of GtkContainer). Use other means to influence the spacing
|
||||
of your containers, such as the CSS margin and padding properties on child
|
||||
widgets.
|
||||
|
||||
### Adapt to gtk_widget_destroy() removal
|
||||
|
||||
The function gtk_widget_destroy() has been removed. To explicitly destroy
|
||||
a toplevel window, use gtk_window_destroy(). To destroy a widget that is
|
||||
part of a hierarchy, remove it from its parent using a container-specific
|
||||
remove api, such as gtk_box_remove() or gtk_stack_remove(). To destroy
|
||||
a freestanding non-toplevel widget, use g_object_unref() to drop your
|
||||
reference.
|
||||
|
||||
### Adapt to coordinate API changes
|
||||
|
||||
A number of APIs that are accepting or returning coordinates have
|
||||
been changed from ints to doubles: gtk_widget_translate_coordinates(),
|
||||
gtk_fixed_put(), gtk_fixed_move(). This change is mostly transparent,
|
||||
except for cases where out parameters are involved: you need to
|
||||
pass double* now, instead of int*.
|
||||
|
||||
### Adapt to GtkStyleContext API changes
|
||||
|
||||
The getters in the GtkStyleContext API, such as
|
||||
gtk_style_context_get_property(), gtk_style_context_get(),
|
||||
or gtk_style_context_get_color() have lost their state argument,
|
||||
and always use the context's current state. Update all callers
|
||||
to omit the state argument.
|
||||
|
||||
The most commonly used GtkStyleContext API, gtk_style_context_add_class(),
|
||||
has been moved to GtkWidget as gtk_widget_add_css_class(), as have the
|
||||
corresponding gtk_style_context_remove_class() and
|
||||
gtk_style_context_has_class() APIs.
|
||||
|
||||
### Adapt to GtkCssProvider API changes
|
||||
|
||||
In GTK 4, the various #GtkCssProvider load functions have lost their
|
||||
#GError argument. If you want to handle CSS loading errors, use the
|
||||
#GtkCssProvider::parsing-error signal instead. gtk_css_provider_get_named()
|
||||
has been replaced by gtk_css_provider_load_named().
|
||||
|
||||
### Stop using GtkShadowType and GtkRelief properties
|
||||
|
||||
The shadow-type properties in GtkScrolledWindow, GtkViewport,
|
||||
and GtkFrame, as well as the relief properties in GtkButton
|
||||
and its subclasses have been removed. GtkScrolledWindow, GtkButton
|
||||
and GtkMenuButton have instead gained a boolean has-frame
|
||||
property.
|
||||
|
||||
### Adapt to GtkWidget's size request changes
|
||||
|
||||
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
|
||||
only one virtual function, GtkWidgetClass::measure() that widgets
|
||||
have to implement. gtk_widget_measure() replaces the various
|
||||
gtk_widget_get_preferred_ functions for querying sizes.
|
||||
|
||||
### Adapt to GtkWidget's size allocation changes
|
||||
|
||||
The #GtkWidget.size_allocate() vfunc takes the baseline as an argument
|
||||
now, so you no longer need to call gtk_widget_get_allocated_baseline()
|
||||
to get it.
|
||||
|
||||
The ::size-allocate signal has been removed, since it is easy
|
||||
to misuse. If you need to learn about sizing changes of custom
|
||||
drawing widgets, use the #GtkDrawingArea::resize or #GtkGLArea::resize
|
||||
signals.
|
||||
|
||||
### Switch to GtkWidget's children APIs
|
||||
|
||||
In GTK 4, any widget can have children (and GtkContainer is gone).
|
||||
There is new API to navigate the widget tree, for use in widget
|
||||
implementations: gtk_widget_get_first_child(), gtk_widget_get_last_child(),
|
||||
gtk_widget_get_next_sibling(), gtk_widget_get_prev_sibling().
|
||||
|
||||
### Don't use -gtk-gradient in your CSS
|
||||
|
||||
GTK now supports standard CSS syntax for both linear and radial
|
||||
gradients, just use those.
|
||||
|
||||
### Don't use -gtk-icon-effect in your CSS
|
||||
|
||||
GTK now supports a more versatile -gtk-icon-filter instead. Replace
|
||||
-gtk-icon-effect: dim; with -gtk-icon-filter: opacity(0.5); and
|
||||
-gtk-icon-effect: hilight; with -gtk-icon-filter: brightness(1.2);.
|
||||
|
||||
### Don't use -gtk-icon-theme in your CSS
|
||||
|
||||
GTK now uses the current icon theme, without a way to change this.
|
||||
|
||||
### Don't use -gtk-outline-...-radius in your CSS
|
||||
|
||||
These non-standard properties have been removed from GTK
|
||||
CSS. Just use regular border radius.
|
||||
|
||||
### Adapt to drawing model changes
|
||||
|
||||
This area has seen the most radical changes in the transition from GTK 3
|
||||
to GTK 4. Widgets no longer use a draw() function to render their contents
|
||||
to a cairo surface. Instead, they have a snapshot() function that creates
|
||||
one or more GskRenderNodes to represent their content. Third-party widgets
|
||||
that use a draw() function or a #GtkWidget::draw signal handler for custom
|
||||
drawing will need to be converted to use gtk_snapshot_append_cairo().
|
||||
|
||||
The auxiliary #GtkSnapshot object has APIs to help with creating render
|
||||
nodes.
|
||||
|
||||
If you are using a #GtkDrawingArea for custom drawing, you need to switch
|
||||
to using gtk_drawing_area_set_draw_func() to set a draw function instead
|
||||
of connnecting a handler to the #GtkWidget::draw signal.
|
||||
|
||||
### Stop using APIs to query GdkSurfaces
|
||||
|
||||
A number of APIs for querying special-purpose windows have been removed,
|
||||
since these windows are no longer publically available:
|
||||
gtk_tree_view_get_bin_window(), gtk_viewport_get_bin_window(),
|
||||
gtk_viewport_get_view_window().
|
||||
|
||||
### Widgets are now visible by default
|
||||
|
||||
The default value of #GtkWidget:visible in GTK 4 is %TRUE, so you no
|
||||
longer need to explicitly show all your widgets. On the flip side, you
|
||||
need to hide widgets that are not meant to be visible from the start.
|
||||
The only widgets that still need to be explicitly shown are toplevel
|
||||
windows, dialogs and popovers.
|
||||
|
||||
A convenient way to remove unnecessary property assignments like this
|
||||
from ui files it run the command `gtk4-builder-tool simplify --replace`
|
||||
on them.
|
||||
|
||||
The function gtk_widget_show_all(), the #GtkWidget:no-show-all property
|
||||
and its getter and setter have been removed in GTK 4, so you should stop
|
||||
using them.
|
||||
|
||||
### Adapt to changes in animated hiding and showing of widgets
|
||||
|
||||
Widgets that appear and disappear with an animation, such as GtkPopover,
|
||||
GtkInfoBar, GtkRevealer no longer use gtk_widget_show() and gtk_widget_hide()
|
||||
for this, but have gained dedicated APIs for this purpose that you should
|
||||
use.
|
||||
|
||||
### Stop passing commandline arguments to gtk_init
|
||||
|
||||
The gtk_init() and gtk_init_check() functions no longer accept commandline
|
||||
arguments. Just call them without arguments. Other initialization functions
|
||||
that were purely related to commandline argument handling, such as
|
||||
gtk_parse_args() and gtk_get_option_group(), are gone. The APIs to
|
||||
initialize GDK separately are also gone, but it is very unlikely
|
||||
that you are affected by that.
|
||||
|
||||
### GdkPixbuf is deemphasized
|
||||
|
||||
A number of #GdkPixbuf-based APIs have been removed. The available replacements
|
||||
are either using #GIcon, or the newly introduced #GdkTexture or #GdkPaintable
|
||||
classes instead. If you are dealing with pixbufs, you can use
|
||||
gdk_texture_new_for_pixbuf() to convert them to texture objects where needed.
|
||||
|
||||
### GtkWidget event signals are removed
|
||||
|
||||
Event controllers and #GtkGestures have already been introduced in GTK 3 to handle
|
||||
input for many cases. In GTK 4, the traditional widget signals for handling input,
|
||||
such as #GtkWidget::motion-event or #GtkWidget::event have been removed.
|
||||
|
||||
### Invalidation handling has changed
|
||||
|
||||
Only gtk_widget_queue_draw() is left to mark a widget as needing redraw.
|
||||
Variations like gtk_widget_queue_draw_rectangle() or gtk_widget_queue_draw_region()
|
||||
are no longer available.
|
||||
|
||||
### Stop using GtkWidget::draw
|
||||
|
||||
The #GtkWidget::draw signal has been removed. Widgets need to implement the
|
||||
#GtkWidgetClass.snapshot() function now. Connecting draw signal handlers is
|
||||
no longer possible. If you want to keep using cairo for drawing, use
|
||||
gtk_snaphot_append_cairo().
|
||||
|
||||
### Window content observation has changed
|
||||
|
||||
Observing widget contents and widget size is now done by using the
|
||||
#GtkWidgetPaintable object instead of connecting to widget signals.
|
||||
|
||||
### Monitor handling has changed
|
||||
|
||||
Instead of a monitor number, #GdkMonitor is now used throughout.
|
||||
gdk_display_get_monitors() returns the list of monitors that can be queried
|
||||
or observed for monitors to pass to APIs like gtk_window_fullscreen_on_monitor().
|
||||
|
||||
### Adapt to cursor API changes
|
||||
|
||||
Use the new gtk_widget_set_cursor() function to set cursors, instead of
|
||||
setting the cursor on the underlying window directly. This is necessary
|
||||
because most widgets don't have their own window anymore, turning any
|
||||
such calls into global cursor changes.
|
||||
|
||||
For creating standard cursors, gdk_cursor_new_for_display() has been removed,
|
||||
you have to use cursor names instead of GdkCursorType. For creating custom cursors,
|
||||
use gdk_cursor_new_from_texture(). The ability to get cursor images has been removed.
|
||||
|
||||
### Adapt to icon size API changes
|
||||
|
||||
Instead of the existing extensible set of symbolic icon sizes, GTK now only
|
||||
supports normal and large icons with the #GtkIconSize enumeration. The actual sizes
|
||||
can be defined by themes via the CSS property -gtk-icon-size.
|
||||
|
||||
GtkImage setters like gtk_image_set_from_icon_name() no longer take a #GtkIconSize
|
||||
argument. You can use the separate gtk_image_set_icon_size() setter if you need
|
||||
to override the icon size.
|
||||
|
||||
The :stock-size property of GtkCellRendererPixbuf has been renamed to
|
||||
#GtkCellRendererPixbuf:icon-size.
|
||||
|
||||
### Adapt to changes in the GtkAssistant API
|
||||
|
||||
The :has-padding property is gone, and GtkAssistant no longer adds padding
|
||||
to pages. You can easily do that yourself.
|
||||
|
||||
### Adapt to changes in the API of GtkEntry, GtkSearchEntry and GtkSpinButton
|
||||
|
||||
The GtkEditable interface has been made more useful, and the core functionality of
|
||||
GtkEntry has been broken out as a GtkText widget. GtkEntry, GtkSearchEntry,
|
||||
GtkSpinButton and the new GtkPasswordEntry now use a GtkText widget internally
|
||||
and implement GtkEditable. In particular, this means that it is no longer
|
||||
possible to use GtkEntry API such as gtk_entry_grab_focus_without_selecting()
|
||||
on a search entry.
|
||||
|
||||
Use GtkEditable API for editable functionality, and widget-specific APIs for
|
||||
things that go beyond the common interface. For password entries, use
|
||||
GtkPasswordEntry. As an example, gtk_spin_button_set_max_width_chars()
|
||||
has been removed in favor of gtk_editable_set_max_width_chars().
|
||||
|
||||
### Adapt to changes in GtkOverlay API
|
||||
|
||||
The GtkOverlay :pass-through child property has been replaced by the
|
||||
#GtkWidget:can-target property. Note that they have the opposite sense:
|
||||
pass-through == !can-target.
|
||||
|
||||
### Use GtkFixed instead of GtkLayout
|
||||
|
||||
Since GtkScrolledWindow can deal with widgets that do not implement
|
||||
the GtkScrollable interface by automatically wrapping them into a
|
||||
GtkViewport, GtkLayout is redundant, and has been removed in favor
|
||||
of the existing GtkFixed container widget.
|
||||
|
||||
### Adapt to search entry changes
|
||||
|
||||
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().
|
||||
|
||||
### Stop using gtk_window_activate_default()
|
||||
|
||||
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. 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.
|
||||
|
||||
### Stop setting ::has-default and ::has-focus in .ui files
|
||||
|
||||
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.
|
||||
|
||||
### Stop using the GtkWidget::display-changed signal
|
||||
|
||||
To track the current display, use the #GtkWidget::root property instead.
|
||||
|
||||
### GtkPopover::modal has been renamed to autohide
|
||||
|
||||
The modal property has been renamed to autohide.
|
||||
gtk-builder-tool can assist with the rename in ui files.
|
||||
|
||||
### gtk_widget_get_surface has been removed
|
||||
|
||||
gtk_widget_get_surface() has been removed.
|
||||
Use gtk_native_get_surface() in combination with
|
||||
gtk_widget_get_native() instead.
|
||||
|
||||
### gtk_widget_is_toplevel has been removed
|
||||
|
||||
gtk_widget_is_toplevel() has been removed.
|
||||
Use GTK_IS_ROOT, GTK_IS_NATIVE or GTK_IS_WINDOW
|
||||
instead, as appropriate.
|
||||
|
||||
### gtk_widget_get_toplevel has been removed
|
||||
|
||||
gtk_widget_get_toplevel() has been removed.
|
||||
Use gtk_widget_get_root() or gtk_widget_get_native()
|
||||
instead, as appropriate.
|
||||
|
||||
### GtkEntryBuffer ::deleted-text has changed
|
||||
|
||||
To allow signal handlers to access the deleted text before it
|
||||
has been deleted #GtkEntryBuffer::deleted-text has changed from
|
||||
%G_SIGNAL_RUN_FIRST to %G_SIGNAL_RUN_LAST. The default handler
|
||||
removes the text from the #GtkEntryBuffer.
|
||||
|
||||
To adapt existing code, use g_signal_connect_after() or
|
||||
%G_CONNECT_AFTER when using g_signal_connect_data() or
|
||||
g_signal_connect_object().
|
||||
|
||||
### GtkMenu, GtkMenuBar and GtkMenuItem are gone
|
||||
|
||||
These widgets were heavily relying on X11-centric concepts such as
|
||||
override-redirect windows and grabs, and were hard to adjust to other
|
||||
windowing systems.
|
||||
|
||||
Menus can already be replaced using GtkPopoverMenu in GTK 3. Additionally,
|
||||
GTK 4 introduces GtkPopoverMenuBar to replace menubars. These new widgets
|
||||
can only be constructed from menu models, so the porting effort involves
|
||||
switching to menu models and actions.
|
||||
|
||||
Tabular menus were rarely used and complicated the menu code,
|
||||
so they have not been brought over to #GtkPopoverMenu. If you need
|
||||
complex layout in menu-like popups, consider directly using a
|
||||
#GtkPopover instead.
|
||||
|
||||
Since menus are gone, GtkMenuButton also lost its ability to show menus,
|
||||
and needs to be used with popovers in GTK 4.
|
||||
|
||||
### GtkToolbar has been removed
|
||||
|
||||
Toolbars were using outdated concepts such as requiring special toolitem
|
||||
widgets. Toolbars should be replaced by using a GtkBox with regular widgets
|
||||
instead and the "toolbar" style class.
|
||||
|
||||
### GtkAspectFrame is no longer a frame
|
||||
|
||||
GtkAspectFrame is no longer derived from GtkFrame and does not
|
||||
place a label and frame around its child anymore. It still lets
|
||||
you control the aspect ratio of its child.
|
||||
|
||||
### Stop using custom tooltip windows
|
||||
|
||||
Tooltips no longer use GtkWindows in GTK 4, and it is no longer
|
||||
possible to provide a custom window for tooltips. Replacing the content
|
||||
of the tooltip with a custom widget is still possible, with
|
||||
gtk_tooltip_set_custom().
|
||||
|
||||
### Switch to the new Drag-and-Drop api
|
||||
|
||||
The source-side Drag-and-Drop apis in GTK 4 have been changed to use an event
|
||||
controller, #GtkDragSource. Instead of calling gtk_drag_source_set()
|
||||
and connecting to #GtkWidget signals, you create a #GtkDragSource object,
|
||||
attach it to the widget with gtk_widget_add_controller(), and connect
|
||||
to #GtkDragSource signals. Instead of calling gtk_drag_begin() on a widget
|
||||
to start a drag manually, call gdk_drag_begin().
|
||||
The ::drag-data-get signal has been replaced by the #GtkDragSource::prepare
|
||||
signal, which returns a #GdkContentProvider for the drag operation.
|
||||
|
||||
The destination-side Drag-and-Drop apis in GTK 4 have also been changed
|
||||
to use an event controller, #GtkDropTarget. Instead of calling
|
||||
gtk_drag_dest_set() and connecting to #GtkWidget signals, you create
|
||||
a #GtkDropTarget object, attach it to the widget with
|
||||
gtk_widget_add_controller(), and connect to #GtkDropTarget signals.
|
||||
The ::drag-motion signal has been renamed to #GtkDropTarget::accept, and
|
||||
instead of ::drag-data-received, you need to use async read methods on the
|
||||
#GdkDrop object, such as gdk_drop_read_async() or gdk_drop_read_value_async().
|
||||
|
||||
### Adapt to GtkIconTheme API changes
|
||||
|
||||
gtk_icon_theme_lookup_icon() returns a #GtkIconPaintable object now, instead
|
||||
of a #GtkIconInfo. It always returns a paintable in the requested size, and
|
||||
never fails. A number of no-longer-relevant lookup flags and API variants
|
||||
have been removed.
|
||||
|
||||
### Update to GtkFileChooser API changes
|
||||
|
||||
GtkFileChooser moved to a GFile-based API. If you need to convert a
|
||||
path or a URI, use g_file_new_for_path(), g_file_new_for_commandline_arg(),
|
||||
or g_file_new_for_uri(); similarly, if you need to get a path or a URI
|
||||
from a GFile, use g_file_get_path(), or g_file_get_uri(). With the
|
||||
removal or path and URI-based functions, the "local-only" property has
|
||||
been removed; GFile can be used to access non-local as well as local
|
||||
resources.
|
||||
|
||||
The GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER action has been removed. Use
|
||||
%GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, instead. If a new folder is needed,
|
||||
the user can create one.
|
||||
|
||||
The "confirm-overwrite" signal, and the "do-overwrite-confirmation"
|
||||
property have been removed from GtkFileChooser. The file chooser widgets
|
||||
will automatically handle the confirmation of overwriting a file when
|
||||
using GTK_FILE_CHOOSER_ACTION_SAVE.
|
||||
|
||||
GtkFileChooser does not support a custom extra widget any more. If you
|
||||
need to add extra widgets, use gtk_file_chooser_add_choice() instead.
|
||||
|
||||
GtkFileChooser does not support a custom preview widget any more. If
|
||||
you need to show a custom preview, you can create your own GtkDialog
|
||||
with a GtkFileChooserWidget and your own preview widget that you
|
||||
update whenever the #GtkFileChooser::selection-changed signal is
|
||||
emitted.
|
||||
|
||||
### Stop using blocking dialog functions
|
||||
|
||||
GtkDialog, GtkNativeDialog, and GtkPrintOperation removed their
|
||||
blocking API using nested main loops. Nested main loops present
|
||||
re-entrancy issues and other hard to debug issues when coupled
|
||||
with other event sources (IPC, accessibility, network operations)
|
||||
that are not under the toolkit or the application developer's
|
||||
control. Additionally, "stop-the-world" functions do not fit
|
||||
the event-driven programming model of GTK.
|
||||
|
||||
You can replace calls to <function>gtk_dialog_run()</function>
|
||||
by specifying that the #GtkDialog must be modal using
|
||||
gtk_window_set_modal() or the %GTK_DIALOG_MODAL flag, and
|
||||
connecting to the #GtkDialog::response signal.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user