summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-03-19 18:03:16 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-03-19 18:03:16 -0400
commit31db61588543a1ba0935ac8ecb2ecac574c0a836 (patch)
treea2e2092e086a9c7d618e2c9ae1fc7b5a659e8a7a
parent3ac4c76b18cc89a841ce09f0943539f16988fd21 (diff)
downloadgtk+-31db61588543a1ba0935ac8ecb2ecac574c0a836.tar.gz
Revert "Merge branch 'disable-window-test' into 'master'"
This reverts commit 3ac4c76b18cc89a841ce09f0943539f16988fd21, reversing changes made to 6ec96d2e989d029a303b8b20ec72b86f974c0e87.
-rw-r--r--demos/gtk-demo/demo.gresource.xml1
-rw-r--r--demos/gtk-demo/fontplane.c25
-rw-r--r--demos/gtk-demo/main.c1
-rw-r--r--demos/gtk-demo/meson.build1
-rw-r--r--demos/gtk-demo/shortcut_triggers.c91
-rw-r--r--demos/gtk-demo/sliding_puzzle.c79
-rw-r--r--docs/reference/gtk/gtk4-docs.xml9
-rw-r--r--docs/reference/gtk/gtk4-sections.txt244
-rw-r--r--docs/reference/gtk/gtk4.types.in5
-rw-r--r--docs/tools/widgets.c8
-rw-r--r--gdk/broadway/broadway.js3
-rw-r--r--gdk/gdktypes.h10
-rw-r--r--gtk/gtk.h7
-rw-r--r--gtk/gtkaccelgroup.c1257
-rw-r--r--gtk/gtkaccelgroup.h176
-rw-r--r--gtk/gtkaccelgroupprivate.h16
-rw-r--r--gtk/gtkaccellabel.c590
-rw-r--r--gtk/gtkaccellabel.h10
-rw-r--r--gtk/gtkaccelmap.c1086
-rw-r--r--gtk/gtkaccelmap.h109
-rw-r--r--gtk/gtkaccelmapprivate.h39
-rw-r--r--gtk/gtkapplication.c1
-rw-r--r--gtk/gtkapplicationaccels.c521
-rw-r--r--gtk/gtkapplicationaccelsprivate.h10
-rw-r--r--gtk/gtkassistant.c8
-rw-r--r--gtk/gtkbindings.c1793
-rw-r--r--gtk/gtkbindings.h124
-rw-r--r--gtk/gtkbindingsprivate.h (renamed from gtk/inspector/shortcuts.h)21
-rw-r--r--gtk/gtkbuilder.c29
-rw-r--r--gtk/gtkcoloreditor.c25
-rw-r--r--gtk/gtkcolorplane.c37
-rw-r--r--gtk/gtkcolorscale.c39
-rw-r--r--gtk/gtkcolorswatch.c21
-rw-r--r--gtk/gtkcombobox.c155
-rw-r--r--gtk/gtkconcatmodel.c254
-rw-r--r--gtk/gtkconcatmodelprivate.h52
-rw-r--r--gtk/gtkdialog.c5
-rw-r--r--gtk/gtkemojichooser.c40
-rw-r--r--gtk/gtkentry.c1
-rw-r--r--gtk/gtkenums.h19
-rw-r--r--gtk/gtkeventcontrollerfocus.c1
-rw-r--r--gtk/gtkeventcontrollerkey.c4
-rw-r--r--gtk/gtkfilechooserwidget.c299
-rw-r--r--gtk/gtkflowbox.c101
-rw-r--r--gtk/gtkiconview.c144
-rw-r--r--gtk/gtkinfobar.c19
-rw-r--r--gtk/gtklabel.c226
-rw-r--r--gtk/gtklinkbutton.c24
-rw-r--r--gtk/gtklistbox.c97
-rw-r--r--gtk/gtkmain.c12
-rw-r--r--gtk/gtkmnemonichash.c201
-rw-r--r--gtk/gtkmnemonichash.h52
-rw-r--r--gtk/gtkmodelbutton.c6
-rw-r--r--gtk/gtkmountoperation.c21
-rw-r--r--gtk/gtknotebook.c203
-rw-r--r--gtk/gtkpaned.c194
-rw-r--r--gtk/gtkpasswordentry.c1
-rw-r--r--gtk/gtkplacesview.c62
-rw-r--r--gtk/gtkplacesviewrow.c30
-rw-r--r--gtk/gtkpopover.c83
-rw-r--r--gtk/gtkpopovermenu.c84
-rw-r--r--gtk/gtkrange.c10
-rw-r--r--gtk/gtkroot.c2
-rw-r--r--gtk/gtkscale.c13
-rw-r--r--gtk/gtkscalebutton.c40
-rw-r--r--gtk/gtkscrollbar.c11
-rw-r--r--gtk/gtkscrolledwindow.c66
-rw-r--r--gtk/gtksearchentry.c22
-rw-r--r--gtk/gtkshortcut.c392
-rw-r--r--gtk/gtkshortcut.h62
-rw-r--r--gtk/gtkshortcutaction.c1134
-rw-r--r--gtk/gtkshortcutaction.h135
-rw-r--r--gtk/gtkshortcutactionprivate.h29
-rw-r--r--gtk/gtkshortcutcontroller.c673
-rw-r--r--gtk/gtkshortcutcontroller.h70
-rw-r--r--gtk/gtkshortcutcontrollerprivate.h28
-rw-r--r--gtk/gtkshortcutlabel.c3
-rw-r--r--gtk/gtkshortcutmanager.c106
-rw-r--r--gtk/gtkshortcutmanager.h71
-rw-r--r--gtk/gtkshortcutmanagerprivate.h12
-rw-r--r--gtk/gtkshortcutssection.c36
-rw-r--r--gtk/gtkshortcutswindow.c12
-rw-r--r--gtk/gtkshortcuttrigger.c976
-rw-r--r--gtk/gtkshortcuttrigger.h121
-rw-r--r--gtk/gtkspinbutton.c32
-rw-r--r--gtk/gtktext.c309
-rw-r--r--gtk/gtktextview.c363
-rw-r--r--gtk/gtktreeview.c428
-rw-r--r--gtk/gtktypes.h3
-rw-r--r--gtk/gtkwidget.c724
-rw-r--r--gtk/gtkwidget.h39
-rw-r--r--gtk/gtkwidgetprivate.h9
-rw-r--r--gtk/gtkwindow.c859
-rw-r--r--gtk/gtkwindow.h31
-rw-r--r--gtk/gtkwindowprivate.h1
-rw-r--r--gtk/inspector/init.c2
-rw-r--r--gtk/inspector/meson.build1
-rw-r--r--gtk/inspector/shortcuts.c158
-rw-r--r--gtk/inspector/shortcuts.ui59
-rw-r--r--gtk/inspector/window.c3
-rw-r--r--gtk/inspector/window.h1
-rw-r--r--gtk/inspector/window.ui10
-rw-r--r--gtk/meson.build16
-rw-r--r--gtk/ui/gtkcoloreditor.ui6
-rw-r--r--gtk/ui/gtkfilechooserwidget.ui11
-rw-r--r--gtk/ui/gtkplacesviewrow.ui6
-rw-r--r--po-properties/POTFILES.in1
-rw-r--r--po/POTFILES.in1
-rw-r--r--tests/testgtk.c53
-rw-r--r--tests/testmenubutton.c4
-rw-r--r--testsuite/css/parser/at-invalid-22.css1
-rw-r--r--testsuite/css/parser/at-invalid-22.errors1
-rw-r--r--testsuite/css/parser/at-invalid-22.ref.css0
-rw-r--r--testsuite/css/parser/meson.build3
-rw-r--r--testsuite/gtk/accel.c15
-rw-r--r--testsuite/gtk/action.c7
-rw-r--r--testsuite/gtk/builder.c53
-rw-r--r--testsuite/gtk/concatmodel.c372
-rw-r--r--testsuite/gtk/defaultvalue.c5
-rw-r--r--testsuite/gtk/meson.build6
120 files changed, 8634 insertions, 7769 deletions
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 7e4046cb6a..4dde63322a 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -210,7 +210,6 @@
<file>search_entry.c</file>
<file>search_entry2.c</file>
<file>shortcuts.c</file>
- <file>shortcut_triggers.c</file>
<file>sizegroup.c</file>
<file>sidebar.c</file>
<file>sliding_puzzle.c</file>
diff --git a/demos/gtk-demo/fontplane.c b/demos/gtk-demo/fontplane.c
index 1f7e074adb..b7b07cb7ad 100644
--- a/demos/gtk-demo/fontplane.c
+++ b/demos/gtk-demo/fontplane.c
@@ -141,6 +141,17 @@ update_value (GtkFontPlane *plane,
}
static void
+hold_action (GtkGestureLongPress *gesture,
+ gdouble x,
+ gdouble y,
+ GtkFontPlane *plane)
+{
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
+}
+
+static void
plane_drag_gesture_begin (GtkGestureDrag *gesture,
gdouble start_x,
gdouble start_y,
@@ -150,6 +161,13 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture));
+ if (button == GDK_BUTTON_SECONDARY)
+ {
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
+ }
+
if (button != GDK_BUTTON_PRIMARY)
{
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
@@ -200,6 +218,13 @@ gtk_font_plane_init (GtkFontPlane *plane)
G_CALLBACK (plane_drag_gesture_end), plane);
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 0);
gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
+
+ gesture = gtk_gesture_long_press_new ();
+ g_signal_connect (gesture, "pressed",
+ G_CALLBACK (hold_action), plane);
+ gtk_gesture_single_set_touch_only (GTK_GESTURE_SINGLE (gesture),
+ TRUE);
+ gtk_widget_add_controller (GTK_WIDGET (plane), GTK_EVENT_CONTROLLER (gesture));
}
static void
diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c
index aef7b1922a..c552f9874e 100644
--- a/demos/gtk-demo/main.c
+++ b/demos/gtk-demo/main.c
@@ -310,6 +310,7 @@ static const char *types[] =
"GtkIconView ",
"GtkCellRendererText ",
"GtkContainer ",
+ "GtkAccelGroup ",
"GtkPaned ",
"GtkPrintOperation ",
"GtkPrintContext ",
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 08694a7355..8dbd14cc2d 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -62,7 +62,6 @@ demos = files([
'search_entry.c',
'search_entry2.c',
'shortcuts.c',
- 'shortcut_triggers.c',
'sidebar.c',
'sizegroup.c',
'sliding_puzzle.c',
diff --git a/demos/gtk-demo/shortcut_triggers.c b/demos/gtk-demo/shortcut_triggers.c
deleted file mode 100644
index d5b59c3de8..0000000000
--- a/demos/gtk-demo/shortcut_triggers.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Shortcuts
- *
- * GtkShortcut is the abstraction used by GTK to handle shortcuts from
- * keyboard or other input devices.
- *
- * Shortcut triggers can be used to weave complex sequences of key
- * presses into sophisticated mechanisms to activate shortcuts.
- *
- * This demo code shows creative ways to do that.
- */
-
-#include <gtk/gtk.h>
-
-static GtkWidget *window = NULL;
-
-static gboolean
-shortcut_activated (GtkWidget *widget,
- GVariant *unused,
- gpointer row)
-{
- g_print ("activated %s\n", gtk_label_get_label (row));
- return TRUE;
-}
-
-static GtkShortcutTrigger *
-create_ctrl_g (void)
-{
- return gtk_keyval_trigger_new (GDK_KEY_g, GDK_CONTROL_MASK);
-}
-
-static GtkShortcutTrigger *
-create_x (void)
-{
- return gtk_keyval_trigger_new (GDK_KEY_x, 0);
-}
-
-struct {
- const char *description;
- GtkShortcutTrigger * (* create_trigger_func) (void);
-} shortcuts[] = {
- { "Press Ctrl-G", create_ctrl_g },
- { "Press X", create_x },
-};
-
-GtkWidget *
-do_shortcut_triggers (GtkWidget *do_widget)
-{
- guint i;
-
- if (!window)
- {
- GtkWidget *list;
- GtkEventController *controller;
-
- window = gtk_window_new ();
- gtk_window_set_display (GTK_WINDOW (window),
- gtk_widget_get_display (do_widget));
- gtk_window_set_title (GTK_WINDOW (window), "Shortcuts");
-
- g_signal_connect (window, "destroy",
- G_CALLBACK (gtk_widget_destroyed), &window);
-
- list = gtk_list_box_new ();
- g_object_set (list, "margin", 6, NULL);
- gtk_container_add (GTK_CONTAINER (window), list);
-
- for (i = 0; i < G_N_ELEMENTS (shortcuts); i++)
- {
- GtkShortcut *shortcut;
- GtkWidget *row;
-
- row = gtk_label_new (shortcuts[i].description);
- gtk_container_add (GTK_CONTAINER (list), row);
-
- controller = gtk_shortcut_controller_new ();
- gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller), GTK_SHORTCUT_SCOPE_GLOBAL);
- gtk_widget_add_controller (row, controller);
-
- shortcut = gtk_shortcut_new (shortcuts[i].create_trigger_func(),
- gtk_callback_action_new (shortcut_activated, row, NULL));
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- }
- }
-
- if (!gtk_widget_get_visible (window))
- gtk_widget_show (window);
- else
- gtk_widget_destroy (window);
-
- return window;
-}
diff --git a/demos/gtk-demo/sliding_puzzle.c b/demos/gtk-demo/sliding_puzzle.c
index 5dcc0351bc..0abb5c9f6e 100644
--- a/demos/gtk-demo/sliding_puzzle.c
+++ b/demos/gtk-demo/sliding_puzzle.c
@@ -160,13 +160,47 @@ check_solved (GtkWidget *grid)
}
static gboolean
-puzzle_key_pressed (GtkWidget *grid,
- GVariant *args,
- gpointer unused)
+puzzle_key_pressed (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ GtkWidget *grid)
{
int dx, dy;
- g_variant_get (args, "(ii)", &dx, &dy);
+ dx = 0;
+ dy = 0;
+
+ switch (keyval)
+ {
+ case GDK_KEY_KP_Left:
+ case GDK_KEY_Left:
+ /* left */
+ dx = -1;
+ break;
+
+ case GDK_KEY_KP_Up:
+ case GDK_KEY_Up:
+ /* up */
+ dy = -1;
+ break;
+
+ case GDK_KEY_KP_Right:
+ case GDK_KEY_Right:
+ /* right */
+ dx = 1;
+ break;
+
+ case GDK_KEY_KP_Down:
+ case GDK_KEY_Down:
+ /* down */
+ dy = 1;
+ break;
+
+ default:
+ /* We return FALSE here because we didn't handle the key that was pressed */
+ return FALSE;
+ }
if (!move_puzzle (grid, dx, dy))
{
@@ -243,24 +277,6 @@ puzzle_button_pressed (GtkGestureClick *gesture,
}
static void
-add_move_binding (GtkShortcutController *controller,
- guint keyval,
- guint kp_keyval,
- int dx,
- int dy)
-{
- GtkShortcut *shortcut;
-
- shortcut = gtk_shortcut_new_with_arguments (
- gtk_alternative_trigger_new (gtk_keyval_trigger_new (keyval, 0),
- gtk_keyval_trigger_new (kp_keyval, 0)),
- gtk_callback_action_new (puzzle_key_pressed, NULL, NULL),
- "(ii)", dx, dy);
- gtk_shortcut_controller_add_shortcut (controller, shortcut);
- g_object_unref (shortcut);
-}
-
-static void
start_puzzle (GdkPaintable *paintable)
{
GtkWidget *picture, *grid;
@@ -282,21 +298,12 @@ start_puzzle (GdkPaintable *paintable)
aspect_ratio = 1.0;
gtk_aspect_frame_set (GTK_ASPECT_FRAME (frame), 0.5, 0.5, aspect_ratio, FALSE);
- /* Add shortcuts so people can use the arrow
+ /* Add a key event controller so people can use the arrow
* keys to move the puzzle */
- controller = gtk_shortcut_controller_new ();
- add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
- GDK_KEY_Left, GDK_KEY_KP_Left,
- -1, 0);
- add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
- GDK_KEY_Right, GDK_KEY_KP_Right,
- 1, 0);
- add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
- GDK_KEY_Up, GDK_KEY_KP_Up,
- 0, -1);
- add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
- GDK_KEY_Down, GDK_KEY_KP_Down,
- 0, 1);
+ controller = gtk_event_controller_key_new ();
+ g_signal_connect (controller, "key-pressed",
+ G_CALLBACK (puzzle_key_pressed),
+ grid);
gtk_widget_add_controller (GTK_WIDGET (grid), controller);
controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
diff --git a/docs/reference/gtk/gtk4-docs.xml b/docs/reference/gtk/gtk4-docs.xml
index 1bbcabc48b..aabc016df4 100644
--- a/docs/reference/gtk/gtk4-docs.xml
+++ b/docs/reference/gtk/gtk4-docs.xml
@@ -336,15 +336,6 @@
<xi:include href="xml/gtkgesturezoom.xml" />
<xi:include href="xml/gtkgesturestylus.xml" />
<xi:include href="xml/gtkpadcontroller.xml" />
- <xi:include href="xml/gtkshortcutcontroller.xml" />
- </chapter>
-
- <chapter>
- <title>Keyboard shortcuts</title>
- <xi:include href="xml/gtkshortcut.xml" />
- <xi:include href="xml/gtkshortcuttrigger.xml" />
- <xi:include href="xml/gtkshortcutaction.xml" />
- <xi:include href="xml/gtkshortcutmanager.xml" />
</chapter>
<chapter>
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 647fcafb5c..13b3f831f6 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -53,6 +53,26 @@ gtk_about_dialog_get_type
<SECTION>
<FILE>gtkaccelgroup</FILE>
<TITLE>Keyboard Accelerators</TITLE>
+GtkAccelGroup
+GtkAccelGroupClass
+gtk_accel_group_new
+GtkAccelFlags
+gtk_accel_group_connect
+gtk_accel_group_connect_by_path
+GtkAccelGroupActivate
+GtkAccelGroupFindFunc
+gtk_accel_group_disconnect
+gtk_accel_group_disconnect_key
+gtk_accel_group_activate
+gtk_accel_group_lock
+gtk_accel_group_unlock
+gtk_accel_group_get_is_locked
+gtk_accel_group_from_accel_closure
+gtk_accel_group_get_modifier_mask
+gtk_accel_groups_activate
+gtk_accel_groups_from_object
+gtk_accel_group_find
+GtkAccelKey
gtk_accelerator_valid
gtk_accelerator_parse
gtk_accelerator_name
@@ -62,6 +82,52 @@ gtk_accelerator_name_with_keycode
gtk_accelerator_get_label_with_keycode
gtk_accelerator_set_default_mod_mask
gtk_accelerator_get_default_mod_mask
+
+<SUBSECTION Standard>
+GTK_TYPE_ACCEL_GROUP
+GTK_ACCEL_GROUP
+GTK_IS_ACCEL_GROUP
+GTK_ACCEL_GROUP_CLASS
+GTK_IS_ACCEL_GROUP_CLASS
+GTK_ACCEL_GROUP_GET_CLASS
+
+<SUBSECTION Private>
+GTK_ACCEL_GROUP_GET_PRIVATE
+GtkAccelGroupPrivate
+GtkAccelGroupEntry
+gtk_accel_group_query
+gtk_accel_group_get_type
+</SECTION>
+
+<SECTION>
+<FILE>gtkaccelmap</FILE>
+<TITLE>Accelerator Maps</TITLE>
+GtkAccelMap
+GtkAccelMapForeach
+gtk_accel_map_add_entry
+gtk_accel_map_lookup_entry
+gtk_accel_map_change_entry
+gtk_accel_map_load
+gtk_accel_map_save
+gtk_accel_map_foreach
+gtk_accel_map_load_fd
+gtk_accel_map_save_fd
+gtk_accel_map_load_scanner
+gtk_accel_map_add_filter
+gtk_accel_map_foreach_unfiltered
+gtk_accel_map_get
+gtk_accel_map_lock_path
+gtk_accel_map_unlock_path
+<SUBSECTION Standard>
+GTK_ACCEL_MAP
+GTK_TYPE_ACCEL_MAP
+GTK_IS_ACCEL_MAP
+GTK_ACCEL_MAP_CLASS
+GTK_IS_ACCEL_MAP_CLASS
+GTK_ACCEL_MAP_GET_CLASS
+GtkAccelMapClass
+<SUBSECTION Private>
+gtk_accel_map_get_type
</SECTION>
<SECTION>
@@ -69,6 +135,10 @@ gtk_accelerator_get_default_mod_mask
<TITLE>GtkAccelLabel</TITLE>
GtkAccelLabel
gtk_accel_label_new
+gtk_accel_label_set_accel_closure
+gtk_accel_label_get_accel_closure
+gtk_accel_label_get_accel_widget
+gtk_accel_label_set_accel_widget
gtk_accel_label_get_accel_width
gtk_accel_label_set_accel
gtk_accel_label_get_accel
@@ -3964,9 +4034,10 @@ gtk_widget_add_tick_callback
gtk_widget_remove_tick_callback
gtk_widget_size_allocate
gtk_widget_allocate
-gtk_widget_class_add_shortcut
-gtk_widget_class_add_binding
-gtk_widget_class_add_binding_signal
+gtk_widget_add_accelerator
+gtk_widget_remove_accelerator
+gtk_widget_set_accel_path
+gtk_widget_list_accel_closures
gtk_widget_can_activate_accel
gtk_widget_activate
gtk_widget_is_focus
@@ -4182,6 +4253,8 @@ gtk_window_new
gtk_window_set_title
gtk_window_set_resizable
gtk_window_get_resizable
+gtk_window_add_accel_group
+gtk_window_remove_accel_group
gtk_window_set_modal
gtk_window_set_default_size
gtk_window_set_hide_on_close
@@ -4193,6 +4266,11 @@ gtk_window_is_active
gtk_window_is_maximized
gtk_window_get_toplevels
gtk_window_list_toplevels
+gtk_window_add_mnemonic
+gtk_window_remove_mnemonic
+gtk_window_mnemonic_activate
+gtk_window_activate_key
+gtk_window_propagate_key_event
gtk_window_get_focus
gtk_window_set_focus
gtk_window_get_default_widget
@@ -4213,6 +4291,7 @@ gtk_window_set_keep_above
gtk_window_set_keep_below
gtk_window_set_decorated
gtk_window_set_deletable
+gtk_window_set_mnemonic_modifier
gtk_window_set_accept_focus
gtk_window_set_focus_on_map
gtk_window_set_startup_id
@@ -4222,6 +4301,7 @@ gtk_window_get_default_icon_name
gtk_window_get_default_size
gtk_window_get_destroy_with_parent
gtk_window_get_icon_name
+gtk_window_get_mnemonic_modifier
gtk_window_get_modal
gtk_window_get_size
gtk_window_get_title
@@ -4538,6 +4618,26 @@ gtk_css_section_get_type
</SECTION>
<SECTION>
+<FILE>gtkbindings</FILE>
+<TITLE>Bindings</TITLE>
+GtkBindingSet
+gtk_binding_set_new
+gtk_binding_set_by_class
+gtk_binding_set_find
+gtk_bindings_activate
+gtk_bindings_activate_event
+gtk_binding_set_activate
+gtk_binding_entry_add_action
+gtk_binding_entry_add_action_variant
+GtkBindingCallback
+gtk_binding_entry_add_callback
+gtk_binding_entry_add_signal
+gtk_binding_entry_add_signal_from_string
+gtk_binding_entry_skip
+gtk_binding_entry_remove
+</SECTION>
+
+<SECTION>
<FILE>gtkenums</FILE>
<TITLE>Standard Enumerations</TITLE>
GtkBaselinePosition
@@ -5962,144 +6062,6 @@ gtk_event_controller_motion_get_type
</SECTION>
<SECTION>
-<FILE>gtkshortcuttrigger</FILE>
-<TITLE>GtkShortcutTrigger</TITLE>
-GtkShortcutTrigger
-gtk_shortcut_trigger_ref
-gtk_shortcut_trigger_unref
-GtkShortcutTriggerType
-gtk_shortcut_trigger_get_trigger_type
-gtk_shortcut_trigger_parse_string
-gtk_shortcut_trigger_trigger
-gtk_shortcut_trigger_hash
-gtk_shortcut_trigger_equal
-gtk_shortcut_trigger_compare
-gtk_shortcut_trigger_to_string
-gtk_shortcut_trigger_print
-gtk_shortcut_trigger_to_label
-gtk_shortcut_trigger_print_label
-
-<SUBSECTION>
-gtk_keyval_trigger_new
-gtk_keyval_trigger_get_modifiers
-gtk_keyval_trigger_get_keyval
-
-<SUBSECTION>
-gtk_mnemonic_trigger_new
-gtk_mnemonic_trigger_get_keyval
-
-<SUBSECTION Private>
-gtk_shortcut_trigger_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutaction</FILE>
-<TITLE>GtkShortcutAction</TITLE>
-GtkShortcutAction
-gtk_shortcut_action_ref
-gtk_shortcut_action_unref
-GtkShortcutActionType
-gtk_shortcut_action_get_action_type
-gtk_shortcut_action_to_string
-gtk_shortcut_action_print
-gtk_shortcut_action_activate
-
-<SUBSECTION>
-gtk_nothing_action_new
-
-<SUBSECTION>
-gtk_callback_action_new
-
-<SUBSECTION>
-gtk_mnemonic_action_new
-
-<SUBSECTION>
-gtk_activate_action_new
-
-<SUBSECTION>
-gtk_signal_action_new
-gtk_signal_action_get_signal_name
-
-<SUBSECTION>
-gtk_action_action_new
-gtk_action_action_get_name
-
-<SUBSECTION>
-gtk_gaction_action_new
-gtk_gaction_action_get_gaction
-
-<SUBSECTION Private>
-gtk_shortcut_action_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcut</FILE>
-<TITLE>GtkShortcut</TITLE>
-GtkShortcut
-gtk_shortcut_new
-gtk_shortcut_new_with_arguments
-gtk_shortcut_get_trigger
-gtk_shortcut_set_trigger
-gtk_shortcut_get_action
-gtk_shortcut_set_action
-gtk_shortcut_get_arguments
-gtk_shortcut_set_arguments
-
-<SUBSECTION Standard>
-GTK_TYPE_SHORTCUT
-GTK_SHORTCUT
-GTK_SHORTCUT_CLASS
-GTK_IS_SHORTCUT
-GTK_IS_SHORTCUT_CLASS
-GTK_SHORTCUT_GET_CLASS
-
-<SUBSECTION Private>
-gtk_shortcut_get_type
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutmanager</FILE>
-<TITLE>GtkShortcutManager</TITLE>
-GtkShortcutManager
-GtkShortcutManagerInterface
-</SECTION>
-
-<SECTION>
-<FILE>gtkshortcutcontroller</FILE>
-<TITLE>GtkShortcutController</TITLE>
-GtkShortcutController
-gtk_shortcut_controller_new
-gtk_shortcut_controller_new_with_model
-GtkShortcutScope
-GtkShortcutManager
-GtkShortcutManagerInterface
-gtk_shortcut_controller_set_mnemonics_modifiers
-gtk_shortcut_controller_get_mnemonics_modifiers
-gtk_shortcut_controller_set_scope
-gtk_shortcut_controller_get_scope
-gtk_shortcut_controller_add_shortcut
-gtk_shortcut_controller_remove_shortcut
-
-<SUBSECTION Standard>
-GTK_TYPE_SHORTCUT_CONTROLLER
-GTK_SHORTCUT_CONTROLLER
-GTK_SHORTCUT_CONTROLLER_CLASS
-GTK_IS_SHORTCUT_CONTROLLER
-GTK_IS_SHORTCUT_CONTROLLER_CLASS
-GTK_SHORTCUT_CONTROLLER_GET_CLASS
-GTK_TYPE_SHORTCUT_MANAGER
-GTK_SHORTCUT_MANAGER
-GTK_SHORTCUT_MANAGER_CLASS
-GTK_IS_SHORTCUT_MANAGER
-GTK_IS_SHORTCUT_MANAGER_CLASS
-GTK_SHORTCUT_MANAGER_GET_CLASS
-
-<SUBSECTION Private>
-gtk_shortcut_controller_get_type
-gtk_shortcut_manager_get_type
-</SECTION>
-
-<SECTION>
<FILE>gtkeventcontrollerkey</FILE>
<TITLE>GtkEventControllerKey</TITLE>
GtkEventControllerKey
diff --git a/docs/reference/gtk/gtk4.types.in b/docs/reference/gtk/gtk4.types.in
index d7d9b0106b..1c7b9eabb2 100644
--- a/docs/reference/gtk/gtk4.types.in
+++ b/docs/reference/gtk/gtk4.types.in
@@ -2,7 +2,9 @@
#include <gtk/gtkunixprint.h>
gtk_about_dialog_get_type
+gtk_accel_group_get_type
gtk_accel_label_get_type
+gtk_accel_map_get_type
gtk_accessible_get_type
gtk_actionable_get_type
gtk_action_bar_get_type
@@ -163,10 +165,7 @@ gtk_search_entry_get_type
gtk_selection_model_get_type
gtk_separator_get_type
gtk_settings_get_type
-gtk_shortcut_get_type
-gtk_shortcut_controller_get_type
gtk_shortcut_label_get_type
-gtk_shortcut_manager_get_type
gtk_shortcuts_window_get_type
gtk_shortcuts_section_get_type
gtk_shortcuts_group_get_type
diff --git a/docs/tools/widgets.c b/docs/tools/widgets.c
index 7b63677368..fba3e02a0a 100644
--- a/docs/tools/widgets.c
+++ b/docs/tools/widgets.c
@@ -281,20 +281,26 @@ create_accel_label (void)
{
WidgetInfo *info;
GtkWidget *widget, *button, *box;
+ GtkAccelGroup *accel_group;
widget = gtk_accel_label_new ("Accel Label");
button = gtk_button_new_with_label ("Quit");
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (widget), button);
gtk_widget_hide (button);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (box), widget);
gtk_container_add (GTK_CONTAINER (box), button);
- gtk_accel_label_set_accel (GTK_ACCEL_LABEL (widget), GDK_KEY_Q, GDK_CONTROL_MASK);
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (widget), button);
+ accel_group = gtk_accel_group_new();
info = new_widget_info ("accel-label", box, SMALL);
+ gtk_widget_add_accelerator (button, "activate", accel_group, GDK_KEY_Q, GDK_CONTROL_MASK,
+ GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
+
return info;
}
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 6cb576d40c..267ef205ee 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -75,7 +75,7 @@ const GDK_CROSSING_GRAB = 1;
const GDK_CROSSING_UNGRAB = 2;
// GdkModifierType
-const GDK_SHIFT_MASK = 1 << 0;
+const GDK_SHIFT_MASK = 1 << 0;
const GDK_LOCK_MASK = 1 << 1;
const GDK_CONTROL_MASK = 1 << 2;
const GDK_MOD1_MASK = 1 << 3;
@@ -91,6 +91,7 @@ const GDK_BUTTON5_MASK = 1 << 12;
const GDK_SUPER_MASK = 1 << 26;
const GDK_HYPER_MASK = 1 << 27;
const GDK_META_MASK = 1 << 28;
+const GDK_RELEASE_MASK = 1 << 30;
var useDataUrls = window.location.search.includes("datauri");
diff --git a/gdk/gdktypes.h b/gdk/gdktypes.h
index 7eb74b080f..5b0f6be7cc 100644
--- a/gdk/gdktypes.h
+++ b/gdk/gdktypes.h
@@ -232,7 +232,8 @@ typedef enum
* @GDK_HYPER_MASK: the Hyper modifier
* @GDK_META_MASK: the Meta modifier
* @GDK_MODIFIER_RESERVED_29_MASK: A reserved bit flag; do not use in your own code
- * @GDK_MODIFIER_RESERVED_30_MASK: A reserved bit flag; do not use in your own code
+ * @GDK_RELEASE_MASK: not used in GDK itself. GTK uses it to differentiate
+ * between (keyval, modifiers) pairs from key press and release events.
* @GDK_MODIFIER_MASK: a mask covering all modifier types.
*
* A set of bit-flags to indicate the state of modifier keys and mouse buttons
@@ -293,11 +294,12 @@ typedef enum
GDK_META_MASK = 1 << 28,
GDK_MODIFIER_RESERVED_29_MASK = 1 << 29,
- GDK_MODIFIER_RESERVED_30_MASK = 1 << 30,
+
+ GDK_RELEASE_MASK = 1 << 30,
/* Combination of GDK_SHIFT_MASK..GDK_BUTTON5_MASK + GDK_SUPER_MASK
- + GDK_HYPER_MASK + GDK_META_MASK */
- GDK_MODIFIER_MASK = 0x1c001fff
+ + GDK_HYPER_MASK + GDK_META_MASK + GDK_RELEASE_MASK */
+ GDK_MODIFIER_MASK = 0x5c001fff
} GdkModifierType;
/**
diff --git a/gtk/gtk.h b/gtk/gtk.h
index 8fe078e6a9..603fe9f9fd 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -34,6 +34,7 @@
#include <gtk/gtkaboutdialog.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkaccellabel.h>
+#include <gtk/gtkaccelmap.h>
#include <gtk/gtkaccessible.h>
#include <gtk/gtkactionable.h>
#include <gtk/gtkactionbar.h>
@@ -48,6 +49,7 @@
#include <gtk/gtkassistant.h>
#include <gtk/gtkbin.h>
#include <gtk/gtkbinlayout.h>
+#include <gtk/gtkbindings.h>
#include <gtk/gtkborder.h>
#include <gtk/gtkboxlayout.h>
#include <gtk/gtkbox.h>
@@ -196,16 +198,11 @@
#include <gtk/gtkselectionmodel.h>
#include <gtk/gtkseparator.h>
#include <gtk/gtksettings.h>
-#include <gtk/gtkshortcut.h>
-#include <gtk/gtkshortcutaction.h>
-#include <gtk/gtkshortcutcontroller.h>
#include <gtk/gtkshortcutlabel.h>
-#include <gtk/gtkshortcutmanager.h>
#include <gtk/gtkshortcutsgroup.h>
#include <gtk/gtkshortcutssection.h>
#include <gtk/gtkshortcutsshortcut.h>
#include <gtk/gtkshortcutswindow.h>
-#include <gtk/gtkshortcuttrigger.h>
#include <gtk/gtkshow.h>
#include <gtk/gtksingleselection.h>
#include <gtk/gtkslicelistmodel.h>
diff --git a/gtk/gtkaccelgroup.c b/gtk/gtkaccelgroup.c
index 553ec84ce3..dbf4e261af 100644
--- a/gtk/gtkaccelgroup.c
+++ b/gtk/gtkaccelgroup.c
@@ -29,6 +29,7 @@
#include "gtkaccelgroup.h"
#include "gtkaccelgroupprivate.h"
#include "gtkaccellabelprivate.h"
+#include "gtkaccelmapprivate.h"
#include "gtkintl.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
@@ -55,11 +56,893 @@
* and mnemonics, of course.
*/
+/* --- prototypes --- */
+static void gtk_accel_group_finalize (GObject *object);
+static void gtk_accel_group_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void accel_closure_invalidate (gpointer data,
+ GClosure *closure);
+
+
/* --- variables --- */
+static guint signal_accel_activate = 0;
+static guint signal_accel_changed = 0;
+static guint quark_acceleratable_groups = 0;
static guint default_accel_mod_mask = 0;
+enum {
+ PROP_0,
+ PROP_IS_LOCKED,
+ PROP_MODIFIER_MASK,
+ N_PROPERTIES
+};
+
+static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelGroup, gtk_accel_group, G_TYPE_OBJECT)
+
/* --- functions --- */
+static void
+gtk_accel_group_class_init (GtkAccelGroupClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ quark_acceleratable_groups = g_quark_from_static_string ("gtk-acceleratable-accel-groups");
+
+ object_class->finalize = gtk_accel_group_finalize;
+ object_class->get_property = gtk_accel_group_get_property;
+
+ class->accel_changed = NULL;
+
+ obj_properties [PROP_IS_LOCKED] =
+ g_param_spec_boolean ("is-locked",
+ "Is locked",
+ "Is the accel group locked",
+ FALSE,
+ G_PARAM_READABLE);
+
+ obj_properties [PROP_MODIFIER_MASK] =
+ g_param_spec_flags ("modifier-mask",
+ "Modifier Mask",
+ "Modifier Mask",
+ GDK_TYPE_MODIFIER_TYPE,
+ default_accel_mod_mask,
+ G_PARAM_READABLE);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ obj_properties);
+
+ /**
+ * GtkAccelGroup::accel-activate:
+ * @accel_group: the #GtkAccelGroup which received the signal
+ * @acceleratable: the object on which the accelerator was activated
+ * @keyval: the accelerator keyval
+ * @modifier: the modifier combination of the accelerator
+ *
+ * The accel-activate signal is an implementation detail of
+ * #GtkAccelGroup and not meant to be used by applications.
+ *
+ * Returns: %TRUE if the accelerator was activated
+ */
+ signal_accel_activate =
+ g_signal_new (I_("accel-activate"),
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_DETAILED,
+ 0,
+ _gtk_boolean_handled_accumulator, NULL,
+ _gtk_marshal_BOOLEAN__OBJECT_UINT_FLAGS,
+ G_TYPE_BOOLEAN, 3,
+ G_TYPE_OBJECT,
+ G_TYPE_UINT,
+ GDK_TYPE_MODIFIER_TYPE);
+ /**
+ * GtkAccelGroup::accel-changed:
+ * @accel_group: the #GtkAccelGroup which received the signal
+ * @keyval: the accelerator keyval
+ * @modifier: the modifier combination of the accelerator
+ * @accel_closure: the #GClosure of the accelerator
+ *
+ * The accel-changed signal is emitted when an entry
+ * is added to or removed from the accel group.
+ *
+ * Widgets like #GtkAccelLabel which display an associated
+ * accelerator should connect to this signal, and rebuild
+ * their visual representation if the @accel_closure is theirs.
+ */
+ signal_accel_changed =
+ g_signal_new (I_("accel-changed"),
+ G_OBJECT_CLASS_TYPE (class),
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ G_STRUCT_OFFSET (GtkAccelGroupClass, accel_changed),
+ NULL, NULL,
+ _gtk_marshal_VOID__UINT_FLAGS_BOXED,
+ G_TYPE_NONE, 3,
+ G_TYPE_UINT,
+ GDK_TYPE_MODIFIER_TYPE,
+ G_TYPE_CLOSURE);
+}
+
+static void
+gtk_accel_group_finalize (GObject *object)
+{
+ GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
+ guint i;
+
+ for (i = 0; i < accel_group->priv->n_accels; i++)
+ {
+ GtkAccelGroupEntry *entry = &accel_group->priv->priv_accels[i];
+
+ if (entry->accel_path_quark)
+ {
+ const gchar *accel_path = g_quark_to_string (entry->accel_path_quark);
+
+ _gtk_accel_map_remove_group (accel_path, accel_group);
+ }
+ g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
+
+ /* remove quick_accel_add() refcount */
+ g_closure_unref (entry->closure);
+ }
+
+ g_free (accel_group->priv->priv_accels);
+
+ G_OBJECT_CLASS (gtk_accel_group_parent_class)->finalize (object);
+}
+
+static void
+gtk_accel_group_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
+
+ switch (param_id)
+ {
+ case PROP_IS_LOCKED:
+ g_value_set_boolean (value, accel_group->priv->lock_count > 0);
+ break;
+ case PROP_MODIFIER_MASK:
+ g_value_set_flags (value, accel_group->priv->modifier_mask);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+gtk_accel_group_init (GtkAccelGroup *accel_group)
+{
+ GtkAccelGroupPrivate *priv;
+
+ accel_group->priv = gtk_accel_group_get_instance_private (accel_group);
+ priv = accel_group->priv;
+
+ priv->lock_count = 0;
+ priv->modifier_mask = gtk_accelerator_get_default_mod_mask ();
+ priv->acceleratables = NULL;
+ priv->n_accels = 0;
+ priv->priv_accels = NULL;
+}
+
+/**
+ * gtk_accel_group_new:
+ *
+ * Creates a new #GtkAccelGroup.
+ *
+ * Returns: a new #GtkAccelGroup object
+ */
+GtkAccelGroup*
+gtk_accel_group_new (void)
+{
+ return g_object_new (GTK_TYPE_ACCEL_GROUP, NULL);
+}
+
+/**
+ * gtk_accel_group_get_is_locked:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Locks are added and removed using gtk_accel_group_lock() and
+ * gtk_accel_group_unlock().
+ *
+ * Returns: %TRUE if there are 1 or more locks on the @accel_group,
+ * %FALSE otherwise.
+ */
+gboolean
+gtk_accel_group_get_is_locked (GtkAccelGroup *accel_group)
+{
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ return accel_group->priv->lock_count > 0;
+}
+
+/**
+ * gtk_accel_group_get_modifier_mask:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Gets a #GdkModifierType representing the mask for this
+ * @accel_group. For example, #GDK_CONTROL_MASK, #GDK_SHIFT_MASK, etc.
+ *
+ * Returns: the modifier mask for this accel group.
+ */
+GdkModifierType
+gtk_accel_group_get_modifier_mask (GtkAccelGroup *accel_group)
+{
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), 0);
+
+ return accel_group->priv->modifier_mask;
+}
+
+static void
+accel_group_weak_ref_detach (GSList *free_list,
+ GObject *stale_object)
+{
+ GSList *slist;
+
+ for (slist = free_list; slist; slist = slist->next)
+ {
+ GtkAccelGroup *accel_group;
+
+ accel_group = slist->data;
+ accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, stale_object);
+ g_object_unref (accel_group);
+ }
+ g_slist_free (free_list);
+ g_object_set_qdata (stale_object, quark_acceleratable_groups, NULL);
+}
+
+void
+_gtk_accel_group_attach (GtkAccelGroup *accel_group,
+ GObject *object)
+{
+ GSList *slist;
+
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) == NULL);
+
+ g_object_ref (accel_group);
+ accel_group->priv->acceleratables = g_slist_prepend (accel_group->priv->acceleratables, object);
+ slist = g_object_get_qdata (object, quark_acceleratable_groups);
+ if (slist)
+ g_object_weak_unref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
+ slist = g_slist_prepend (slist, accel_group);
+ g_object_set_qdata (object, quark_acceleratable_groups, slist);
+ g_object_weak_ref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
+}
+
+void
+_gtk_accel_group_detach (GtkAccelGroup *accel_group,
+ GObject *object)
+{
+ GSList *slist;
+
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (G_IS_OBJECT (object));
+ g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) != NULL);
+
+ accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, object);
+ slist = g_object_get_qdata (object, quark_acceleratable_groups);
+ g_object_weak_unref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
+ slist = g_slist_remove (slist, accel_group);
+ g_object_set_qdata (object, quark_acceleratable_groups, slist);
+ if (slist)
+ g_object_weak_ref (object,
+ (GWeakNotify) accel_group_weak_ref_detach,
+ slist);
+ g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_groups_from_object:
+ * @object: a #GObject, usually a #GtkWindow
+ *
+ * Gets a list of all accel groups which are attached to @object.
+ *
+ * Returns: (element-type GtkAccelGroup) (transfer none): a list of
+ * all accel groups which are attached to @object
+ */
+GSList*
+gtk_accel_groups_from_object (GObject *object)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+
+ return g_object_get_qdata (object, quark_acceleratable_groups);
+}
+
+/**
+ * gtk_accel_group_find:
+ * @accel_group: a #GtkAccelGroup
+ * @find_func: (scope call): a function to filter the entries
+ * of @accel_group with
+ * @data: data to pass to @find_func
+ *
+ * Finds the first entry in an accelerator group for which
+ * @find_func returns %TRUE and returns its #GtkAccelKey.
+ *
+ * Returns: (transfer none): the key of the first entry passing
+ * @find_func. The key is owned by GTK+ and must not be freed.
+ */
+GtkAccelKey*
+gtk_accel_group_find (GtkAccelGroup *accel_group,
+ GtkAccelGroupFindFunc find_func,
+ gpointer data)
+{
+ GtkAccelKey *key = NULL;
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+ g_return_val_if_fail (find_func != NULL, NULL);
+
+ g_object_ref (accel_group);
+ for (i = 0; i < accel_group->priv->n_accels; i++)
+ if (find_func (&accel_group->priv->priv_accels[i].key,
+ accel_group->priv->priv_accels[i].closure,
+ data))
+ {
+ key = &accel_group->priv->priv_accels[i].key;
+ break;
+ }
+ g_object_unref (accel_group);
+
+ return key;
+}
+
+/**
+ * gtk_accel_group_lock:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Locks the given accelerator group.
+ *
+ * Locking an acelerator group prevents the accelerators contained
+ * within it to be changed during runtime. Refer to
+ * gtk_accel_map_change_entry() about runtime accelerator changes.
+ *
+ * If called more than once, @accel_group remains locked until
+ * gtk_accel_group_unlock() has been called an equivalent number
+ * of times.
+ */
+void
+gtk_accel_group_lock (GtkAccelGroup *accel_group)
+{
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ accel_group->priv->lock_count += 1;
+
+ if (accel_group->priv->lock_count == 1) {
+ /* State change from unlocked to locked */
+ g_object_notify_by_pspec (G_OBJECT (accel_group), obj_properties[PROP_IS_LOCKED]);
+ }
+}
+
+/**
+ * gtk_accel_group_unlock:
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Undoes the last call to gtk_accel_group_lock() on this @accel_group.
+ */
+void
+gtk_accel_group_unlock (GtkAccelGroup *accel_group)
+{
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (accel_group->priv->lock_count > 0);
+
+ accel_group->priv->lock_count -= 1;
+
+ if (accel_group->priv->lock_count < 1) {
+ /* State change from locked to unlocked */
+ g_object_notify_by_pspec (G_OBJECT (accel_group), obj_properties[PROP_IS_LOCKED]);
+ }
+}
+
+static void
+accel_closure_invalidate (gpointer data,
+ GClosure *closure)
+{
+ GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (data);
+
+ gtk_accel_group_disconnect (accel_group, closure);
+}
+
+static int
+bsearch_compare_accels (const void *d1,
+ const void *d2)
+{
+ const GtkAccelGroupEntry *entry1 = d1;
+ const GtkAccelGroupEntry *entry2 = d2;
+
+ if (entry1->key.accel_key == entry2->key.accel_key)
+ return entry1->key.accel_mods < entry2->key.accel_mods ? -1 : entry1->key.accel_mods > entry2->key.accel_mods;
+ else
+ return entry1->key.accel_key < entry2->key.accel_key ? -1 : 1;
+}
+
+static void
+quick_accel_add (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure,
+ GQuark path_quark)
+{
+ guint pos, i = accel_group->priv->n_accels++;
+ GtkAccelGroupEntry key;
+
+ /* find position */
+ key.key.accel_key = accel_key;
+ key.key.accel_mods = accel_mods;
+ for (pos = 0; pos < i; pos++)
+ if (bsearch_compare_accels (&key, accel_group->priv->priv_accels + pos) < 0)
+ break;
+
+ /* insert at position, ref closure */
+ accel_group->priv->priv_accels = g_renew (GtkAccelGroupEntry, accel_group->priv->priv_accels, accel_group->priv->n_accels);
+ memmove (accel_group->priv->priv_accels + pos + 1, accel_group->priv->priv_accels + pos,
+ (i - pos) * sizeof (accel_group->priv->priv_accels[0]));
+ accel_group->priv->priv_accels[pos].key.accel_key = accel_key;
+ accel_group->priv->priv_accels[pos].key.accel_mods = accel_mods;
+ accel_group->priv->priv_accels[pos].key.accel_flags = accel_flags;
+ accel_group->priv->priv_accels[pos].closure = g_closure_ref (closure);
+ accel_group->priv->priv_accels[pos].accel_path_quark = path_quark;
+ g_closure_sink (closure);
+
+ /* handle closure invalidation and reverse lookups */
+ g_closure_add_invalidate_notifier (closure, accel_group, accel_closure_invalidate);
+
+ /* get accel path notification */
+ if (path_quark)
+ _gtk_accel_map_add_group (g_quark_to_string (path_quark), accel_group);
+
+ /* connect and notify changed */
+ if (accel_key)
+ {
+ gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
+ GQuark accel_quark = g_quark_from_string (accel_name);
+
+ g_free (accel_name);
+
+ /* setup handler */
+ g_signal_connect_closure_by_id (accel_group, signal_accel_activate, accel_quark, closure, FALSE);
+
+ /* and notify */
+ g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+ }
+}
+
+static void
+quick_accel_remove (GtkAccelGroup *accel_group,
+ guint pos)
+{
+ GQuark accel_quark = 0;
+ GtkAccelGroupEntry *entry = accel_group->priv->priv_accels + pos;
+ guint accel_key = entry->key.accel_key;
+ GdkModifierType accel_mods = entry->key.accel_mods;
+ GClosure *closure = entry->closure;
+
+ /* quark for notification */
+ if (accel_key)
+ {
+ gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
+
+ accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+ }
+
+ /* clean up closure invalidate notification and disconnect */
+ g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
+ if (accel_quark)
+ g_signal_handlers_disconnect_matched (accel_group,
+ G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_CLOSURE,
+ signal_accel_activate, accel_quark,
+ closure, NULL, NULL);
+ /* clean up accel path notification */
+ if (entry->accel_path_quark)
+ _gtk_accel_map_remove_group (g_quark_to_string (entry->accel_path_quark), accel_group);
+
+ /* physically remove */
+ accel_group->priv->n_accels -= 1;
+ memmove (entry, entry + 1,
+ (accel_group->priv->n_accels - pos) * sizeof (accel_group->priv->priv_accels[0]));
+
+ /* and notify */
+ if (accel_quark)
+ g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
+
+ /* remove quick_accel_add() refcount */
+ g_closure_unref (closure);
+}
+
+static GtkAccelGroupEntry*
+quick_accel_find (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ guint *count_p)
+{
+ GtkAccelGroupEntry *entry;
+ GtkAccelGroupEntry key;
+
+ *count_p = 0;
+
+ if (!accel_group->priv->n_accels)
+ return NULL;
+
+ key.key.accel_key = accel_key;
+ key.key.accel_mods = accel_mods;
+ entry = bsearch (&key, accel_group->priv->priv_accels, accel_group->priv->n_accels,
+ sizeof (accel_group->priv->priv_accels[0]), bsearch_compare_accels);
+
+ if (!entry)
+ return NULL;
+
+ /* step back to the first member */
+ for (; entry > accel_group->priv->priv_accels; entry--)
+ if (entry[-1].key.accel_key != accel_key ||
+ entry[-1].key.accel_mods != accel_mods)
+ break;
+ /* count equal members */
+ for (; entry + *count_p < accel_group->priv->priv_accels + accel_group->priv->n_accels; (*count_p)++)
+ if (entry[*count_p].key.accel_key != accel_key ||
+ entry[*count_p].key.accel_mods != accel_mods)
+ break;
+ return entry;
+}
+
+/**
+ * gtk_accel_group_connect:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @accel_flags: a flag mask to configure this accelerator
+ * @closure: closure to be executed upon accelerator activation
+ *
+ * Installs an accelerator in this group. When @accel_group is being
+ * activated in response to a call to gtk_accel_groups_activate(),
+ * @closure will be invoked if the @accel_key and @accel_mods from
+ * gtk_accel_groups_activate() match those of this connection.
+ *
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ *
+ * Note that, due to implementation details, a single closure can
+ * only be connected to one accelerator group.
+ */
+void
+gtk_accel_group_connect (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure)
+{
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (accel_key > 0);
+ g_return_if_fail (gtk_accel_group_from_accel_closure (closure) == NULL);
+
+ g_object_ref (accel_group);
+ if (!closure->is_invalid)
+ quick_accel_add (accel_group,
+ gdk_keyval_to_lower (accel_key),
+ accel_mods, accel_flags, closure, 0);
+ g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_group_connect_by_path:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_path: path used for determining key and modifiers
+ * @closure: closure to be executed upon accelerator activation
+ *
+ * Installs an accelerator in this group, using an accelerator path
+ * to look up the appropriate key and modifiers (see
+ * gtk_accel_map_add_entry()). When @accel_group is being activated
+ * in response to a call to gtk_accel_groups_activate(), @closure will
+ * be invoked if the @accel_key and @accel_mods from
+ * gtk_accel_groups_activate() match the key and modifiers for the path.
+ *
+ * The signature used for the @closure is that of #GtkAccelGroupActivate.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore,
+ * if you pass a static string, you can save some memory by interning it
+ * first with g_intern_static_string().
+ */
+void
+gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group,
+ const gchar *accel_path,
+ GClosure *closure)
+{
+ guint accel_key = 0;
+ GdkModifierType accel_mods = 0;
+ GtkAccelKey key;
+
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+ if (closure->is_invalid)
+ return;
+
+ g_object_ref (accel_group);
+
+ if (gtk_accel_map_lookup_entry (accel_path, &key))
+ {
+ accel_key = gdk_keyval_to_lower (key.accel_key);
+ accel_mods = key.accel_mods;
+ }
+
+ quick_accel_add (accel_group, accel_key, accel_mods, GTK_ACCEL_VISIBLE, closure,
+ g_quark_from_string (accel_path));
+
+ g_object_unref (accel_group);
+}
+
+/**
+ * gtk_accel_group_disconnect:
+ * @accel_group: the accelerator group to remove an accelerator from
+ * @closure: (allow-none): the closure to remove from this accelerator
+ * group, or %NULL to remove all closures
+ *
+ * Removes an accelerator previously installed through
+ * gtk_accel_group_connect().
+ *
+ * Returns: %TRUE if the closure was found and got disconnected
+ */
+gboolean
+gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
+ GClosure *closure)
+{
+ guint i;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ for (i = 0; i < accel_group->priv->n_accels; i++)
+ if (accel_group->priv->priv_accels[i].closure == closure)
+ {
+ g_object_ref (accel_group);
+ quick_accel_remove (accel_group, i);
+ g_object_unref (accel_group);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * gtk_accel_group_disconnect_key:
+ * @accel_group: the accelerator group to install an accelerator in
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ *
+ * Removes an accelerator previously installed through
+ * gtk_accel_group_connect().
+ *
+ * Returns: %TRUE if there was an accelerator which could be
+ * removed, %FALSE otherwise
+ */
+gboolean
+gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods)
+{
+ GtkAccelGroupEntry *entries;
+ GSList *slist, *clist = NULL;
+ gboolean removed_one = FALSE;
+ guint n;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+
+ g_object_ref (accel_group);
+
+ accel_key = gdk_keyval_to_lower (accel_key);
+ entries = quick_accel_find (accel_group, accel_key, accel_mods, &n);
+ while (n--)
+ {
+ GClosure *closure = g_closure_ref (entries[n].closure);
+
+ clist = g_slist_prepend (clist, closure);
+ }
+
+ for (slist = clist; slist; slist = slist->next)
+ {
+ GClosure *closure = slist->data;
+
+ removed_one |= gtk_accel_group_disconnect (accel_group, closure);
+ g_closure_unref (closure);
+ }
+ g_slist_free (clist);
+
+ g_object_unref (accel_group);
+
+ return removed_one;
+}
+
+void
+_gtk_accel_group_reconnect (GtkAccelGroup *accel_group,
+ GQuark accel_path_quark)
+{
+ GSList *slist, *clist = NULL;
+ guint i;
+
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ g_object_ref (accel_group);
+
+ for (i = 0; i < accel_group->priv->n_accels; i++)
+ if (accel_group->priv->priv_accels[i].accel_path_quark == accel_path_quark)
+ {
+ GClosure *closure = g_closure_ref (accel_group->priv->priv_accels[i].closure);
+
+ clist = g_slist_prepend (clist, closure);
+ }
+
+ for (slist = clist; slist; slist = slist->next)
+ {
+ GClosure *closure = slist->data;
+
+ gtk_accel_group_disconnect (accel_group, closure);
+ gtk_accel_group_connect_by_path (accel_group, g_quark_to_string (accel_path_quark), closure);
+ g_closure_unref (closure);
+ }
+ g_slist_free (clist);
+
+ g_object_unref (accel_group);
+}
+
+GSList*
+_gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group)
+{
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+ return accel_group->priv->acceleratables;
+}
+
+/**
+ * gtk_accel_group_query:
+ * @accel_group: the accelerator group to query
+ * @accel_key: key value of the accelerator
+ * @accel_mods: modifier combination of the accelerator
+ * @n_entries: (out) (optional): location to return the number
+ * of entries found, or %NULL
+ *
+ * Queries an accelerator group for all entries matching @accel_key
+ * and @accel_mods.
+ *
+ * Returns: (nullable) (transfer none) (array length=n_entries): an array of
+ * @n_entries #GtkAccelGroupEntry elements, or %NULL. The array
+ * is owned by GTK+ and must not be freed.
+ */
+GtkAccelGroupEntry*
+gtk_accel_group_query (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ guint *n_entries)
+{
+ GtkAccelGroupEntry *entries;
+ guint n;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
+
+ entries = quick_accel_find (accel_group, gdk_keyval_to_lower (accel_key), accel_mods, &n);
+
+ if (n_entries)
+ *n_entries = entries ? n : 0;
+
+ return entries;
+}
+
+/**
+ * gtk_accel_group_from_accel_closure:
+ * @closure: a #GClosure
+ *
+ * Finds the #GtkAccelGroup to which @closure is connected;
+ * see gtk_accel_group_connect().
+ *
+ * Returns: (nullable) (transfer none): the #GtkAccelGroup to which @closure
+ * is connected, or %NULL
+ */
+GtkAccelGroup*
+gtk_accel_group_from_accel_closure (GClosure *closure)
+{
+ guint i;
+
+ g_return_val_if_fail (closure != NULL, NULL);
+
+ /* A few remarks on what we do here. in general, we need a way to
+ * reverse lookup accel_groups from closures that are being used in
+ * accel groups. this could be done e.g via a hashtable. it is however
+ * cheaper (memory wise) to just use the invalidation notifier on the
+ * closure itself (which we need to install anyway), that contains the
+ * accel group as data which, besides needing to peek a bit at closure
+ * internals, works just as good.
+ */
+ for (i = 0; i < G_CLOSURE_N_NOTIFIERS (closure); i++)
+ if (closure->notifiers[i].notify == accel_closure_invalidate)
+ return closure->notifiers[i].data;
+
+ return NULL;
+}
+
+/**
+ * gtk_accel_group_activate:
+ * @accel_group: a #GtkAccelGroup
+ * @accel_quark: the quark for the accelerator name
+ * @acceleratable: the #GObject, usually a #GtkWindow, on which
+ * to activate the accelerator
+ * @accel_key: accelerator keyval from a key event
+ * @accel_mods: keyboard state mask from a key event
+ *
+ * Finds the first accelerator in @accel_group that matches
+ * @accel_key and @accel_mods, and activates it.
+ *
+ * Returns: %TRUE if an accelerator was activated and handled
+ * this keypress
+ */
+gboolean
+gtk_accel_group_activate (GtkAccelGroup *accel_group,
+ GQuark accel_quark,
+ GObject *acceleratable,
+ guint accel_key,
+ GdkModifierType accel_mods)
+{
+ gboolean was_handled;
+
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
+ g_return_val_if_fail (G_IS_OBJECT (acceleratable), FALSE);
+
+ was_handled = FALSE;
+ g_signal_emit (accel_group, signal_accel_activate, accel_quark,
+ acceleratable, accel_key, accel_mods, &was_handled);
+
+ return was_handled;
+}
+
+/**
+ * gtk_accel_groups_activate:
+ * @object: the #GObject, usually a #GtkWindow, on which
+ * to activate the accelerator
+ * @accel_key: accelerator keyval from a key event
+ * @accel_mods: keyboard state mask from a key event
+ *
+ * Finds the first accelerator in any #GtkAccelGroup attached
+ * to @object that matches @accel_key and @accel_mods, and
+ * activates that accelerator.
+ *
+ * Returns: %TRUE if an accelerator was activated and handled
+ * this keypress
+ */
+gboolean
+gtk_accel_groups_activate (GObject *object,
+ guint accel_key,
+ GdkModifierType accel_mods)
+{
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+ if (gtk_accelerator_valid (accel_key, accel_mods))
+ {
+ gchar *accel_name;
+ GQuark accel_quark;
+ GSList *slist;
+
+ accel_name = gtk_accelerator_name (accel_key, (accel_mods & gtk_accelerator_get_default_mod_mask ()));
+ accel_quark = g_quark_from_string (accel_name);
+ g_free (accel_name);
+
+ for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
+ if (gtk_accel_group_activate (slist->data, accel_quark, object, accel_key, accel_mods))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/**
* gtk_accelerator_valid:
* @keyval: a GDK keyval
@@ -205,6 +1088,20 @@ is_control (const gchar *string)
}
static inline gboolean
+is_release (const gchar *string)
+{
+ return ((string[0] == '<') &&
+ (string[1] == 'r' || string[1] == 'R') &&
+ (string[2] == 'e' || string[2] == 'E') &&
+ (string[3] == 'l' || string[3] == 'L') &&
+ (string[4] == 'e' || string[4] == 'E') &&
+ (string[5] == 'a' || string[5] == 'A') &&
+ (string[6] == 's' || string[6] == 'S') &&
+ (string[7] == 'e' || string[7] == 'E') &&
+ (string[8] == '>'));
+}
+
+static inline gboolean
is_meta (const gchar *string)
{
return ((string[0] == '<') &&
@@ -265,7 +1162,6 @@ is_keycode (const gchar *string)
/**
* gtk_accelerator_parse_with_keycode:
* @accelerator: string representing an accelerator
- * @display: (allow-none): the #GdkDisplay to look up @accelerator_codes in
* @accelerator_key: (out) (allow-none): return location for accelerator
* keyval, or %NULL
* @accelerator_codes: (out) (array zero-terminated=1) (transfer full) (allow-none):
@@ -286,12 +1182,9 @@ is_keycode (const gchar *string)
*
* If the parse fails, @accelerator_key, @accelerator_mods and
* @accelerator_codes will be set to 0 (zero).
- *
- * Returns: %TRUE if parsing succeeded
*/
-gboolean
+void
gtk_accelerator_parse_with_keycode (const gchar *accelerator,
- GdkDisplay *display,
guint *accelerator_key,
guint **accelerator_codes,
GdkModifierType *accelerator_mods)
@@ -307,8 +1200,7 @@ gtk_accelerator_parse_with_keycode (const gchar *accelerator,
*accelerator_mods = 0;
if (accelerator_codes)
*accelerator_codes = NULL;
-
- g_return_val_if_fail (accelerator != NULL, FALSE);
+ g_return_if_fail (accelerator != NULL);
error = FALSE;
keyval = 0;
@@ -318,7 +1210,13 @@ gtk_accelerator_parse_with_keycode (const gchar *accelerator,
{
if (*accelerator == '<')
{
- if (len >= 9 && is_primary (accelerator))
+ if (len >= 9 && is_release (accelerator))
+ {
+ accelerator += 9;
+ len -= 9;
+ mods |= GDK_RELEASE_MASK;
+ }
+ else if (len >= 9 && is_primary (accelerator))
{
accelerator += 9;
len -= 9;
@@ -455,7 +1353,7 @@ gtk_accelerator_parse_with_keycode (const gchar *accelerator,
if (keyval && accelerator_codes != NULL)
{
- GdkKeymap *keymap = gdk_display_get_keymap (display ? display : gdk_display_get_default ());
+ GdkKeymap *keymap = gdk_display_get_keymap (gdk_display_get_default ());
GdkKeymapKey *keys;
gint n_keys, i, j;
@@ -518,8 +1416,6 @@ out:
*accelerator_key = gdk_keyval_to_lower (keyval);
if (accelerator_mods)
*accelerator_mods = mods;
-
- return !error;
}
/**
@@ -543,12 +1439,12 @@ out:
* If the parse fails, @accelerator_key and @accelerator_mods will
* be set to 0 (zero).
*/
-gboolean
+void
gtk_accelerator_parse (const gchar *accelerator,
guint *accelerator_key,
GdkModifierType *accelerator_mods)
{
- return gtk_accelerator_parse_with_keycode (accelerator, NULL, accelerator_key, NULL, accelerator_mods);
+ gtk_accelerator_parse_with_keycode (accelerator, accelerator_key, NULL, accelerator_mods);
}
/**
@@ -609,6 +1505,7 @@ gchar*
gtk_accelerator_name (guint accelerator_key,
GdkModifierType accelerator_mods)
{
+ static const gchar text_release[] = "<Release>";
static const gchar text_primary[] = "<Primary>";
static const gchar text_shift[] = "<Shift>";
static const gchar text_control[] = "<Control>";
@@ -633,6 +1530,8 @@ gtk_accelerator_name (guint accelerator_key,
saved_mods = accelerator_mods;
l = 0;
+ if (accelerator_mods & GDK_RELEASE_MASK)
+ l += sizeof (text_release) - 1;
if (accelerator_mods & _gtk_get_primary_accel_mod ())
{
l += sizeof (text_primary) - 1;
@@ -665,6 +1564,11 @@ gtk_accelerator_name (guint accelerator_key,
accelerator_mods = saved_mods;
l = 0;
accelerator[l] = 0;
+ if (accelerator_mods & GDK_RELEASE_MASK)
+ {
+ strcpy (accelerator + l, text_release);
+ l += sizeof (text_release) - 1;
+ }
if (accelerator_mods & _gtk_get_primary_accel_mod ())
{
strcpy (accelerator + l, text_primary);
@@ -768,131 +1672,6 @@ gtk_accelerator_get_label_with_keycode (GdkDisplay *display,
return gtk_label;
}
-/* Underscores in key names are better displayed as spaces
- * E.g., Page_Up should be “Page Up”.
- *
- * Some keynames also have prefixes that are not suitable
- * for display, e.g XF86AudioMute, so strip those out, too.
- *
- * This function is only called on untranslated keynames,
- * so no need to be UTF-8 safe.
- */
-static void
-append_without_underscores (GString *s,
- const char *str)
-{
- const char *p;
-
- if (g_str_has_prefix (str, "XF86"))
- p = str + 4;
- else if (g_str_has_prefix (str, "ISO_"))
- p = str + 4;
- else
- p = str;
-
- for ( ; *p; p++)
- {
- if (*p == '_')
- g_string_append_c (s, ' ');
- else
- g_string_append_c (s, *p);
- }
-}
-
-/* On Mac, if the key has symbolic representation (e.g. arrow keys),
- * append it to gstring and return TRUE; otherwise return FALSE.
- * See http://docs.info.apple.com/article.html?path=Mac/10.5/en/cdb_symbs.html
- * for the list of special keys. */
-static gboolean
-append_keyval_symbol (guint accelerator_key,
- GString *gstring)
-{
-#ifdef GDK_WINDOWING_QUARTZ
- switch (accelerator_key)
- {
- case GDK_KEY_Return:
- /* U+21A9 LEFTWARDS ARROW WITH HOOK */
- g_string_append (gstring, "\xe2\x86\xa9");
- return TRUE;
-
- case GDK_KEY_ISO_Enter:
- /* U+2324 UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS */
- g_string_append (gstring, "\xe2\x8c\xa4");
- return TRUE;
-
- case GDK_KEY_Left:
- /* U+2190 LEFTWARDS ARROW */
- g_string_append (gstring, "\xe2\x86\x90");
- return TRUE;
-
- case GDK_KEY_Up:
- /* U+2191 UPWARDS ARROW */
- g_string_append (gstring, "\xe2\x86\x91");
- return TRUE;
-
- case GDK_KEY_Right:
- /* U+2192 RIGHTWARDS ARROW */
- g_string_append (gstring, "\xe2\x86\x92");
- return TRUE;
-
- case GDK_KEY_Down:
- /* U+2193 DOWNWARDS ARROW */
- g_string_append (gstring, "\xe2\x86\x93");
- return TRUE;
-
- case GDK_KEY_Page_Up:
- /* U+21DE UPWARDS ARROW WITH DOUBLE STROKE */
- g_string_append (gstring, "\xe2\x87\x9e");
- return TRUE;
-
- case GDK_KEY_Page_Down:
- /* U+21DF DOWNWARDS ARROW WITH DOUBLE STROKE */
- g_string_append (gstring, "\xe2\x87\x9f");
- return TRUE;
-
- case GDK_KEY_Home:
- /* U+2196 NORTH WEST ARROW */
- g_string_append (gstring, "\xe2\x86\x96");
- return TRUE;
-
- case GDK_KEY_End:
- /* U+2198 SOUTH EAST ARROW */
- g_string_append (gstring, "\xe2\x86\x98");
- return TRUE;
-
- case GDK_KEY_Escape:
- /* U+238B BROKEN CIRCLE WITH NORTHWEST ARROW */
- g_string_append (gstring, "\xe2\x8e\x8b");
- return TRUE;
-
- case GDK_KEY_BackSpace:
- /* U+232B ERASE TO THE LEFT */
- g_string_append (gstring, "\xe2\x8c\xab");
- return TRUE;
-
- case GDK_KEY_Delete:
- /* U+2326 ERASE TO THE RIGHT */
- g_string_append (gstring, "\xe2\x8c\xa6");
- return TRUE;
-
- default:
- return FALSE;
- }
-#else /* !GDK_WINDOWING_QUARTZ */
- return FALSE;
-#endif
-}
-
-static void
-append_separator (GString *string)
-{
-#ifndef GDK_WINDOWING_QUARTZ
- g_string_append (string, "+");
-#else
- /* no separator on quartz */
-#endif
-}
-
/**
* gtk_accelerator_get_label:
* @accelerator_key: accelerator keyval
@@ -907,202 +1686,16 @@ gchar*
gtk_accelerator_get_label (guint accelerator_key,
GdkModifierType accelerator_mods)
{
- GString *gstring;
-
- gstring = g_string_new (NULL);
-
- gtk_accelerator_print_label (gstring, accelerator_key, accelerator_mods);
-
- return g_string_free (gstring, FALSE);
-}
-
-void
-gtk_accelerator_print_label (GString *gstring,
- guint accelerator_key,
- GdkModifierType accelerator_mods)
-{
- gboolean seen_mod = FALSE;
- gunichar ch;
-
- if (accelerator_mods & GDK_SHIFT_MASK)
- {
-#ifndef GDK_WINDOWING_QUARTZ
- /* This is the text that should appear next to menu accelerators
- * that use the shift key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Shift"));
-#else
- /* U+21E7 UPWARDS WHITE ARROW */
- g_string_append (gstring, "\xe2\x87\xa7");
-#endif
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_CONTROL_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
- /* This is the text that should appear next to menu accelerators
- * that use the control key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Ctrl"));
-#else
- /* U+2303 UP ARROWHEAD */
- g_string_append (gstring, "\xe2\x8c\x83");
-#endif
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_MOD1_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
- /* This is the text that should appear next to menu accelerators
- * that use the alt key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Alt"));
-#else
- /* U+2325 OPTION KEY */
- g_string_append (gstring, "\xe2\x8c\xa5");
-#endif
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_MOD2_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
- g_string_append (gstring, "Mod2");
- seen_mod = TRUE;
- }
+ GtkAccelLabelClass *klass;
+ gchar *label;
- if (accelerator_mods & GDK_MOD3_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
+ klass = g_type_class_ref (GTK_TYPE_ACCEL_LABEL);
+ label = _gtk_accel_label_class_get_accelerator_label (klass,
+ accelerator_key,
+ accelerator_mods);
+ g_type_class_unref (klass); /* klass is kept alive since gtk uses static types */
- g_string_append (gstring, "Mod3");
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_MOD4_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
- g_string_append (gstring, "Mod4");
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_MOD5_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
- g_string_append (gstring, "Mod5");
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_SUPER_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
- /* This is the text that should appear next to menu accelerators
- * that use the super key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Super"));
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_HYPER_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
- /* This is the text that should appear next to menu accelerators
- * that use the hyper key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Hyper"));
- seen_mod = TRUE;
- }
-
- if (accelerator_mods & GDK_META_MASK)
- {
- if (seen_mod)
- append_separator (gstring);
-
-#ifndef GDK_WINDOWING_QUARTZ
- /* This is the text that should appear next to menu accelerators
- * that use the meta key. If the text on this key isn't typically
- * translated on keyboards used for your language, don't translate
- * this.
- */
- g_string_append (gstring, C_("keyboard label", "Meta"));
-#else
- /* Command key symbol U+2318 PLACE OF INTEREST SIGN */
- g_string_append (gstring, "\xe2\x8c\x98");
-#endif
- seen_mod = TRUE;
- }
-
- ch = gdk_keyval_to_unicode (accelerator_key);
- if (ch && (ch == ' ' || g_unichar_isgraph (ch)))
- {
- if (seen_mod)
- append_separator (gstring);
-
- switch (ch)
- {
- case ' ':
- g_string_append (gstring, C_("keyboard label", "Space"));
- break;
- case '\\':
- g_string_append (gstring, C_("keyboard label", "Backslash"));
- break;
- default:
- g_string_append_unichar (gstring, g_unichar_toupper (ch));
- break;
- }
- }
- else if (!append_keyval_symbol (accelerator_key, gstring))
- {
- const char *tmp;
-
- tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
- if (tmp != NULL)
- {
- if (seen_mod)
- append_separator (gstring);
-
- if (tmp[0] != 0 && tmp[1] == 0)
- g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
- else
- {
- const char *str;
- str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp);
- if (str == tmp)
- append_without_underscores (gstring, tmp);
- else
- g_string_append (gstring, str);
- }
- }
- }
+ return label;
}
/**
diff --git a/gtk/gtkaccelgroup.h b/gtk/gtkaccelgroup.h
index 69d0a3f227..bdb4d29888 100644
--- a/gtk/gtkaccelgroup.h
+++ b/gtk/gtkaccelgroup.h
@@ -36,17 +36,172 @@
G_BEGIN_DECLS
+/* --- type macros --- */
+#define GTK_TYPE_ACCEL_GROUP (gtk_accel_group_get_type ())
+#define GTK_ACCEL_GROUP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GTK_TYPE_ACCEL_GROUP, GtkAccelGroup))
+#define GTK_ACCEL_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
+#define GTK_IS_ACCEL_GROUP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GTK_TYPE_ACCEL_GROUP))
+#define GTK_IS_ACCEL_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ACCEL_GROUP))
+#define GTK_ACCEL_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_GROUP, GtkAccelGroupClass))
+
+
+/* --- accel flags --- */
+/**
+ * GtkAccelFlags:
+ * @GTK_ACCEL_VISIBLE: Accelerator is visible
+ * @GTK_ACCEL_LOCKED: Accelerator not removable
+ * @GTK_ACCEL_MASK: Mask
+ *
+ * Accelerator flags used with gtk_accel_group_connect().
+ */
+typedef enum
+{
+ GTK_ACCEL_VISIBLE = 1 << 0,
+ GTK_ACCEL_LOCKED = 1 << 1,
+ GTK_ACCEL_MASK = 0x07
+} GtkAccelFlags;
+
+
+/* --- typedefs & structures --- */
+typedef struct _GtkAccelGroup GtkAccelGroup;
+typedef struct _GtkAccelGroupClass GtkAccelGroupClass;
+typedef struct _GtkAccelGroupPrivate GtkAccelGroupPrivate;
+typedef struct _GtkAccelKey GtkAccelKey;
+typedef struct _GtkAccelGroupEntry GtkAccelGroupEntry;
+typedef gboolean (*GtkAccelGroupActivate) (GtkAccelGroup *accel_group,
+ GObject *acceleratable,
+ guint keyval,
+ GdkModifierType modifier);
+
+/**
+ * GtkAccelGroupFindFunc:
+ * @key:
+ * @closure:
+ * @data: (closure):
+ */
+typedef gboolean (*GtkAccelGroupFindFunc) (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data);
+
+/**
+ * GtkAccelGroup:
+ *
+ * An object representing and maintaining a group of accelerators.
+ */
+struct _GtkAccelGroup
+{
+ GObject parent;
+ GtkAccelGroupPrivate *priv;
+};
+
+/**
+ * GtkAccelGroupClass:
+ * @parent_class: The parent class.
+ * @accel_changed: Signal emitted when an entry is added to or removed
+ * from the accel group.
+ */
+struct _GtkAccelGroupClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+
+ void (*accel_changed) (GtkAccelGroup *accel_group,
+ guint keyval,
+ GdkModifierType modifier,
+ GClosure *accel_closure);
+
+ /*< private >*/
+
+ /* Padding for future expansion */
+ void (*_gtk_reserved1) (void);
+ void (*_gtk_reserved2) (void);
+ void (*_gtk_reserved3) (void);
+ void (*_gtk_reserved4) (void);
+};
+
+/**
+ * GtkAccelKey:
+ * @accel_key: The accelerator keyval
+ * @accel_mods:The accelerator modifiers
+ * @accel_flags: The accelerator flags
+ */
+struct _GtkAccelKey
+{
+ guint accel_key;
+ GdkModifierType accel_mods;
+ guint accel_flags : 16;
+};
+
+
+/* -- Accelerator Groups --- */
+GDK_AVAILABLE_IN_ALL
+GType gtk_accel_group_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroup* gtk_accel_group_new (void);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_group_get_is_locked (GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
+GdkModifierType
+ gtk_accel_group_get_modifier_mask (GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_group_lock (GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_group_unlock (GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_group_connect (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags,
+ GClosure *closure);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_group_connect_by_path (GtkAccelGroup *accel_group,
+ const gchar *accel_path,
+ GClosure *closure);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
+ GClosure *closure);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_group_activate (GtkAccelGroup *accel_group,
+ GQuark accel_quark,
+ GObject *acceleratable,
+ guint accel_key,
+ GdkModifierType accel_mods);
+
+
+/* --- GtkActivatable glue --- */
+void _gtk_accel_group_attach (GtkAccelGroup *accel_group,
+ GObject *object);
+void _gtk_accel_group_detach (GtkAccelGroup *accel_group,
+ GObject *object);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_groups_activate (GObject *object,
+ guint accel_key,
+ GdkModifierType accel_mods);
+GDK_AVAILABLE_IN_ALL
+GSList* gtk_accel_groups_from_object (GObject *object);
+GDK_AVAILABLE_IN_ALL
+GtkAccelKey* gtk_accel_group_find (GtkAccelGroup *accel_group,
+ GtkAccelGroupFindFunc find_func,
+ gpointer data);
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroup* gtk_accel_group_from_accel_closure (GClosure *closure);
+
+
/* --- Accelerators--- */
GDK_AVAILABLE_IN_ALL
gboolean gtk_accelerator_valid (guint keyval,
GdkModifierType modifiers) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
-gboolean gtk_accelerator_parse (const gchar *accelerator,
+void gtk_accelerator_parse (const gchar *accelerator,
guint *accelerator_key,
GdkModifierType *accelerator_mods);
GDK_AVAILABLE_IN_ALL
-gboolean gtk_accelerator_parse_with_keycode (const gchar *accelerator,
- GdkDisplay *display,
+void gtk_accelerator_parse_with_keycode (const gchar *accelerator,
guint *accelerator_key,
guint **accelerator_codes,
GdkModifierType *accelerator_mods);
@@ -72,6 +227,21 @@ GDK_AVAILABLE_IN_ALL
GdkModifierType
gtk_accelerator_get_default_mod_mask (void);
+GDK_AVAILABLE_IN_ALL
+GtkAccelGroupEntry* gtk_accel_group_query (GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ guint *n_entries);
+
+struct _GtkAccelGroupEntry
+{
+ GtkAccelKey key;
+ GClosure *closure;
+ GQuark accel_path_quark;
+};
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkAccelGroup, g_object_unref)
+
G_END_DECLS
#endif /* __GTK_ACCEL_GROUP_H__ */
diff --git a/gtk/gtkaccelgroupprivate.h b/gtk/gtkaccelgroupprivate.h
index c5b4daef55..15da43ae2b 100644
--- a/gtk/gtkaccelgroupprivate.h
+++ b/gtk/gtkaccelgroupprivate.h
@@ -25,9 +25,19 @@
G_BEGIN_DECLS
-void gtk_accelerator_print_label (GString *gstring,
- guint accelerator_key,
- GdkModifierType accelerator_mods);
+struct _GtkAccelGroupPrivate
+{
+ guint lock_count;
+ GdkModifierType modifier_mask;
+ GSList *acceleratables;
+ guint n_accels;
+ GtkAccelGroupEntry *priv_accels;
+};
+
+void _gtk_accel_group_reconnect (GtkAccelGroup *accel_group,
+ GQuark accel_path_quark);
+GSList* _gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group);
+
G_END_DECLS
#endif /* __GTK_ACCEL_GROUP_PRIVATE_H__ */
diff --git a/gtk/gtkaccellabel.c b/gtk/gtkaccellabel.c
index 4fabce26a5..75ee16bc8c 100644
--- a/gtk/gtkaccellabel.c
+++ b/gtk/gtkaccellabel.c
@@ -29,7 +29,9 @@
#include <string.h>
#include "gtklabel.h"
+#include "gtkaccellabel.h"
#include "gtkaccellabelprivate.h"
+#include "gtkaccelmap.h"
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkprivate.h"
@@ -68,6 +70,7 @@
* set (see #GtkAccelFlags).
* A #GtkAccelLabel can display multiple accelerators and even signal names,
* though it is almost always used to display just one accelerator key.
+ * ]|
*
* # CSS nodes
*
@@ -83,6 +86,8 @@
enum {
PROP_0,
+ PROP_ACCEL_CLOSURE,
+ PROP_ACCEL_WIDGET,
PROP_LABEL,
PROP_USE_UNDERLINE,
LAST_PROP
@@ -109,6 +114,10 @@ struct _GtkAccelLabelPrivate
GtkWidget *text_label;
GtkWidget *accel_label;
+ GtkWidget *accel_widget; /* done */
+ GClosure *accel_closure; /* has set function */
+ GtkAccelGroup *accel_group; /* set by set_accel_closure() */
+
guint accel_key; /* manual accel key specification if != 0 */
GdkModifierType accel_mods;
};
@@ -123,6 +132,7 @@ static void gtk_accel_label_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
+static void gtk_accel_label_destroy (GtkWidget *widget);
static void gtk_accel_label_finalize (GObject *object);
G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelLabel, gtk_accel_label, GTK_TYPE_WIDGET)
@@ -137,8 +147,56 @@ gtk_accel_label_class_init (GtkAccelLabelClass *class)
gobject_class->set_property = gtk_accel_label_set_property;
gobject_class->get_property = gtk_accel_label_get_property;
+ widget_class->destroy = gtk_accel_label_destroy;
+
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_ACCEL_LABEL);
+#ifndef GDK_WINDOWING_QUARTZ
+ /* This is the text that should appear next to menu accelerators
+ * that use the shift key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ class->mod_name_shift = g_strdup (C_("keyboard label", "Shift"));
+ /* This is the text that should appear next to menu accelerators
+ * that use the control key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ class->mod_name_control = g_strdup (C_("keyboard label", "Ctrl"));
+ /* This is the text that should appear next to menu accelerators
+ * that use the alt key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ class->mod_name_alt = g_strdup (C_("keyboard label", "Alt"));
+ class->mod_separator = g_strdup ("+");
+#else /* GDK_WINDOWING_QUARTZ */
+
+ /* U+21E7 UPWARDS WHITE ARROW */
+ class->mod_name_shift = g_strdup ("\xe2\x87\xa7");
+ /* U+2303 UP ARROWHEAD */
+ class->mod_name_control = g_strdup ("\xe2\x8c\x83");
+ /* U+2325 OPTION KEY */
+ class->mod_name_alt = g_strdup ("\xe2\x8c\xa5");
+ class->mod_separator = g_strdup ("");
+
+#endif /* GDK_WINDOWING_QUARTZ */
+
+ props[PROP_ACCEL_CLOSURE] =
+ g_param_spec_boxed ("accel-closure",
+ P_("Accelerator Closure"),
+ P_("The closure to be monitored for accelerator changes"),
+ G_TYPE_CLOSURE,
+ GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+ props[PROP_ACCEL_WIDGET] =
+ g_param_spec_object ("accel-widget",
+ P_("Accelerator Widget"),
+ P_("The widget to be monitored for accelerator changes"),
+ GTK_TYPE_WIDGET,
+ GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
props[PROP_LABEL] =
g_param_spec_string ("label",
P_("Label"),
@@ -171,6 +229,12 @@ gtk_accel_label_set_property (GObject *object,
switch (prop_id)
{
+ case PROP_ACCEL_CLOSURE:
+ gtk_accel_label_set_accel_closure (accel_label, g_value_get_boxed (value));
+ break;
+ case PROP_ACCEL_WIDGET:
+ gtk_accel_label_set_accel_widget (accel_label, g_value_get_object (value));
+ break;
case PROP_LABEL:
gtk_accel_label_set_label (accel_label, g_value_get_string (value));
break;
@@ -190,9 +254,16 @@ gtk_accel_label_get_property (GObject *object,
GParamSpec *pspec)
{
GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
switch (prop_id)
{
+ case PROP_ACCEL_CLOSURE:
+ g_value_set_boxed (value, priv->accel_closure);
+ break;
+ case PROP_ACCEL_WIDGET:
+ g_value_set_object (value, priv->accel_widget);
+ break;
case PROP_LABEL:
g_value_set_string (value, gtk_accel_label_get_label (accel_label));
break;
@@ -210,6 +281,10 @@ gtk_accel_label_init (GtkAccelLabel *accel_label)
{
GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+ priv->accel_widget = NULL;
+ priv->accel_closure = NULL;
+ priv->accel_group = NULL;
+
priv->text_label = gtk_label_new ("");
gtk_widget_set_hexpand (priv->text_label, TRUE);
gtk_label_set_xalign (GTK_LABEL (priv->text_label), 0.0f);
@@ -243,6 +318,17 @@ gtk_accel_label_new (const gchar *string)
}
static void
+gtk_accel_label_destroy (GtkWidget *widget)
+{
+ GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (widget);
+
+ gtk_accel_label_set_accel_widget (accel_label, NULL);
+ gtk_accel_label_set_accel_closure (accel_label, NULL);
+
+ GTK_WIDGET_CLASS (gtk_accel_label_parent_class)->destroy (widget);
+}
+
+static void
gtk_accel_label_finalize (GObject *object)
{
GtkAccelLabel *accel_label = GTK_ACCEL_LABEL (object);
@@ -255,6 +341,26 @@ gtk_accel_label_finalize (GObject *object)
}
/**
+ * gtk_accel_label_get_accel_widget:
+ * @accel_label: a #GtkAccelLabel
+ *
+ * Fetches the widget monitored by this accelerator label. See
+ * gtk_accel_label_set_accel_widget().
+ *
+ * Returns: (nullable) (transfer none): the widget monitored by @accel_label,
+ * or %NULL if it is not monitoring a widget.
+ **/
+GtkWidget *
+gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
+
+ return priv->accel_widget;
+}
+
+/**
* gtk_accel_label_get_accel_width:
* @accel_label: a #GtkAccelLabel.
*
@@ -278,6 +384,463 @@ gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label)
return min;
}
+static void
+refetch_widget_accel_closure (GtkAccelLabel *accel_label)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+ GClosure *closure = NULL;
+ GList *clist, *list;
+
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+ g_return_if_fail (GTK_IS_WIDGET (priv->accel_widget));
+
+ clist = gtk_widget_list_accel_closures (priv->accel_widget);
+ for (list = clist; list; list = list->next)
+ {
+ /* we just take the first closure used */
+ closure = list->data;
+ break;
+ }
+
+ g_list_free (clist);
+ gtk_accel_label_set_accel_closure (accel_label, closure);
+}
+
+static void
+accel_widget_weak_ref_cb (GtkAccelLabel *accel_label,
+ GtkWidget *old_accel_widget)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+ g_return_if_fail (GTK_IS_WIDGET (priv->accel_widget));
+
+ g_signal_handlers_disconnect_by_func (priv->accel_widget,
+ refetch_widget_accel_closure,
+ accel_label);
+ priv->accel_widget = NULL;
+ g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_WIDGET]);
+}
+
+/**
+ * gtk_accel_label_set_accel_widget:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_widget: (nullable): the widget to be monitored, or %NULL
+ *
+ * Sets the widget to be monitored by this accelerator label. Passing %NULL for
+ * @accel_widget will dissociate @accel_label from its current widget, if any.
+ */
+void
+gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+ GtkWidget *accel_widget)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+
+ if (accel_widget)
+ g_return_if_fail (GTK_IS_WIDGET (accel_widget));
+
+ if (accel_widget != priv->accel_widget)
+ {
+ if (priv->accel_widget)
+ {
+ gtk_accel_label_set_accel_closure (accel_label, NULL);
+ g_signal_handlers_disconnect_by_func (priv->accel_widget,
+ refetch_widget_accel_closure,
+ accel_label);
+ g_object_weak_unref (G_OBJECT (priv->accel_widget),
+ (GWeakNotify) accel_widget_weak_ref_cb, accel_label);
+ }
+
+ priv->accel_widget = accel_widget;
+
+ if (priv->accel_widget)
+ {
+ g_object_weak_ref (G_OBJECT (priv->accel_widget),
+ (GWeakNotify) accel_widget_weak_ref_cb, accel_label);
+ g_signal_connect_object (priv->accel_widget, "accel-closures-changed",
+ G_CALLBACK (refetch_widget_accel_closure),
+ accel_label, G_CONNECT_SWAPPED);
+ refetch_widget_accel_closure (accel_label);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_WIDGET]);
+ }
+}
+
+static void
+gtk_accel_label_reset (GtkAccelLabel *accel_label)
+{
+ gtk_accel_label_refetch (accel_label);
+}
+
+static void
+check_accel_changed (GtkAccelGroup *accel_group,
+ guint keyval,
+ GdkModifierType modifier,
+ GClosure *accel_closure,
+ GtkAccelLabel *accel_label)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ if (accel_closure == priv->accel_closure)
+ gtk_accel_label_reset (accel_label);
+}
+
+/**
+ * gtk_accel_label_set_accel_closure:
+ * @accel_label: a #GtkAccelLabel
+ * @accel_closure: (nullable): the closure to monitor for accelerator changes,
+ * or %NULL
+ *
+ * Sets the closure to be monitored by this accelerator label. The closure
+ * must be connected to an accelerator group; see gtk_accel_group_connect().
+ * Passing %NULL for @accel_closure will dissociate @accel_label from its
+ * current closure, if any.
+ **/
+void
+gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+ GClosure *accel_closure)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ g_return_if_fail (GTK_IS_ACCEL_LABEL (accel_label));
+
+ if (accel_closure)
+ g_return_if_fail (gtk_accel_group_from_accel_closure (accel_closure) != NULL);
+
+ if (accel_closure != priv->accel_closure)
+ {
+ if (priv->accel_closure)
+ {
+ g_signal_handlers_disconnect_by_func (priv->accel_group,
+ check_accel_changed,
+ accel_label);
+ priv->accel_group = NULL;
+ g_closure_unref (priv->accel_closure);
+ }
+
+ priv->accel_closure = accel_closure;
+
+ if (priv->accel_closure)
+ {
+ g_closure_ref (priv->accel_closure);
+ priv->accel_group = gtk_accel_group_from_accel_closure (accel_closure);
+ g_signal_connect_object (priv->accel_group, "accel-changed", G_CALLBACK (check_accel_changed),
+ accel_label, 0);
+ }
+
+ gtk_accel_label_reset (accel_label);
+ g_object_notify_by_pspec (G_OBJECT (accel_label), props[PROP_ACCEL_CLOSURE]);
+ }
+}
+
+/**
+ * gtk_accel_label_get_accel_closure:
+ * @accel_label: a #GtkAccelLabel
+ *
+ * Fetches the closure monitored by this accelerator label. See
+ * gtk_accel_label_set_accel_closure().
+ *
+ * Returns: (nullable) (transfer none): the closure monitored by @accel_label,
+ * or %NULL if it is not monitoring a closure.
+ */
+GClosure *
+gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label)
+{
+ GtkAccelLabelPrivate *priv = gtk_accel_label_get_instance_private (accel_label);
+
+ g_return_val_if_fail (GTK_IS_ACCEL_LABEL (accel_label), NULL);
+
+ return priv->accel_closure;
+}
+
+static gboolean
+find_accel (GtkAccelKey *key,
+ GClosure *closure,
+ gpointer data)
+{
+ return data == (gpointer) closure;
+}
+
+/* Underscores in key names are better displayed as spaces
+ * E.g., Page_Up should be “Page Up”.
+ *
+ * Some keynames also have prefixes that are not suitable
+ * for display, e.g XF86AudioMute, so strip those out, too.
+ *
+ * This function is only called on untranslated keynames,
+ * so no need to be UTF-8 safe.
+ */
+static void
+append_without_underscores (GString *s,
+ const char *str)
+{
+ const char *p;
+
+ if (g_str_has_prefix (str, "XF86"))
+ p = str + 4;
+ else if (g_str_has_prefix (str, "ISO_"))
+ p = str + 4;
+ else
+ p = str;
+
+ for ( ; *p; p++)
+ {
+ if (*p == '_')
+ g_string_append_c (s, ' ');
+ else
+ g_string_append_c (s, *p);
+ }
+}
+
+/* On Mac, if the key has symbolic representation (e.g. arrow keys),
+ * append it to gstring and return TRUE; otherwise return FALSE.
+ * See http://docs.info.apple.com/article.html?path=Mac/10.5/en/cdb_symbs.html
+ * for the list of special keys. */
+static gboolean
+append_keyval_symbol (guint accelerator_key,
+ GString *gstring)
+{
+#ifdef GDK_WINDOWING_QUARTZ
+ switch (accelerator_key)
+ {
+ case GDK_KEY_Return:
+ /* U+21A9 LEFTWARDS ARROW WITH HOOK */
+ g_string_append (gstring, "\xe2\x86\xa9");
+ return TRUE;
+
+ case GDK_KEY_ISO_Enter:
+ /* U+2324 UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS */
+ g_string_append (gstring, "\xe2\x8c\xa4");
+ return TRUE;
+
+ case GDK_KEY_Left:
+ /* U+2190 LEFTWARDS ARROW */
+ g_string_append (gstring, "\xe2\x86\x90");
+ return TRUE;
+
+ case GDK_KEY_Up:
+ /* U+2191 UPWARDS ARROW */
+ g_string_append (gstring, "\xe2\x86\x91");
+ return TRUE;
+
+ case GDK_KEY_Right:
+ /* U+2192 RIGHTWARDS ARROW */
+ g_string_append (gstring, "\xe2\x86\x92");
+ return TRUE;
+
+ case GDK_KEY_Down:
+ /* U+2193 DOWNWARDS ARROW */
+ g_string_append (gstring, "\xe2\x86\x93");
+ return TRUE;
+
+ case GDK_KEY_Page_Up:
+ /* U+21DE UPWARDS ARROW WITH DOUBLE STROKE */
+ g_string_append (gstring, "\xe2\x87\x9e");
+ return TRUE;
+
+ case GDK_KEY_Page_Down:
+ /* U+21DF DOWNWARDS ARROW WITH DOUBLE STROKE */
+ g_string_append (gstring, "\xe2\x87\x9f");
+ return TRUE;
+
+ case GDK_KEY_Home:
+ /* U+2196 NORTH WEST ARROW */
+ g_string_append (gstring, "\xe2\x86\x96");
+ return TRUE;
+
+ case GDK_KEY_End:
+ /* U+2198 SOUTH EAST ARROW */
+ g_string_append (gstring, "\xe2\x86\x98");
+ return TRUE;
+
+ case GDK_KEY_Escape:
+ /* U+238B BROKEN CIRCLE WITH NORTHWEST ARROW */
+ g_string_append (gstring, "\xe2\x8e\x8b");
+ return TRUE;
+
+ case GDK_KEY_BackSpace:
+ /* U+232B ERASE TO THE LEFT */
+ g_string_append (gstring, "\xe2\x8c\xab");
+ return TRUE;
+
+ case GDK_KEY_Delete:
+ /* U+2326 ERASE TO THE RIGHT */
+ g_string_append (gstring, "\xe2\x8c\xa6");
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+#else /* !GDK_WINDOWING_QUARTZ */
+ return FALSE;
+#endif
+}
+
+gchar *
+_gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,
+ guint accelerator_key,
+ GdkModifierType accelerator_mods)
+{
+ GString *gstring;
+ gboolean seen_mod = FALSE;
+ gunichar ch;
+
+ gstring = g_string_sized_new (10); /* ~len('backspace') */
+
+ if (accelerator_mods & GDK_SHIFT_MASK)
+ {
+ g_string_append (gstring, klass->mod_name_shift);
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_CONTROL_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+ g_string_append (gstring, klass->mod_name_control);
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_MOD1_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+ g_string_append (gstring, klass->mod_name_alt);
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_MOD2_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ g_string_append (gstring, "Mod2");
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_MOD3_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ g_string_append (gstring, "Mod3");
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_MOD4_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ g_string_append (gstring, "Mod4");
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_MOD5_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ g_string_append (gstring, "Mod5");
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_SUPER_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ /* This is the text that should appear next to menu accelerators
+ * that use the super key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ g_string_append (gstring, C_("keyboard label", "Super"));
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_HYPER_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ /* This is the text that should appear next to menu accelerators
+ * that use the hyper key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ g_string_append (gstring, C_("keyboard label", "Hyper"));
+ seen_mod = TRUE;
+ }
+
+ if (accelerator_mods & GDK_META_MASK)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+#ifndef GDK_WINDOWING_QUARTZ
+ /* This is the text that should appear next to menu accelerators
+ * that use the meta key. If the text on this key isn't typically
+ * translated on keyboards used for your language, don't translate
+ * this.
+ */
+ g_string_append (gstring, C_("keyboard label", "Meta"));
+#else
+ /* Command key symbol U+2318 PLACE OF INTEREST SIGN */
+ g_string_append (gstring, "\xe2\x8c\x98");
+#endif
+ seen_mod = TRUE;
+ }
+
+ ch = gdk_keyval_to_unicode (accelerator_key);
+ if (ch && (ch == ' ' || g_unichar_isgraph (ch)))
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ switch (ch)
+ {
+ case ' ':
+ g_string_append (gstring, C_("keyboard label", "Space"));
+ break;
+ case '\\':
+ g_string_append (gstring, C_("keyboard label", "Backslash"));
+ break;
+ default:
+ g_string_append_unichar (gstring, g_unichar_toupper (ch));
+ break;
+ }
+ }
+ else if (!append_keyval_symbol (accelerator_key, gstring))
+ {
+ const char *tmp;
+
+ tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+ if (tmp != NULL)
+ {
+ if (seen_mod)
+ g_string_append (gstring, klass->mod_separator);
+
+ if (tmp[0] != 0 && tmp[1] == 0)
+ g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
+ else
+ {
+ const gchar *str;
+ str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp);
+ if (str == tmp)
+ append_without_underscores (gstring, tmp);
+ else
+ g_string_append (gstring, str);
+ }
+ }
+ }
+
+ return g_string_free (gstring, FALSE);
+}
+
/**
* gtk_accel_label_refetch:
* @accel_label: a #GtkAccelLabel.
@@ -301,7 +864,7 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
"gtk-enable-accels", &enable_accels,
NULL);
- if (enable_accels && priv->accel_key)
+ if (enable_accels && (priv->accel_closure || priv->accel_key))
{
gboolean have_accel = FALSE;
guint accel_key;
@@ -315,9 +878,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
have_accel = TRUE;
}
+ /* If we don't have a hardcoded value, check the accel group */
+ if (!have_accel)
+ {
+ GtkAccelKey *key;
+
+ key = gtk_accel_group_find (priv->accel_group, find_accel, priv->accel_closure);
+
+ if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
+ {
+ accel_key = key->accel_key;
+ accel_mods = key->accel_mods;
+ have_accel = TRUE;
+ }
+ }
+
/* If we found a key using either method, set it */
if (have_accel)
- accel_string = gtk_accelerator_get_label (accel_key, accel_mods);
+ {
+ GtkAccelLabelClass *klass;
+
+ klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
+ accel_string = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
+ }
+
else
/* Otherwise we have a closure with no key. Show "-/-". */
accel_string = g_strdup ("-/-");
@@ -359,7 +943,7 @@ gtk_accel_label_set_accel (GtkAccelLabel *accel_label,
priv->accel_key = accelerator_key;
priv->accel_mods = accelerator_mods;
- gtk_accel_label_refetch (accel_label);
+ gtk_accel_label_reset (accel_label);
}
/**
diff --git a/gtk/gtkaccellabel.h b/gtk/gtkaccellabel.h
index 7177b79ceb..a5e63559f1 100644
--- a/gtk/gtkaccellabel.h
+++ b/gtk/gtkaccellabel.h
@@ -46,8 +46,18 @@ GType gtk_accel_label_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
GtkWidget *gtk_accel_label_new (const gchar *string);
GDK_AVAILABLE_IN_ALL
+GtkWidget *gtk_accel_label_get_accel_widget (GtkAccelLabel *accel_label);
+GDK_AVAILABLE_IN_ALL
guint gtk_accel_label_get_accel_width (GtkAccelLabel *accel_label);
GDK_AVAILABLE_IN_ALL
+void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
+ GtkWidget *accel_widget);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
+ GClosure *accel_closure);
+GDK_AVAILABLE_IN_ALL
+GClosure * gtk_accel_label_get_accel_closure (GtkAccelLabel *accel_label);
+GDK_AVAILABLE_IN_ALL
gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label);
GDK_AVAILABLE_IN_ALL
void gtk_accel_label_set_accel (GtkAccelLabel *accel_label,
diff --git a/gtk/gtkaccelmap.c b/gtk/gtkaccelmap.c
new file mode 100644
index 0000000000..2c24d78fa8
--- /dev/null
+++ b/gtk/gtkaccelmap.c
@@ -0,0 +1,1086 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkaccelmapprivate.h"
+#include "gtkaccelgroupprivate.h"
+
+#include "gtkmarshalers.h"
+#include "gtkwindowprivate.h"
+#include "gtkintl.h"
+
+#include <glib/gstdio.h>
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef G_OS_WIN32
+#include <io.h>
+#endif
+
+
+/**
+ * SECTION:gtkaccelmap
+ * @Short_description: Loadable keyboard accelerator specifications
+ * @Title: Accelerator Maps
+ * @See_also: #GtkAccelGroup, #GtkAccelKey, gtk_widget_set_accel_path(), gtk_menu_item_set_accel_path()
+ *
+ * Accelerator maps are used to define runtime configurable accelerators.
+ * Functions for manipulating them are are usually used by higher level
+ * convenience mechanisms and are thus considered
+ * “low-level”. You’ll want to use them if you’re manually creating menus that
+ * should have user-configurable accelerators.
+ *
+ * An accelerator is uniquely defined by:
+ * - accelerator path
+ * - accelerator key
+ * - accelerator modifiers
+ *
+ * The accelerator path must consist of
+ * “<WINDOWTYPE>/Category1/Category2/.../Action”, where WINDOWTYPE
+ * should be a unique application-specific identifier that corresponds
+ * to the kind of window the accelerator is being used in, e.g.
+ * “Gimp-Image”, “Abiword-Document” or “Gnumeric-Settings”.
+ * The “Category1/.../Action” portion is most appropriately chosen by
+ * the action the accelerator triggers, i.e. for accelerators on menu
+ * items, choose the item’s menu path, e.g. “File/Save As”,
+ * “Image/View/Zoom” or “Edit/Select All”. So a full valid accelerator
+ * path may look like: “<Gimp-Toolbox>/File/Dialogs/Tool Options...”.
+ *
+ * All accelerators are stored inside one global #GtkAccelMap that can
+ * be obtained using gtk_accel_map_get(). See
+ * [Monitoring changes][monitoring-changes] for additional
+ * details.
+ *
+ * # Manipulating accelerators
+ *
+ * New accelerators can be added using gtk_accel_map_add_entry().
+ * To search for specific accelerator, use gtk_accel_map_lookup_entry().
+ * Modifications of existing accelerators should be done using
+ * gtk_accel_map_change_entry().
+ *
+ * In order to avoid having some accelerators changed, they can be
+ * locked using gtk_accel_map_lock_path(). Unlocking is done using
+ * gtk_accel_map_unlock_path().
+ *
+ * # Saving and loading accelerator maps
+ *
+ * Accelerator maps can be saved to and loaded from some external
+ * resource. For simple saving and loading from file,
+ * gtk_accel_map_save() and gtk_accel_map_load() are provided.
+ * Saving and loading can also be done by providing file descriptor
+ * to gtk_accel_map_save_fd() and gtk_accel_map_load_fd().
+ *
+ * # Monitoring changes
+ *
+ * #GtkAccelMap object is only useful for monitoring changes of
+ * accelerators. By connecting to #GtkAccelMap::changed signal, one
+ * can monitor changes of all accelerators. It is also possible to
+ * monitor only single accelerator path by using it as a detail of
+ * the #GtkAccelMap::changed signal.
+ */
+
+
+/* --- structures --- */
+struct _GtkAccelMap
+{
+ GObject parent_instance;
+};
+
+struct _GtkAccelMapClass
+{
+ GObjectClass parent_class;
+};
+
+typedef struct {
+ const gchar *accel_path;
+ guint accel_key;
+ guint accel_mods;
+ guint std_accel_key;
+ guint std_accel_mods;
+ guint changed : 1;
+ guint lock_count : 15;
+ GSList *groups;
+} AccelEntry;
+
+/* --- signals --- */
+enum {
+ CHANGED,
+ LAST_SIGNAL
+};
+
+/* --- variables --- */
+
+static GHashTable *accel_entry_ht = NULL; /* accel_path -> AccelEntry */
+static GSList *accel_filters = NULL;
+static gulong accel_map_signals[LAST_SIGNAL] = { 0, };
+
+/* --- prototypes --- */
+static void do_accel_map_changed (AccelEntry *entry);
+
+/* --- functions --- */
+static guint
+accel_entry_hash (gconstpointer key)
+{
+ const AccelEntry *entry = key;
+
+ return g_str_hash (entry->accel_path);
+}
+
+static gboolean
+accel_entry_equal (gconstpointer key1,
+ gconstpointer key2)
+{
+ const AccelEntry *entry1 = key1;
+ const AccelEntry *entry2 = key2;
+
+ return g_str_equal (entry1->accel_path, entry2->accel_path);
+}
+
+static int
+accel_entry_compare (gconstpointer a,
+ gconstpointer b)
+{
+ const AccelEntry *entry1 = a;
+ const AccelEntry *entry2 = b;
+
+ return strcmp (entry1->accel_path, entry2->accel_path);
+}
+
+static inline AccelEntry*
+accel_path_lookup (const gchar *accel_path)
+{
+ AccelEntry ekey;
+
+ ekey.accel_path = accel_path;
+
+ /* safety NULL check for return_if_fail()s */
+ return accel_path ? g_hash_table_lookup (accel_entry_ht, &ekey) : NULL;
+}
+
+void
+_gtk_accel_map_init (void)
+{
+ if (accel_entry_ht == NULL)
+ accel_entry_ht = g_hash_table_new (accel_entry_hash, accel_entry_equal);
+}
+
+gboolean
+_gtk_accel_path_is_valid (const gchar *accel_path)
+{
+ gchar *p;
+
+ if (!accel_path || accel_path[0] != '<' ||
+ accel_path[1] == '<' || accel_path[1] == '>' || !accel_path[1])
+ return FALSE;
+ p = strchr (accel_path, '>');
+ if (!p || (p[1] != 0 && p[1] != '/'))
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * gtk_accel_map_add_entry:
+ * @accel_path: valid accelerator path
+ * @accel_key: the accelerator key
+ * @accel_mods: the accelerator modifiers
+ *
+ * Registers a new accelerator with the global accelerator map.
+ * This function should only be called once per @accel_path
+ * with the canonical @accel_key and @accel_mods for this path.
+ * To change the accelerator during runtime programatically, use
+ * gtk_accel_map_change_entry().
+ *
+ * Set @accel_key and @accel_mods to 0 to request a removal of
+ * the accelerator.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with
+ * g_intern_static_string().
+ */
+void
+gtk_accel_map_add_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods)
+{
+ AccelEntry *entry;
+
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+ if (!accel_key)
+ accel_mods = 0;
+ else
+ accel_mods &= gtk_accelerator_get_default_mod_mask ();
+
+ entry = accel_path_lookup (accel_path);
+ if (entry)
+ {
+ if (!entry->std_accel_key && !entry->std_accel_mods &&
+ (accel_key || accel_mods))
+ {
+ entry->std_accel_key = accel_key;
+ entry->std_accel_mods = accel_mods;
+ if (!entry->changed)
+ gtk_accel_map_change_entry (entry->accel_path, accel_key, accel_mods, TRUE);
+ }
+ }
+ else
+ {
+ entry = g_slice_new0 (AccelEntry);
+ entry->accel_path = g_intern_string (accel_path);
+ entry->std_accel_key = accel_key;
+ entry->std_accel_mods = accel_mods;
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = FALSE;
+ entry->lock_count = 0;
+ g_hash_table_insert (accel_entry_ht, entry, entry);
+
+ do_accel_map_changed (entry);
+ }
+}
+
+/**
+ * gtk_accel_map_lookup_entry:
+ * @accel_path: a valid accelerator path
+ * @key: (allow-none) (out): the accelerator key to be filled in (optional)
+ *
+ * Looks up the accelerator entry for @accel_path and fills in @key.
+ *
+ * Returns: %TRUE if @accel_path is known, %FALSE otherwise
+ */
+gboolean
+gtk_accel_map_lookup_entry (const gchar *accel_path,
+ GtkAccelKey *key)
+{
+ AccelEntry *entry;
+
+ g_return_val_if_fail (_gtk_accel_path_is_valid (accel_path), FALSE);
+
+ entry = accel_path_lookup (accel_path);
+ if (entry && key)
+ {
+ key->accel_key = entry->accel_key;
+ key->accel_mods = entry->accel_mods;
+ key->accel_flags = 0;
+ }
+
+ return entry ? TRUE : FALSE;
+}
+
+static void
+hash2slist_foreach (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GSList **slist_p = user_data;
+
+ *slist_p = g_slist_prepend (*slist_p, value);
+}
+
+static GSList*
+g_hash_table_slist_values (GHashTable *hash_table)
+{
+ GSList *slist = NULL;
+
+ g_return_val_if_fail (hash_table != NULL, NULL);
+
+ g_hash_table_foreach (hash_table, hash2slist_foreach, &slist);
+
+ return slist;
+}
+
+/* if simulate==TRUE, return whether accel_path can be changed to
+ * accel_key && accel_mods. otherwise, return whether accel_path
+ * was actually changed.
+ */
+static gboolean
+internal_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace,
+ gboolean simulate)
+{
+ GSList *node, *slist, *win_list, *group_list, *replace_list = NULL;
+ GHashTable *group_hm, *window_hm;
+ gboolean change_accel, removable, can_change = TRUE, seen_accel = FALSE;
+ GQuark entry_quark;
+ AccelEntry *entry = accel_path_lookup (accel_path);
+
+ /* not much todo if there's no entry yet */
+ if (!entry)
+ {
+ if (!simulate)
+ {
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ entry = accel_path_lookup (accel_path);
+ g_assert (entry);
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+
+ do_accel_map_changed (entry);
+ }
+ return TRUE;
+ }
+
+ /* if there's nothing to change, not much todo either */
+ if (entry->accel_key == accel_key && entry->accel_mods == accel_mods)
+ {
+ if (!simulate)
+ entry->changed = TRUE;
+ return simulate ? TRUE : FALSE;
+ }
+
+ /* The no-change case has already been handled, so
+ * simulate doesn't make a difference here.
+ */
+ if (entry->lock_count > 0)
+ return FALSE;
+
+ /* nobody's interested, easy going */
+ if (!entry->groups)
+ {
+ if (!simulate)
+ {
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+
+ do_accel_map_changed (entry);
+ }
+ return TRUE;
+ }
+
+ /* 1) fetch all accel groups affected by this entry */
+ entry_quark = g_quark_try_string (entry->accel_path);
+ group_hm = g_hash_table_new (NULL, NULL);
+ window_hm = g_hash_table_new (NULL, NULL);
+ for (slist = entry->groups; slist; slist = slist->next)
+ g_hash_table_insert (group_hm, slist->data, slist->data);
+
+ /* 2) collect acceleratables affected */
+ group_list = g_hash_table_slist_values (group_hm);
+ for (slist = group_list; slist; slist = slist->next)
+ {
+ GtkAccelGroup *group = slist->data;
+
+ for (node = _gtk_accel_group_get_accelerables (group); node; node = node->next)
+ g_hash_table_insert (window_hm, node->data, node->data);
+ }
+ g_slist_free (group_list);
+
+ /* 3) include all accel groups used by acceleratables */
+ win_list = g_hash_table_slist_values (window_hm);
+ g_hash_table_destroy (window_hm);
+ for (slist = win_list; slist; slist = slist->next)
+ for (node = gtk_accel_groups_from_object (slist->data); node; node = node->next)
+ g_hash_table_insert (group_hm, node->data, node->data);
+ group_list = g_hash_table_slist_values (group_hm);
+ g_hash_table_destroy (group_hm);
+
+ /* 4) walk the acceleratables and figure whether they occupy accel_key&accel_mods */
+ if (accel_key)
+ for (slist = win_list; slist; slist = slist->next)
+ if (GTK_IS_WINDOW (slist->data)) /* bad kludge in lack of a GtkAcceleratable */
+ if (_gtk_window_query_nonaccels (slist->data, accel_key, accel_mods))
+ {
+ seen_accel = TRUE;
+ break;
+ }
+ removable = !seen_accel;
+
+ /* 5) walk all accel groups and search for locks */
+ if (removable)
+ for (slist = group_list; slist; slist = slist->next)
+ {
+ GtkAccelGroup *group = slist->data;
+ GtkAccelGroupEntry *ag_entry;
+ guint i, n;
+
+ n = 0;
+ ag_entry = entry->accel_key ? gtk_accel_group_query (group, entry->accel_key, entry->accel_mods, &n) : NULL;
+ for (i = 0; i < n; i++)
+ if (ag_entry[i].accel_path_quark == entry_quark)
+ {
+ can_change = !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+ if (!can_change)
+ goto break_loop_step5;
+ }
+
+ n = 0;
+ ag_entry = accel_key ? gtk_accel_group_query (group, accel_key, accel_mods, &n) : NULL;
+ for (i = 0; i < n; i++)
+ {
+ seen_accel = TRUE;
+ removable = !gtk_accel_group_get_is_locked (group) && !(ag_entry[i].key.accel_flags & GTK_ACCEL_LOCKED);
+ if (!removable)
+ goto break_loop_step5;
+ if (ag_entry[i].accel_path_quark)
+ replace_list = g_slist_prepend (replace_list, GUINT_TO_POINTER (ag_entry[i].accel_path_quark));
+ }
+ }
+ break_loop_step5:
+
+ /* 6) check whether we can remove existing accelerators */
+ if (removable && can_change)
+ for (slist = replace_list; slist; slist = slist->next)
+ if (!internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, TRUE))
+ {
+ removable = FALSE;
+ break;
+ }
+
+ /* 7) check conditions and proceed if possible */
+ change_accel = can_change && (!seen_accel || (removable && replace));
+
+ if (change_accel && !simulate)
+ {
+ /* ref accel groups */
+ for (slist = group_list; slist; slist = slist->next)
+ g_object_ref (slist->data);
+
+ /* 8) remove existing accelerators */
+ for (slist = replace_list; slist; slist = slist->next)
+ internal_change_entry (g_quark_to_string (GPOINTER_TO_UINT (slist->data)), 0, 0, FALSE, FALSE);
+
+ /* 9) install new accelerator */
+ entry->accel_key = accel_key;
+ entry->accel_mods = accel_mods;
+ entry->changed = TRUE;
+
+ for (slist = group_list; slist; slist = slist->next)
+ _gtk_accel_group_reconnect (slist->data, g_quark_from_string (entry->accel_path));
+
+ /* unref accel groups */
+ for (slist = group_list; slist; slist = slist->next)
+ g_object_unref (slist->data);
+
+ do_accel_map_changed (entry);
+ }
+ g_slist_free (replace_list);
+ g_slist_free (group_list);
+ g_slist_free (win_list);
+
+ return change_accel;
+}
+
+/**
+ * gtk_accel_map_change_entry:
+ * @accel_path: a valid accelerator path
+ * @accel_key: the new accelerator key
+ * @accel_mods: the new accelerator modifiers
+ * @replace: %TRUE if other accelerators may be deleted upon conflicts
+ *
+ * Changes the @accel_key and @accel_mods currently associated with @accel_path.
+ * Due to conflicts with other accelerators, a change may not always be possible,
+ * @replace indicates whether other accelerators may be deleted to resolve such
+ * conflicts. A change will only occur if all conflicts could be resolved (which
+ * might not be the case if conflicting accelerators are locked). Successful
+ * changes are indicated by a %TRUE return value.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with
+ * g_intern_static_string().
+ *
+ * Returns: %TRUE if the accelerator could be changed, %FALSE otherwise
+ */
+gboolean
+gtk_accel_map_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace)
+{
+ g_return_val_if_fail (_gtk_accel_path_is_valid (accel_path), FALSE);
+
+ return internal_change_entry (accel_path, accel_key, accel_key ? accel_mods : 0, replace, FALSE);
+}
+
+static guint
+accel_map_parse_accel_path (GScanner *scanner)
+{
+ guint accel_key = 0;
+ GdkModifierType accel_mods = 0;
+ gchar *path, *accel;
+
+ /* parse accel path */
+ g_scanner_get_next_token (scanner);
+ if (scanner->token != G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ /* test if the next token is an accelerator */
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != G_TOKEN_STRING)
+ {
+ /* if not so, eat that token and error out */
+ g_scanner_get_next_token (scanner);
+ return G_TOKEN_STRING;
+ }
+
+ /* get the full accelerator specification */
+ path = g_strdup (scanner->value.v_string);
+ g_scanner_get_next_token (scanner);
+ accel = g_strdup (scanner->value.v_string);
+
+ /* ensure the entry is present */
+ gtk_accel_map_add_entry (path, 0, 0);
+
+ /* and propagate it */
+ gtk_accelerator_parse (accel, &accel_key, &accel_mods);
+ gtk_accel_map_change_entry (path, accel_key, accel_mods, TRUE);
+
+ g_free (accel);
+ g_free (path);
+
+ /* check correct statement end */
+ g_scanner_get_next_token (scanner);
+ if (scanner->token != ')')
+ return ')';
+ else
+ return G_TOKEN_NONE;
+}
+
+static void
+accel_map_parse_statement (GScanner *scanner)
+{
+ guint expected_token;
+
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token == G_TOKEN_SYMBOL)
+ {
+ guint (*parser_func) (GScanner*);
+
+ parser_func = (guint (*) (GScanner *))scanner->value.v_symbol;
+
+ expected_token = parser_func (scanner);
+ }
+ else
+ expected_token = G_TOKEN_SYMBOL;
+
+ /* skip rest of statement on errrors
+ */
+ if (expected_token != G_TOKEN_NONE)
+ {
+ register guint level;
+
+ level = 1;
+ if (scanner->token == ')')
+ level--;
+ if (scanner->token == '(')
+ level++;
+
+ while (!g_scanner_eof (scanner) && level > 0)
+ {
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token == '(')
+ level++;
+ else if (scanner->token == ')')
+ level--;
+ }
+ }
+}
+
+/**
+ * gtk_accel_map_load_scanner:
+ * @scanner: a #GScanner which has already been provided with an input file
+ *
+ * #GScanner variant of gtk_accel_map_load().
+ */
+void
+gtk_accel_map_load_scanner (GScanner *scanner)
+{
+ gboolean skip_comment_single;
+ gboolean symbol_2_token;
+ gchar *cpair_comment_single;
+ gpointer saved_symbol;
+
+ g_return_if_fail (scanner != NULL);
+
+ /* configure scanner */
+ skip_comment_single = scanner->config->skip_comment_single;
+ scanner->config->skip_comment_single = TRUE;
+ cpair_comment_single = scanner->config->cpair_comment_single;
+ scanner->config->cpair_comment_single = (char *) ";\n";
+ symbol_2_token = scanner->config->symbol_2_token;
+ scanner->config->symbol_2_token = FALSE;
+ saved_symbol = g_scanner_lookup_symbol (scanner, "gtk_accel_path");
+ g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path",
+ accel_map_parse_accel_path);
+
+ /* outer parsing loop
+ */
+ g_scanner_peek_next_token (scanner);
+ while (scanner->next_token == '(')
+ {
+ g_scanner_get_next_token (scanner);
+
+ accel_map_parse_statement (scanner);
+
+ g_scanner_peek_next_token (scanner);
+ }
+
+ /* restore config */
+ scanner->config->skip_comment_single = skip_comment_single;
+ scanner->config->cpair_comment_single = cpair_comment_single;
+ scanner->config->symbol_2_token = symbol_2_token;
+ g_scanner_scope_remove_symbol (scanner, 0, "gtk_accel_path");
+ if (saved_symbol)
+ g_scanner_scope_add_symbol (scanner, 0, "gtk_accel_path", saved_symbol);
+}
+
+/**
+ * gtk_accel_map_load_fd:
+ * @fd: a valid readable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_load().
+ *
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_load_fd (gint fd)
+{
+ GScanner *scanner;
+
+ g_return_if_fail (fd >= 0);
+
+ /* create and setup scanner */
+ scanner = g_scanner_new (NULL);
+ g_scanner_input_file (scanner, fd);
+
+ gtk_accel_map_load_scanner (scanner);
+
+ g_scanner_destroy (scanner);
+}
+
+/**
+ * gtk_accel_map_load:
+ * @file_name: (type filename): a file containing accelerator specifications,
+ * in the GLib file name encoding
+ *
+ * Parses a file previously saved with gtk_accel_map_save() for
+ * accelerator specifications, and propagates them accordingly.
+ */
+void
+gtk_accel_map_load (const gchar *file_name)
+{
+ gint fd;
+
+ g_return_if_fail (file_name != NULL);
+
+ fd = g_open (file_name, O_RDONLY, 0);
+ if (fd < 0)
+ return;
+
+ gtk_accel_map_load_fd (fd);
+
+ close (fd);
+}
+
+static gboolean
+write_all (gint fd,
+ gchar *buf,
+ gsize to_write)
+{
+ while (to_write > 0)
+ {
+ gssize count = write (fd, buf, to_write);
+ if (count < 0)
+ {
+ if (errno != EINTR)
+ return FALSE;
+ }
+ else
+ {
+ to_write -= count;
+ buf += count;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+accel_map_print (gpointer data,
+ const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean changed)
+{
+ GString *gstring = g_string_new (changed ? NULL : "; ");
+ gint fd = GPOINTER_TO_INT (data);
+ gchar *tmp, *name;
+
+ g_string_append (gstring, "(gtk_accel_path \"");
+
+ tmp = g_strescape (accel_path, NULL);
+ g_string_append (gstring, tmp);
+ g_free (tmp);
+
+ g_string_append (gstring, "\" \"");
+
+ name = gtk_accelerator_name (accel_key, accel_mods);
+ tmp = g_strescape (name, NULL);
+ g_free (name);
+ g_string_append (gstring, tmp);
+ g_free (tmp);
+
+ g_string_append (gstring, "\")\n");
+
+ write_all (fd, gstring->str, gstring->len);
+
+ g_string_free (gstring, TRUE);
+}
+
+/**
+ * gtk_accel_map_save_fd:
+ * @fd: a valid writable file descriptor
+ *
+ * Filedescriptor variant of gtk_accel_map_save().
+ *
+ * Note that the file descriptor will not be closed by this function.
+ */
+void
+gtk_accel_map_save_fd (gint fd)
+{
+ GString *gstring;
+
+ g_return_if_fail (fd >= 0);
+
+ gstring = g_string_new ("; ");
+ if (g_get_prgname ())
+ g_string_append (gstring, g_get_prgname ());
+ g_string_append (gstring, " GtkAccelMap rc-file -*- scheme -*-\n");
+ g_string_append (gstring, "; this file is an automated accelerator map dump\n");
+ g_string_append (gstring, ";\n");
+
+ write_all (fd, gstring->str, gstring->len);
+
+ g_string_free (gstring, TRUE);
+
+ gtk_accel_map_foreach (GINT_TO_POINTER (fd), accel_map_print);
+}
+
+/**
+ * gtk_accel_map_save:
+ * @file_name: (type filename): the name of the file to contain
+ * accelerator specifications, in the GLib file name encoding
+ *
+ * Saves current accelerator specifications (accelerator path, key
+ * and modifiers) to @file_name.
+ * The file is written in a format suitable to be read back in by
+ * gtk_accel_map_load().
+ */
+void
+gtk_accel_map_save (const gchar *file_name)
+{
+ gint fd;
+
+ g_return_if_fail (file_name != NULL);
+
+ fd = g_open (file_name, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd < 0)
+ return;
+
+ gtk_accel_map_save_fd (fd);
+
+ close (fd);
+}
+
+/**
+ * gtk_accel_map_foreach:
+ * @data: (allow-none): data to be passed into @foreach_func
+ * @foreach_func: (scope call): function to be executed for each accel
+ * map entry which is not filtered out
+ *
+ * Loops over the entries in the accelerator map whose accel path
+ * doesn’t match any of the filters added with gtk_accel_map_add_filter(),
+ * and execute @foreach_func on each. The signature of @foreach_func is
+ * that of #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach (gpointer data,
+ GtkAccelMapForeach foreach_func)
+{
+ GSList *entries, *slist, *node;
+
+ g_return_if_fail (foreach_func != NULL);
+
+ entries = g_hash_table_slist_values (accel_entry_ht);
+ entries = g_slist_sort (entries, accel_entry_compare);
+
+ for (slist = entries; slist; slist = slist->next)
+ {
+ AccelEntry *entry = slist->data;
+ gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+ gboolean skip = FALSE;
+
+ for (node = accel_filters; node; node = node->next)
+ if (g_pattern_match_string (node->data, entry->accel_path))
+ {
+ skip = TRUE;
+ break;
+ }
+
+ if (!skip)
+ foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+ }
+ g_slist_free (entries);
+}
+
+/**
+ * gtk_accel_map_foreach_unfiltered:
+ * @data: data to be passed into @foreach_func
+ * @foreach_func: (scope call): function to be executed for each accel
+ * map entry
+ *
+ * Loops over all entries in the accelerator map, and execute
+ * @foreach_func on each. The signature of @foreach_func is that of
+ * #GtkAccelMapForeach, the @changed parameter indicates whether
+ * this accelerator was changed during runtime (thus, would need
+ * saving during an accelerator map dump).
+ */
+void
+gtk_accel_map_foreach_unfiltered (gpointer data,
+ GtkAccelMapForeach foreach_func)
+{
+ GSList *entries, *slist;
+
+ g_return_if_fail (foreach_func != NULL);
+
+ entries = g_hash_table_slist_values (accel_entry_ht);
+ for (slist = entries; slist; slist = slist->next)
+ {
+ AccelEntry *entry = slist->data;
+ gboolean changed = entry->accel_key != entry->std_accel_key || entry->accel_mods != entry->std_accel_mods;
+
+ foreach_func (data, entry->accel_path, entry->accel_key, entry->accel_mods, changed);
+ }
+ g_slist_free (entries);
+}
+
+/**
+ * gtk_accel_map_add_filter:
+ * @filter_pattern: a pattern (see #GPatternSpec)
+ *
+ * Adds a filter to the global list of accel path filters.
+ *
+ * Accel map entries whose accel path matches one of the filters
+ * are skipped by gtk_accel_map_foreach().
+ *
+ * This function is intended for GTK+ modules that create their own
+ * menus, but don’t want them to be saved into the applications accelerator
+ * map dump.
+ */
+void
+gtk_accel_map_add_filter (const gchar *filter_pattern)
+{
+ GPatternSpec *pspec;
+ GSList *slist;
+
+ g_return_if_fail (filter_pattern != NULL);
+
+ pspec = g_pattern_spec_new (filter_pattern);
+ for (slist = accel_filters; slist; slist = slist->next)
+ if (g_pattern_spec_equal (pspec, slist->data))
+ {
+ g_pattern_spec_free (pspec);
+ return;
+ }
+ accel_filters = g_slist_prepend (accel_filters, pspec);
+}
+
+void
+_gtk_accel_map_add_group (const gchar *accel_path,
+ GtkAccelGroup *accel_group)
+{
+ AccelEntry *entry;
+
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ entry = accel_path_lookup (accel_path);
+ if (!entry)
+ {
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ entry = accel_path_lookup (accel_path);
+ }
+ entry->groups = g_slist_prepend (entry->groups, accel_group);
+}
+
+void
+_gtk_accel_map_remove_group (const gchar *accel_path,
+ GtkAccelGroup *accel_group)
+{
+ AccelEntry *entry;
+
+ entry = accel_path_lookup (accel_path);
+ g_return_if_fail (entry != NULL);
+ g_return_if_fail (g_slist_find (entry->groups, accel_group));
+
+ entry->groups = g_slist_remove (entry->groups, accel_group);
+}
+
+
+/**
+ * gtk_accel_map_lock_path:
+ * @accel_path: a valid accelerator path
+ *
+ * Locks the given accelerator path. If the accelerator map doesn’t yet contain
+ * an entry for @accel_path, a new one is created.
+ *
+ * Locking an accelerator path prevents its accelerator from being changed
+ * during runtime. A locked accelerator path can be unlocked by
+ * gtk_accel_map_unlock_path(). Refer to gtk_accel_map_change_entry()
+ * for information about runtime accelerator changes.
+ *
+ * If called more than once, @accel_path remains locked until
+ * gtk_accel_map_unlock_path() has been called an equivalent number
+ * of times.
+ *
+ * Note that locking of individual accelerator paths is independent from
+ * locking the #GtkAccelGroup containing them. For runtime accelerator
+ * changes to be possible, both the accelerator path and its #GtkAccelGroup
+ * have to be unlocked.
+ **/
+void
+gtk_accel_map_lock_path (const gchar *accel_path)
+{
+ AccelEntry *entry;
+
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+ entry = accel_path_lookup (accel_path);
+
+ if (!entry)
+ {
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ entry = accel_path_lookup (accel_path);
+ }
+
+ entry->lock_count += 1;
+}
+
+/**
+ * gtk_accel_map_unlock_path:
+ * @accel_path: a valid accelerator path
+ *
+ * Undoes the last call to gtk_accel_map_lock_path() on this @accel_path.
+ * Refer to gtk_accel_map_lock_path() for information about accelerator path locking.
+ **/
+void
+gtk_accel_map_unlock_path (const gchar *accel_path)
+{
+ AccelEntry *entry;
+
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+ entry = accel_path_lookup (accel_path);
+
+ g_return_if_fail (entry != NULL && entry->lock_count > 0);
+
+ entry->lock_count -= 1;
+}
+
+G_DEFINE_TYPE (GtkAccelMap, gtk_accel_map, G_TYPE_OBJECT)
+
+static void
+gtk_accel_map_class_init (GtkAccelMapClass *accel_map_class)
+{
+ /**
+ * GtkAccelMap::changed:
+ * @object: the global accel map object
+ * @accel_path: the path of the accelerator that changed
+ * @accel_key: the key value for the new accelerator
+ * @accel_mods: the modifier mask for the new accelerator
+ *
+ * Notifies of a change in the global accelerator map.
+ * The path is also used as the detail for the signal,
+ * so it is possible to connect to
+ * changed::`accel_path`.
+ */
+ accel_map_signals[CHANGED] = g_signal_new (I_("changed"),
+ G_TYPE_FROM_CLASS (accel_map_class),
+ G_SIGNAL_DETAILED|G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ _gtk_marshal_VOID__STRING_UINT_FLAGS,
+ G_TYPE_NONE, 3,
+ G_TYPE_STRING, G_TYPE_UINT, GDK_TYPE_MODIFIER_TYPE);
+}
+
+static void
+gtk_accel_map_init (GtkAccelMap *map)
+{
+}
+
+static GtkAccelMap *accel_map;
+
+/**
+ * gtk_accel_map_get:
+ *
+ * Gets the singleton global #GtkAccelMap object. This object
+ * is useful only for notification of changes to the accelerator
+ * map via the ::changed signal; it isn’t a parameter to the
+ * other accelerator map functions.
+ *
+ * Returns: (transfer none): the global #GtkAccelMap object
+ **/
+GtkAccelMap *
+gtk_accel_map_get (void)
+{
+ if (!accel_map)
+ accel_map = g_object_new (GTK_TYPE_ACCEL_MAP, NULL);
+
+ return accel_map;
+}
+
+static void
+do_accel_map_changed (AccelEntry *entry)
+{
+ if (accel_map)
+ g_signal_emit (accel_map,
+ accel_map_signals[CHANGED],
+ g_quark_from_string (entry->accel_path),
+ entry->accel_path,
+ entry->accel_key,
+ entry->accel_mods);
+}
+
+gchar *
+_gtk_accel_path_for_action (const gchar *action_name,
+ GVariant *parameter)
+{
+ GString *s;
+
+ s = g_string_new ("<GAction>/");
+ g_string_append (s, action_name);
+ if (parameter)
+ {
+ g_string_append_c (s, '/');
+ g_variant_print_string (parameter, s, FALSE);
+ }
+ return g_string_free (s, FALSE);
+}
+
diff --git a/gtk/gtkaccelmap.h b/gtk/gtkaccelmap.h
new file mode 100644
index 0000000000..e04f251299
--- /dev/null
+++ b/gtk/gtkaccelmap.h
@@ -0,0 +1,109 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_ACCEL_MAP_H__
+#define __GTK_ACCEL_MAP_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkaccelgroup.h>
+
+G_BEGIN_DECLS
+
+/* --- global GtkAccelMap object --- */
+#define GTK_TYPE_ACCEL_MAP (gtk_accel_map_get_type ())
+#define GTK_ACCEL_MAP(accel_map) (G_TYPE_CHECK_INSTANCE_CAST ((accel_map), GTK_TYPE_ACCEL_MAP, GtkAccelMap))
+#define GTK_ACCEL_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_MAP, GtkAccelMapClass))
+#define GTK_IS_ACCEL_MAP(accel_map) (G_TYPE_CHECK_INSTANCE_TYPE ((accel_map), GTK_TYPE_ACCEL_MAP))
+#define GTK_IS_ACCEL_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_ACCEL_MAP))
+#define GTK_ACCEL_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ACCEL_MAP, GtkAccelMapClass))
+
+typedef struct _GtkAccelMap GtkAccelMap;
+typedef struct _GtkAccelMapClass GtkAccelMapClass;
+
+/* --- notifier --- */
+/**
+ * GtkAccelMapForeach:
+ * @data: User data passed to gtk_accel_map_foreach() or
+ * gtk_accel_map_foreach_unfiltered()
+ * @accel_path: Accel path of the current accelerator
+ * @accel_key: Key of the current accelerator
+ * @accel_mods: Modifiers of the current accelerator
+ * @changed: Changed flag of the accelerator (if %TRUE, accelerator has changed
+ * during runtime and would need to be saved during an accelerator dump)
+ */
+typedef void (*GtkAccelMapForeach) (gpointer data,
+ const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean changed);
+
+
+/* --- public API --- */
+
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_add_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_map_lookup_entry (const gchar *accel_path,
+ GtkAccelKey *key);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_accel_map_change_entry (const gchar *accel_path,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ gboolean replace);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_load (const gchar *file_name);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_save (const gchar *file_name);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_foreach (gpointer data,
+ GtkAccelMapForeach foreach_func);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_load_fd (gint fd);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_load_scanner (GScanner *scanner);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_save_fd (gint fd);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_lock_path (const gchar *accel_path);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_unlock_path (const gchar *accel_path);
+
+/* --- filter functions --- */
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_add_filter (const gchar *filter_pattern);
+GDK_AVAILABLE_IN_ALL
+void gtk_accel_map_foreach_unfiltered (gpointer data,
+ GtkAccelMapForeach foreach_func);
+
+/* --- notification --- */
+GDK_AVAILABLE_IN_ALL
+GType gtk_accel_map_get_type (void) G_GNUC_CONST;
+GDK_AVAILABLE_IN_ALL
+GtkAccelMap *gtk_accel_map_get (void);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GtkAccelMap, g_object_unref)
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_H__ */
diff --git a/gtk/gtkaccelmapprivate.h b/gtk/gtkaccelmapprivate.h
new file mode 100644
index 0000000000..8be1e5e74a
--- /dev/null
+++ b/gtk/gtkaccelmapprivate.h
@@ -0,0 +1,39 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1998, 2001 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_ACCEL_MAP_PRIVATE_H__
+#define __GTK_ACCEL_MAP_PRIVATE_H__
+
+
+#include <gtk/gtkaccelmap.h>
+
+G_BEGIN_DECLS
+
+void _gtk_accel_map_init (void);
+
+void _gtk_accel_map_add_group (const gchar *accel_path,
+ GtkAccelGroup *accel_group);
+void _gtk_accel_map_remove_group (const gchar *accel_path,
+ GtkAccelGroup *accel_group);
+gboolean _gtk_accel_path_is_valid (const gchar *accel_path);
+
+gchar * _gtk_accel_path_for_action (const gchar *action_name,
+ GVariant *parameter);
+
+G_END_DECLS
+
+#endif /* __GTK_ACCEL_MAP_PRIVATE_H__ */
diff --git a/gtk/gtkapplication.c b/gtk/gtkapplication.c
index efd2e3a55f..768915c807 100644
--- a/gtk/gtkapplication.c
+++ b/gtk/gtkapplication.c
@@ -37,6 +37,7 @@
#include "gtkmarshalers.h"
#include "gtkmain.h"
#include "gtkrecentmanager.h"
+#include "gtkaccelmapprivate.h"
#include "gtkicontheme.h"
#include "gtkbuilder.h"
#include "gtkshortcutswindow.h"
diff --git a/gtk/gtkapplicationaccels.c b/gtk/gtkapplicationaccels.c
index e4e60bfc4b..a27501facf 100644
--- a/gtk/gtkapplicationaccels.c
+++ b/gtk/gtkapplicationaccels.c
@@ -22,28 +22,134 @@
#include "config.h"
#include "gtkapplicationaccelsprivate.h"
-
#include "gtkactionmuxerprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcuttrigger.h"
+
+#include <string.h>
+
+typedef struct
+{
+ guint key;
+ GdkModifierType modifier;
+} AccelKey;
struct _GtkApplicationAccels
{
GObject parent;
- GListModel *shortcuts;
+ GHashTable *action_to_accels;
+ GHashTable *accel_to_actions;
};
G_DEFINE_TYPE (GtkApplicationAccels, gtk_application_accels, G_TYPE_OBJECT)
+static AccelKey *
+accel_key_copy (const AccelKey *source)
+{
+ AccelKey *dest;
+
+ dest = g_slice_new (AccelKey);
+ dest->key = source->key;
+ dest->modifier = source->modifier;
+
+ return dest;
+}
+
+static void
+accel_key_free (gpointer data)
+{
+ AccelKey *key = data;
+
+ g_slice_free (AccelKey, key);
+}
+
+static guint
+accel_key_hash (gconstpointer data)
+{
+ const AccelKey *key = data;
+
+ return key->key + (key->modifier << 16);
+}
+
+static gboolean
+accel_key_equal (gconstpointer a,
+ gconstpointer b)
+{
+ const AccelKey *ak = a;
+ const AccelKey *bk = b;
+
+ return ak->key == bk->key && ak->modifier == bk->modifier;
+}
+
+static void
+add_entry (GtkApplicationAccels *accels,
+ AccelKey *key,
+ const gchar *action_and_target)
+{
+ const gchar **old;
+ const gchar **new;
+ gint n;
+
+ old = g_hash_table_lookup (accels->accel_to_actions, key);
+ if (old != NULL)
+ for (n = 0; old[n]; n++) /* find the length */
+ ;
+ else
+ n = 0;
+
+ new = g_renew (const gchar *, old, n + 1 + 1);
+ new[n] = action_and_target;
+ new[n + 1] = NULL;
+
+ g_hash_table_insert (accels->accel_to_actions, accel_key_copy (key), new);
+}
+
+static void
+remove_entry (GtkApplicationAccels *accels,
+ AccelKey *key,
+ const gchar *action_and_target)
+{
+ const gchar **old;
+ const gchar **new;
+ gint n, i;
+
+ /* if we can't find the entry then something has gone very wrong... */
+ old = g_hash_table_lookup (accels->accel_to_actions, key);
+ g_assert (old != NULL);
+
+ for (n = 0; old[n]; n++) /* find the length */
+ ;
+ g_assert_cmpint (n, >, 0);
+
+ if (n == 1)
+ {
+ /* The simple case of removing the last action for an accel. */
+ g_assert_cmpstr (old[0], ==, action_and_target);
+ g_hash_table_remove (accels->accel_to_actions, key);
+ return;
+ }
+
+ for (i = 0; i < n; i++)
+ if (g_str_equal (old[i], action_and_target))
+ break;
+
+ /* We must have found it... */
+ g_assert_cmpint (i, <, n);
+
+ new = g_new (const gchar *, n - 1 + 1);
+ memcpy (new, old, i * sizeof (const gchar *));
+ memcpy (new + i, old + i + 1, (n - (i + 1)) * sizeof (const gchar *));
+ new[n - 1] = NULL;
+
+ g_hash_table_insert (accels->accel_to_actions, accel_key_copy (key), new);
+}
+
static void
gtk_application_accels_finalize (GObject *object)
{
GtkApplicationAccels *accels = GTK_APPLICATION_ACCELS (object);
- g_list_store_remove_all (G_LIST_STORE (accels->shortcuts));
- g_object_unref (accels->shortcuts);
+ g_hash_table_unref (accels->accel_to_actions);
+ g_hash_table_unref (accels->action_to_accels);
G_OBJECT_CLASS (gtk_application_accels_parent_class)->finalize (object);
}
@@ -59,7 +165,9 @@ gtk_application_accels_class_init (GtkApplicationAccelsClass *klass)
static void
gtk_application_accels_init (GtkApplicationAccels *accels)
{
- accels->shortcuts = G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
+ accels->accel_to_actions = g_hash_table_new_full (accel_key_hash, accel_key_equal,
+ accel_key_free, g_free);
+ accels->action_to_accels = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
GtkApplicationAccels *
@@ -73,97 +181,54 @@ gtk_application_accels_set_accels_for_action (GtkApplicationAccels *accels,
const gchar *detailed_action_name,
const gchar * const *accelerators)
{
- gchar *action_name;
- GVariant *target;
- GtkShortcut *shortcut;
- GtkShortcutTrigger *trigger = NULL;
- GError *error = NULL;
- guint i;
-
- if (!g_action_parse_detailed_name (detailed_action_name, &action_name, &target, &error))
- {
- g_critical ("Error parsing action name: %s", error->message);
- g_error_free (error);
- return;
- }
-
- /* remove the accelerator if it already exists */
- for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
- {
- GtkShortcut *shortcut_i = g_list_model_get_item (accels->shortcuts, i);
- GtkShortcutAction *action = gtk_shortcut_get_action (shortcut_i);
- GVariant *args = gtk_shortcut_get_arguments (shortcut_i);
-
- if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION ||
- !g_str_equal (gtk_action_action_get_name (action), action_name))
- continue;
+ gchar *action_and_target;
+ AccelKey *keys, *old_keys;
+ gint i, n;
- if ((target == NULL && args != NULL) ||
- (target != NULL && (args == NULL || !g_variant_equal (target, args))))
- continue;
-
- g_list_store_remove (G_LIST_STORE (accels->shortcuts), i);
- break;
- }
+ action_and_target = gtk_normalise_detailed_action_name (detailed_action_name);
- if (accelerators == NULL)
- goto out;
+ n = accelerators ? g_strv_length ((gchar **) accelerators) : 0;
- for (i = 0; accelerators[i]; i++)
+ if (n > 0)
{
- GtkShortcutTrigger *new_trigger;
- guint key, modifier;
+ keys = g_new0 (AccelKey, n + 1);
- if (!gtk_accelerator_parse (accelerators[i], &key, &modifier))
+ for (i = 0; i < n; i++)
{
- g_critical ("Unable to parse accelerator '%s': ignored request to install accelerators",
- accelerators[i]);
- if (trigger)
- gtk_shortcut_trigger_unref (trigger);
- goto out;;
+ gtk_accelerator_parse (accelerators[i], &keys[i].key, &keys[i].modifier);
+
+ if (keys[i].key == 0)
+ {
+ g_warning ("Unable to parse accelerator '%s': ignored request to install %d accelerators",
+ accelerators[i], n);
+ g_free (action_and_target);
+ g_free (keys);
+ return;
+ }
}
- new_trigger = gtk_keyval_trigger_new (key, modifier);
- if (trigger)
- trigger = gtk_alternative_trigger_new (trigger, new_trigger);
- else
- trigger = new_trigger;
}
- if (trigger == NULL)
- goto out;
-
- shortcut = gtk_shortcut_new (trigger, gtk_action_action_new (action_name));
- gtk_shortcut_set_arguments (shortcut, target);
- g_list_store_append (G_LIST_STORE (accels->shortcuts), shortcut);
- g_object_unref (shortcut);
-
-out:
- g_free (action_name);
- if (target)
- g_variant_unref (target);
-}
+ else
+ keys = NULL;
-static void
-append_accelerators (GPtrArray *accels,
- GtkShortcutTrigger *trigger)
-{
- switch (gtk_shortcut_trigger_get_trigger_type (trigger))
+ old_keys = g_hash_table_lookup (accels->action_to_accels, action_and_target);
+ if (old_keys)
{
- case GTK_SHORTCUT_TRIGGER_KEYVAL:
- g_ptr_array_add (accels,
- gtk_accelerator_name (gtk_keyval_trigger_get_keyval (trigger),
- gtk_keyval_trigger_get_modifiers (trigger)));
- return;
+ /* We need to remove accel entries from existing keys */
+ for (i = 0; old_keys[i].key; i++)
+ remove_entry (accels, &old_keys[i], action_and_target);
+ }
- case GTK_SHORTCUT_TRIGGER_ALTERNATIVE:
- append_accelerators (accels, gtk_alternative_trigger_get_first (trigger));
- append_accelerators (accels, gtk_alternative_trigger_get_second (trigger));
- return;
+ if (keys)
+ {
+ g_hash_table_replace (accels->action_to_accels, action_and_target, keys);
- case GTK_SHORTCUT_TRIGGER_MNEMONIC:
- case GTK_SHORTCUT_TRIGGER_NEVER:
- default:
- /* not an accelerator */
- return;
+ for (i = 0; i < n; i++)
+ add_entry (accels, &keys[i], action_and_target);
+ }
+ else
+ {
+ g_hash_table_remove (accels->action_to_accels, action_and_target);
+ g_free (action_and_target);
}
}
@@ -171,137 +236,223 @@ gchar **
gtk_application_accels_get_accels_for_action (GtkApplicationAccels *accels,
const gchar *detailed_action_name)
{
- GPtrArray *result;
- char *action_name;
- GVariant *target;
- GError *error = NULL;
- guint i;
+ gchar *action_and_target;
+ AccelKey *keys;
+ gchar **result;
+ gint n, i = 0;
- result = g_ptr_array_new ();
+ action_and_target = gtk_normalise_detailed_action_name (detailed_action_name);
- if (!g_action_parse_detailed_name (detailed_action_name, &action_name, &target, &error))
+ keys = g_hash_table_lookup (accels->action_to_accels, action_and_target);
+ if (!keys)
{
- g_critical ("Error parsing action name: %s", error->message);
- g_error_free (error);
- g_ptr_array_add (result, NULL);
- return (gchar **) g_ptr_array_free (result, FALSE);
+ g_free (action_and_target);
+ return g_new0 (gchar *, 0 + 1);
}
- for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
- {
- GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
- GtkShortcutAction *action = gtk_shortcut_get_action (shortcut);
- GVariant *args = gtk_shortcut_get_arguments (shortcut);
+ for (n = 0; keys[n].key; n++)
+ ;
- if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION ||
- !g_str_equal (gtk_action_action_get_name (action), action_name))
- continue;
+ result = g_new0 (gchar *, n + 1);
- if ((target == NULL && args != NULL) ||
- (target != NULL && (args == NULL || !g_variant_equal (target, args))))
- continue;
-
- append_accelerators (result, gtk_shortcut_get_trigger (shortcut));
- break;
- }
+ for (i = 0; i < n; i++)
+ result[i] = gtk_accelerator_name (keys[i].key, keys[i].modifier);
- g_free (action_name);
- if (target)
- g_variant_unref (target);
- g_ptr_array_add (result, NULL);
- return (gchar **) g_ptr_array_free (result, FALSE);
+ g_free (action_and_target);
+ return result;
}
-static gboolean
-trigger_matches_accel (GtkShortcutTrigger *trigger,
- guint keyval,
- GdkModifierType modifiers)
+gchar **
+gtk_application_accels_get_actions_for_accel (GtkApplicationAccels *accels,
+ const gchar *accel)
{
- switch (gtk_shortcut_trigger_get_trigger_type (trigger))
+ const gchar * const *actions_and_targets;
+ gchar **detailed_actions;
+ AccelKey accel_key;
+ guint i, n;
+
+ gtk_accelerator_parse (accel, &accel_key.key, &accel_key.modifier);
+
+ if (accel_key.key == 0)
{
- case GTK_SHORTCUT_TRIGGER_KEYVAL:
- return gtk_keyval_trigger_get_keyval (trigger) == keyval
- && gtk_keyval_trigger_get_modifiers (trigger) == modifiers;
-
- case GTK_SHORTCUT_TRIGGER_ALTERNATIVE:
- return trigger_matches_accel (gtk_alternative_trigger_get_first (trigger), keyval, modifiers)
- || trigger_matches_accel (gtk_alternative_trigger_get_second (trigger), keyval, modifiers);
-
- case GTK_SHORTCUT_TRIGGER_MNEMONIC:
- case GTK_SHORTCUT_TRIGGER_NEVER:
- default:
- return FALSE;
+ g_critical ("invalid accelerator string '%s'", accel);
+ g_return_val_if_fail (accel_key.key != 0, NULL);
}
-}
-static char *
-get_detailed_name_for_shortcut (GtkShortcut *shortcut)
-{
- GtkShortcutAction *action = gtk_shortcut_get_action (shortcut);
+ actions_and_targets = g_hash_table_lookup (accels->accel_to_actions, &accel_key);
+ n = actions_and_targets ? g_strv_length ((gchar **) actions_and_targets) : 0;
- if (gtk_shortcut_action_get_action_type (action) != GTK_SHORTCUT_ACTION_ACTION)
- return NULL;
+ detailed_actions = g_new0 (gchar *, n + 1);
- return g_action_print_detailed_name (gtk_action_action_get_name (action), gtk_shortcut_get_arguments (shortcut));
+ for (i = 0; i < n; i++)
+ {
+ const gchar *action_and_target = actions_and_targets[i];
+ const gchar *sep;
+ GVariant *target;
+
+ sep = strrchr (action_and_target, '|');
+ target = g_variant_parse (NULL, action_and_target, sep, NULL, NULL);
+ detailed_actions[i] = g_action_print_detailed_name (sep + 1, target);
+ if (target)
+ g_variant_unref (target);
+ }
+
+ detailed_actions[n] = NULL;
+
+ return detailed_actions;
}
gchar **
-gtk_application_accels_get_actions_for_accel (GtkApplicationAccels *accels,
- const gchar *accel)
+gtk_application_accels_list_action_descriptions (GtkApplicationAccels *accels)
{
- GPtrArray *result;
- guint key, modifiers;
- guint i;
+ GHashTableIter iter;
+ gchar **result;
+ gint n, i = 0;
+ gpointer key;
- if (!gtk_accelerator_parse (accel, &key, &modifiers))
- {
- g_critical ("invalid accelerator string '%s'", accel);
- return NULL;
- }
+ n = g_hash_table_size (accels->action_to_accels);
+ result = g_new (gchar *, n + 1);
- result = g_ptr_array_new ();
-
- for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
+ g_hash_table_iter_init (&iter, accels->action_to_accels);
+ while (g_hash_table_iter_next (&iter, &key, NULL))
{
- GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
- char *detailed_name;
-
- if (!trigger_matches_accel (gtk_shortcut_get_trigger (shortcut), key, modifiers))
- continue;
-
- detailed_name = get_detailed_name_for_shortcut (shortcut);
- if (detailed_name)
- g_ptr_array_add (result, detailed_name);
+ const gchar *action_and_target = key;
+ const gchar *sep;
+ GVariant *target;
+
+ sep = strrchr (action_and_target, '|');
+ target = g_variant_parse (NULL, action_and_target, sep, NULL, NULL);
+ result[i++] = g_action_print_detailed_name (sep + 1, target);
+ if (target)
+ g_variant_unref (target);
}
+ g_assert_cmpint (i, ==, n);
+ result[i] = NULL;
- g_ptr_array_add (result, NULL);
- return (gchar **) g_ptr_array_free (result, FALSE);
+ return result;
}
-gchar **
-gtk_application_accels_list_action_descriptions (GtkApplicationAccels *accels)
+void
+gtk_application_accels_foreach_key (GtkApplicationAccels *accels,
+ GtkWindow *window,
+ GtkWindowKeysForeachFunc callback,
+ gpointer user_data)
{
- GPtrArray *result;
- guint i;
+ GHashTableIter iter;
+ gpointer key;
- result = g_ptr_array_new ();
-
- for (i = 0; i < g_list_model_get_n_items (accels->shortcuts); i++)
+ g_hash_table_iter_init (&iter, accels->accel_to_actions);
+ while (g_hash_table_iter_next (&iter, &key, NULL))
{
- GtkShortcut *shortcut = g_list_model_get_item (accels->shortcuts, i);
- char *detailed_name;
+ AccelKey *accel_key = key;
- detailed_name = get_detailed_name_for_shortcut (shortcut);
- if (detailed_name)
- g_ptr_array_add (result, detailed_name);
+ (* callback) (window, accel_key->key, accel_key->modifier, FALSE, user_data);
}
-
- g_ptr_array_add (result, NULL);
- return (gchar **) g_ptr_array_free (result, FALSE);
}
-GListModel *
-gtk_application_accels_get_shortcuts (GtkApplicationAccels *accels)
+gboolean
+gtk_application_accels_activate (GtkApplicationAccels *accels,
+ GActionGroup *action_group,
+ guint key,
+ GdkModifierType modifier)
{
- return accels->shortcuts;
+ AccelKey accel_key = { key, modifier };
+ const gchar **actions;
+ gint i;
+
+ actions = g_hash_table_lookup (accels->accel_to_actions, &accel_key);
+
+ if (actions == NULL)
+ return FALSE;
+
+ /* We may have more than one action on a given accel. This could be
+ * the case if we have different types of windows with different
+ * actions in each.
+ *
+ * Find the first one that will successfully activate and use it.
+ */
+ for (i = 0; actions[i]; i++)
+ {
+ const GVariantType *parameter_type;
+ const gchar *action_name;
+ const gchar *sep;
+ gboolean enabled;
+ GVariant *target;
+
+ sep = strrchr (actions[i], '|');
+ action_name = sep + 1;
+
+ if (!g_action_group_query_action (action_group, action_name, &enabled, &parameter_type, NULL, NULL, NULL))
+ continue;
+
+ if (!enabled)
+ continue;
+
+ /* We found an action with the correct name and it's enabled.
+ * This is the action that we are going to try to invoke.
+ *
+ * There is still the possibility that the target value doesn't
+ * match the expected parameter type. In that case, we will print
+ * a warning.
+ *
+ * Note: we want to hold a ref on the target while we're invoking
+ * the action to prevent trouble if someone uninstalls the accel
+ * from the handler. That's not a problem since we're parsing it.
+ */
+ if (actions[i] != sep) /* if it has a target... */
+ {
+ GError *error = NULL;
+
+ if (parameter_type == NULL)
+ {
+ gchar *accel_str = gtk_accelerator_name (key, modifier);
+ g_warning ("Accelerator '%s' tries to invoke action '%s' with target, but action has no parameter",
+ accel_str, action_name);
+ g_free (accel_str);
+ return TRUE;
+ }
+
+ target = g_variant_parse (NULL, actions[i], sep, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (target);
+
+ if (!g_variant_is_of_type (target, parameter_type))
+ {
+ gchar *accel_str = gtk_accelerator_name (key, modifier);
+ gchar *typestr = g_variant_type_dup_string (parameter_type);
+ gchar *targetstr = g_variant_print (target, TRUE);
+ g_warning ("Accelerator '%s' tries to invoke action '%s' with target '%s',"
+ " but action expects parameter with type '%s'", accel_str, action_name, targetstr, typestr);
+ g_variant_unref (target);
+ g_free (targetstr);
+ g_free (accel_str);
+ g_free (typestr);
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (parameter_type != NULL)
+ {
+ gchar *accel_str = gtk_accelerator_name (key, modifier);
+ gchar *typestr = g_variant_type_dup_string (parameter_type);
+ g_warning ("Accelerator '%s' tries to invoke action '%s' without target,"
+ " but action expects parameter with type '%s'", accel_str, action_name, typestr);
+ g_free (accel_str);
+ g_free (typestr);
+ return TRUE;
+ }
+
+ target = NULL;
+ }
+
+ g_action_group_activate_action (action_group, action_name, target);
+
+ if (target)
+ g_variant_unref (target);
+
+ return TRUE;
+ }
+
+ return FALSE;
}
diff --git a/gtk/gtkapplicationaccelsprivate.h b/gtk/gtkapplicationaccelsprivate.h
index fbde7da368..b126401a78 100644
--- a/gtk/gtkapplicationaccelsprivate.h
+++ b/gtk/gtkapplicationaccelsprivate.h
@@ -47,7 +47,15 @@ gchar ** gtk_application_accels_get_actions_for_accel (GtkApplicat
gchar ** gtk_application_accels_list_action_descriptions (GtkApplicationAccels *accels);
-GListModel * gtk_application_accels_get_shortcuts (GtkApplicationAccels *accels);
+void gtk_application_accels_foreach_key (GtkApplicationAccels *accels,
+ GtkWindow *window,
+ GtkWindowKeysForeachFunc callback,
+ gpointer user_data);
+
+gboolean gtk_application_accels_activate (GtkApplicationAccels *accels,
+ GActionGroup *action_group,
+ guint key,
+ GdkModifierType modifier);
G_END_DECLS
diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c
index b0b46c1dd2..4161e2d1b4 100644
--- a/gtk/gtkassistant.c
+++ b/gtk/gtkassistant.c
@@ -65,6 +65,7 @@
#include "gtkassistant.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbuildable.h"
#include "gtkbutton.h"
@@ -509,6 +510,7 @@ gtk_assistant_class_init (GtkAssistantClass *class)
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
GtkWindowClass *window_class;
+ GtkBindingSet *binding_set;
gobject_class = (GObjectClass *) class;
widget_class = (GtkWidgetClass *) class;
@@ -617,10 +619,8 @@ gtk_assistant_class_init (GtkAssistantClass *class)
NULL,
G_TYPE_NONE, 0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "escape",
- NULL);
+ binding_set = gtk_binding_set_by_class (class);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "escape", 0);
/**
* GtkAssistant:use-header-bar:
diff --git a/gtk/gtkbindings.c b/gtk/gtkbindings.c
new file mode 100644
index 0000000000..9f3d879d04
--- /dev/null
+++ b/gtk/gtkbindings.c
@@ -0,0 +1,1793 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkBindingSet: Keybinding manager for GObjects.
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdarg.h>
+
+#include "gtkbindingsprivate.h"
+#include "gtkkeyhash.h"
+#include "gtkstylecontext.h"
+#include "gtkwidget.h"
+#include "gtkintl.h"
+
+/**
+ * SECTION:gtkbindings
+ * @Title: Bindings
+ * @Short_description: Key bindings for individual widgets
+ * @See_also: Keyboard Accelerators, Mnemonics, #GtkCssProvider
+ *
+ * #GtkBindingSet provides a mechanism for configuring GTK+ key bindings
+ * through CSS files. This eases key binding adjustments for application
+ * developers as well as users and provides GTK+ users or administrators
+ * with high key binding configurability which requires no application
+ * or toolkit side changes.
+ *
+ * In order for bindings to work in a custom widget implementation, the
+ * widget’s #GtkWidget:can-focus and #GtkWidget:has-focus properties
+ * must both be true. For example, by calling gtk_widget_set_can_focus()
+ * in the widget’s initialisation function; and by calling
+ * gtk_widget_grab_focus() when the widget is clicked.
+ */
+
+/* --- defines --- */
+#define BINDING_MOD_MASK() (gtk_accelerator_get_default_mod_mask () | GDK_RELEASE_MASK)
+
+
+/* --- structures --- */
+typedef enum {
+ GTK_BINDING_TOKEN_BIND,
+ GTK_BINDING_TOKEN_UNBIND
+} GtkBindingTokens;
+
+typedef struct _GtkBindingEntry GtkBindingEntry;
+typedef struct _GtkBindingSignal GtkBindingSignal;
+typedef struct _GtkBindingArg GtkBindingArg;
+typedef struct _GtkBindingSignalSignal GtkBindingSignalSignal;
+typedef struct _GtkBindingSignalAction GtkBindingSignalAction;
+typedef struct _GtkBindingSignalCallback GtkBindingSignalCallback;
+
+/**
+ * GtkBindingSet:
+ * @set_name: unique name of this binding set
+ * @priority: unused
+ * @entries: the key binding entries in this binding set
+ * @current: implementation detail
+ *
+ * A binding set maintains a list of activatable key bindings.
+ * A single binding set can match multiple types of widgets.
+ * Similar to style contexts, can be matched by any information contained
+ * in a widgets #GtkWidgetPath. When a binding within a set is matched upon
+ * activation, an action signal is emitted on the target widget to carry out
+ * the actual activation.
+ */
+struct _GtkBindingSet
+{
+ gchar *set_name;
+ gint priority;
+ GtkBindingEntry *entries;
+ GtkBindingEntry *current;
+};
+
+/**
+ * GtkBindingEntry:
+ * @keyval: key value to match
+ * @modifiers: key modifiers to match
+ * @binding_set: binding set this entry belongs to
+ * @destroyed: implementation detail
+ * @in_emission: implementation detail
+ * @marks_unbound: implementation detail
+ * @set_next: linked list of entries maintained by binding set
+ * @hash_next: implementation detail
+ * @signals: action signals of this entry
+ *
+ * Each key binding element of a binding sets binding list is
+ * represented by a GtkBindingEntry.
+ */
+struct _GtkBindingEntry
+{
+ /* key portion */
+ guint keyval;
+ GdkModifierType modifiers;
+
+ GtkBindingSet *binding_set;
+ guint destroyed : 1;
+ guint in_emission : 1;
+ guint marks_unbound : 1;
+ GtkBindingEntry *set_next;
+ GtkBindingEntry *hash_next;
+ GtkBindingSignal *signals;
+};
+
+/**
+ * GtkBindingArg:
+ * @arg_type: implementation detail
+ *
+ * A #GtkBindingArg holds the data associated with
+ * an argument for a key binding signal emission as
+ * stored in #GtkBindingSignal.
+ */
+struct _GtkBindingArg
+{
+ GType arg_type;
+ union {
+ glong long_data;
+ gdouble double_data;
+ gchar *string_data;
+ } d;
+};
+
+typedef enum
+{
+ GTK_BINDING_SIGNAL,
+ GTK_BINDING_ACTION,
+ GTK_BINDING_CALLBACK
+} GtkBindingActionType;
+
+/**
+ * GtkBindingSignal:
+ * @next: implementation detail
+ * @action_type: Actual type of the action
+ *
+ * A GtkBindingSignal stores the necessary information to
+ * activate a widget in response to a key press via a signal
+ * emission.
+ */
+struct _GtkBindingSignal
+{
+ GtkBindingSignal *next;
+ GtkBindingActionType action_type;
+};
+
+struct _GtkBindingSignalSignal
+{
+ GtkBindingSignal parent;
+ const gchar *signal_name;
+ guint n_args;
+ GtkBindingArg *args;
+};
+
+struct _GtkBindingSignalAction
+{
+ GtkBindingSignal parent;
+ const gchar *action_name;
+ GVariant *variant;
+};
+
+struct _GtkBindingSignalCallback
+{
+ GtkBindingSignal parent;
+ GtkBindingCallback callback;
+ GVariant *args;
+ gpointer user_data;
+ GDestroyNotify user_destroy;
+};
+
+/* --- variables --- */
+static GHashTable *binding_entry_hash_table = NULL;
+static GSList *binding_key_hashes = NULL;
+static GSList *binding_set_list = NULL;
+static const gchar key_class_binding_set[] = "gtk-class-binding-set";
+static GQuark key_id_class_binding_set = 0;
+
+
+/* --- functions --- */
+
+static GtkBindingSignal*
+binding_signal_new_signal (const gchar *signal_name,
+ guint n_args)
+{
+ GtkBindingSignalSignal *signal;
+
+ signal = (GtkBindingSignalSignal *) g_slice_alloc0 (sizeof (GtkBindingSignalSignal) + n_args * sizeof (GtkBindingArg));
+ signal->parent.next = NULL;
+ signal->parent.action_type = GTK_BINDING_SIGNAL;
+ signal->signal_name = g_intern_string (signal_name);
+ signal->n_args = n_args;
+ signal->args = (GtkBindingArg *)(signal + 1);
+
+ return &signal->parent;
+}
+
+static GtkBindingSignal*
+binding_signal_new_action (const gchar *action_name,
+ GVariant *variant)
+{
+ GtkBindingSignalAction *signal;
+
+ signal = g_slice_new0 (GtkBindingSignalAction);
+ signal->parent.next = NULL;
+ signal->parent.action_type = GTK_BINDING_ACTION;
+ signal->action_name = g_intern_string (action_name);
+ signal->variant = variant;
+ if (variant)
+ g_variant_ref_sink (variant);
+
+ return &signal->parent;
+}
+
+static GtkBindingSignal *
+binding_signal_new_callback (GtkBindingCallback callback,
+ GVariant *args,
+ gpointer user_data,
+ GDestroyNotify user_destroy)
+{
+ GtkBindingSignalCallback *signal;
+
+ signal = g_slice_new0 (GtkBindingSignalCallback);
+ signal->parent.next = NULL;
+ signal->parent.action_type = GTK_BINDING_CALLBACK;
+ signal->callback = callback;
+ signal->args = args;
+ if (args)
+ g_variant_ref_sink (args);
+ signal->user_data = user_data;
+ signal->user_destroy = user_destroy;
+
+ return &signal->parent;
+}
+
+static void
+binding_signal_free (GtkBindingSignal *signal)
+{
+ guint i;
+
+ switch (signal->action_type)
+ {
+ case GTK_BINDING_SIGNAL:
+ {
+ GtkBindingSignalSignal *sig = (GtkBindingSignalSignal *) signal;
+ for (i = 0; i < sig->n_args; i++)
+ {
+ if (G_TYPE_FUNDAMENTAL (sig->args[i].arg_type) == G_TYPE_STRING)
+ g_free (sig->args[i].d.string_data);
+ }
+ g_slice_free1 (sizeof (GtkBindingSignalSignal) + sig->n_args * sizeof (GtkBindingArg), sig);
+ }
+ break;
+
+ case GTK_BINDING_ACTION:
+ {
+ GtkBindingSignalAction *sig = (GtkBindingSignalAction *) signal;
+ g_clear_pointer (&sig->variant, g_variant_unref);
+ g_slice_free (GtkBindingSignalAction, sig);
+ }
+ break;
+
+ case GTK_BINDING_CALLBACK:
+ {
+ GtkBindingSignalCallback *sig = (GtkBindingSignalCallback *) signal;
+ if (sig->user_destroy)
+ sig->user_destroy (sig->user_data);
+ g_slice_free (GtkBindingSignalCallback, sig);
+ }
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static guint
+binding_entry_hash (gconstpointer key)
+{
+ register const GtkBindingEntry *e = key;
+ register guint h;
+
+ h = e->keyval;
+ h ^= e->modifiers;
+
+ return h;
+}
+
+static gint
+binding_entries_compare (gconstpointer a,
+ gconstpointer b)
+{
+ register const GtkBindingEntry *ea = a;
+ register const GtkBindingEntry *eb = b;
+
+ return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
+}
+
+static void
+binding_key_hash_insert_entry (GtkKeyHash *key_hash,
+ GtkBindingEntry *entry)
+{
+ guint keyval = entry->keyval;
+
+ /* We store lowercased accelerators. To deal with this, if <Shift>
+ * was specified, uppercase.
+ */
+ if (entry->modifiers & GDK_SHIFT_MASK)
+ {
+ if (keyval == GDK_KEY_Tab)
+ keyval = GDK_KEY_ISO_Left_Tab;
+ else
+ keyval = gdk_keyval_to_upper (keyval);
+ }
+
+ _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
+}
+
+static void
+binding_key_hash_destroy (gpointer data)
+{
+ GtkKeyHash *key_hash = data;
+
+ binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
+ _gtk_key_hash_free (key_hash);
+}
+
+static void
+insert_entries_into_key_hash (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ GtkKeyHash *key_hash = data;
+ GtkBindingEntry *entry = value;
+
+ for (; entry; entry = entry->hash_next)
+ binding_key_hash_insert_entry (key_hash, entry);
+}
+
+static GtkKeyHash *
+binding_key_hash_for_keymap (GdkKeymap *keymap)
+{
+ static GQuark key_hash_quark = 0;
+ GtkKeyHash *key_hash;
+
+ if (!key_hash_quark)
+ key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
+
+ key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
+
+ if (!key_hash)
+ {
+ key_hash = _gtk_key_hash_new (keymap, NULL);
+ g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
+
+ if (binding_entry_hash_table)
+ g_hash_table_foreach (binding_entry_hash_table,
+ insert_entries_into_key_hash,
+ key_hash);
+
+ binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
+ }
+
+ return key_hash;
+}
+
+
+static GtkBindingEntry*
+binding_entry_new (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GSList *tmp_list;
+ GtkBindingEntry *entry;
+
+ if (!binding_entry_hash_table)
+ binding_entry_hash_table = g_hash_table_new (binding_entry_hash, binding_entries_compare);
+
+ entry = g_new (GtkBindingEntry, 1);
+ entry->keyval = keyval;
+ entry->modifiers = modifiers;
+ entry->binding_set = binding_set,
+ entry->destroyed = FALSE;
+ entry->in_emission = FALSE;
+ entry->marks_unbound = FALSE;
+ entry->signals = NULL;
+
+ entry->set_next = binding_set->entries;
+ binding_set->entries = entry;
+
+ entry->hash_next = g_hash_table_lookup (binding_entry_hash_table, entry);
+ if (entry->hash_next)
+ g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
+ g_hash_table_insert (binding_entry_hash_table, entry, entry);
+
+ for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkKeyHash *key_hash = tmp_list->data;
+ binding_key_hash_insert_entry (key_hash, entry);
+ }
+
+ return entry;
+}
+
+static void
+binding_entry_free (GtkBindingEntry *entry)
+{
+ GtkBindingSignal *sig;
+
+ g_assert (entry->set_next == NULL &&
+ entry->hash_next == NULL &&
+ entry->in_emission == FALSE &&
+ entry->destroyed == TRUE);
+
+ entry->destroyed = FALSE;
+
+ sig = entry->signals;
+ while (sig)
+ {
+ GtkBindingSignal *prev;
+
+ prev = sig;
+ sig = prev->next;
+ binding_signal_free (prev);
+ }
+ g_free (entry);
+}
+
+static void
+binding_entry_destroy (GtkBindingEntry *entry)
+{
+ GtkBindingEntry *o_entry;
+ register GtkBindingEntry *tmp;
+ GtkBindingEntry *begin;
+ register GtkBindingEntry *last;
+ GSList *tmp_list;
+
+ /* unlink from binding set
+ */
+ last = NULL;
+ tmp = entry->binding_set->entries;
+ while (tmp)
+ {
+ if (tmp == entry)
+ {
+ if (last)
+ last->set_next = entry->set_next;
+ else
+ entry->binding_set->entries = entry->set_next;
+ break;
+ }
+ last = tmp;
+ tmp = last->set_next;
+ }
+ entry->set_next = NULL;
+
+ o_entry = g_hash_table_lookup (binding_entry_hash_table, entry);
+ begin = o_entry;
+ last = NULL;
+ tmp = begin;
+ while (tmp)
+ {
+ if (tmp == entry)
+ {
+ if (last)
+ last->hash_next = entry->hash_next;
+ else
+ begin = entry->hash_next;
+ break;
+ }
+ last = tmp;
+ tmp = last->hash_next;
+ }
+ entry->hash_next = NULL;
+
+ if (!begin)
+ g_hash_table_remove (binding_entry_hash_table, entry);
+ else if (begin != o_entry)
+ {
+ g_hash_table_remove (binding_entry_hash_table, entry);
+ g_hash_table_insert (binding_entry_hash_table, begin, begin);
+ }
+
+ for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkKeyHash *key_hash = tmp_list->data;
+ _gtk_key_hash_remove_entry (key_hash, entry);
+ }
+
+ entry->destroyed = TRUE;
+
+ if (!entry->in_emission)
+ binding_entry_free (entry);
+}
+
+static GtkBindingEntry*
+binding_ht_lookup_entry (GtkBindingSet *set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GtkBindingEntry lookup_entry = { 0 };
+ GtkBindingEntry *entry;
+
+ if (!binding_entry_hash_table)
+ return NULL;
+
+ lookup_entry.keyval = keyval;
+ lookup_entry.modifiers = modifiers;
+
+ entry = g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
+ for (; entry; entry = entry->hash_next)
+ if (entry->binding_set == set)
+ return entry;
+
+ return NULL;
+}
+
+static gboolean
+binding_compose_params (GObject *object,
+ GtkBindingArg *args,
+ GSignalQuery *query,
+ GValue **params_p)
+{
+ GValue *params;
+ const GType *types;
+ guint i;
+ gboolean valid;
+
+ params = g_new0 (GValue, query->n_params + 1);
+ *params_p = params;
+
+ /* The instance we emit on is the first object in the array
+ */
+ g_value_init (params, G_TYPE_OBJECT);
+ g_value_set_object (params, G_OBJECT (object));
+ params++;
+
+ types = query->param_types;
+ valid = TRUE;
+ for (i = 1; i < query->n_params + 1 && valid; i++)
+ {
+ GValue tmp_value = G_VALUE_INIT;
+
+ g_value_init (params, *types);
+
+ switch (G_TYPE_FUNDAMENTAL (args->arg_type))
+ {
+ case G_TYPE_DOUBLE:
+ g_value_init (&tmp_value, G_TYPE_DOUBLE);
+ g_value_set_double (&tmp_value, args->d.double_data);
+ break;
+ case G_TYPE_LONG:
+ g_value_init (&tmp_value, G_TYPE_LONG);
+ g_value_set_long (&tmp_value, args->d.long_data);
+ break;
+ case G_TYPE_STRING:
+ /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
+ * that since we don't have a GParamSpec, so just do something simple
+ */
+ if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
+ {
+ GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
+ GEnumValue *enum_value;
+
+ valid = FALSE;
+
+ enum_value = g_enum_get_value_by_name (class, args->d.string_data);
+ if (!enum_value)
+ enum_value = g_enum_get_value_by_nick (class, args->d.string_data);
+
+ if (enum_value)
+ {
+ g_value_init (&tmp_value, *types);
+ g_value_set_enum (&tmp_value, enum_value->value);
+ valid = TRUE;
+ }
+
+ g_type_class_unref (class);
+ }
+ /* This is just a hack for compatibility with GTK+-1.2 where a string
+ * could be used for a single flag value / without the support for multiple
+ * values in gtk_rc_parse_flags(), this isn't very useful.
+ */
+ else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
+ {
+ GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
+ GFlagsValue *flags_value;
+
+ valid = FALSE;
+
+ flags_value = g_flags_get_value_by_name (class, args->d.string_data);
+ if (!flags_value)
+ flags_value = g_flags_get_value_by_nick (class, args->d.string_data);
+ if (flags_value)
+ {
+ g_value_init (&tmp_value, *types);
+ g_value_set_flags (&tmp_value, flags_value->value);
+ valid = TRUE;
+ }
+
+ g_type_class_unref (class);
+ }
+ else
+ {
+ g_value_init (&tmp_value, G_TYPE_STRING);
+ g_value_set_static_string (&tmp_value, args->d.string_data);
+ }
+ break;
+ default:
+ valid = FALSE;
+ break;
+ }
+
+ if (valid)
+ {
+ if (!g_value_transform (&tmp_value, params))
+ valid = FALSE;
+
+ g_value_unset (&tmp_value);
+ }
+
+ types++;
+ params++;
+ args++;
+ }
+
+ if (!valid)
+ {
+ guint j;
+
+ for (j = 0; j < i; j++)
+ g_value_unset (&(*params_p)[j]);
+
+ g_free (*params_p);
+ *params_p = NULL;
+ }
+
+ return valid;
+}
+
+static gboolean
+binding_signal_activate_signal (GtkBindingSignalSignal *sig,
+ GObject *object)
+{
+ GSignalQuery query;
+ guint signal_id;
+ GValue *params = NULL;
+ GValue return_val = G_VALUE_INIT;
+ gboolean handled = FALSE;
+
+ signal_id = g_signal_lookup (sig->signal_name, G_OBJECT_TYPE (object));
+ if (!signal_id)
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "could not find signal \"%s\" in the '%s' class ancestry",
+ sig->signal_name,
+ g_type_name (G_OBJECT_TYPE (object)));
+ return FALSE;
+ }
+
+ g_signal_query (signal_id, &query);
+ if (query.n_params != sig->n_args ||
+ (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
+ !binding_compose_params (object, sig->args, &query, &params))
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "signature mismatch for signal \"%s\" in the '%s' class ancestry",
+ sig->signal_name,
+ g_type_name (G_OBJECT_TYPE (object)));
+ return FALSE;
+ }
+ else if (!(query.signal_flags & G_SIGNAL_ACTION))
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "signal \"%s\" in the '%s' class ancestry cannot be used for action emissions",
+ sig->signal_name,
+ g_type_name (G_OBJECT_TYPE (object)));
+ return FALSE;
+ }
+
+ if (query.return_type == G_TYPE_BOOLEAN)
+ g_value_init (&return_val, G_TYPE_BOOLEAN);
+
+ g_signal_emitv (params, signal_id, 0, &return_val);
+
+ if (query.return_type == G_TYPE_BOOLEAN)
+ {
+ if (g_value_get_boolean (&return_val))
+ handled = TRUE;
+ g_value_unset (&return_val);
+ }
+ else
+ handled = TRUE;
+
+ if (params != NULL)
+ {
+ guint i;
+
+ for (i = 0; i < query.n_params + 1; i++)
+ g_value_unset (&params[i]);
+
+ g_free (params);
+ }
+
+ return handled;
+}
+
+static gboolean
+binding_signal_activate_action (GtkBindingSignalAction *sig,
+ GObject *object)
+{
+ if (!GTK_IS_WIDGET (object))
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "actions must be emitted on GtkWidget subtypes, %s is not supported",
+ G_OBJECT_TYPE_NAME (object));
+ return FALSE;
+ }
+
+ if (!gtk_widget_activate_action_variant (GTK_WIDGET (object), sig->action_name, sig->variant))
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "action \"%s\" does not exist on class \"%s\"",
+ sig->action_name,
+ G_OBJECT_TYPE_NAME (object));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+binding_signal_activate_callback (GtkBindingSignalCallback *sig,
+ GObject *object)
+{
+ if (!GTK_IS_WIDGET (object))
+ {
+ g_warning ("gtk_binding_entry_activate(): "
+ "callbacks must be run on GtkWidget subtypes, %s is not supported",
+ G_OBJECT_TYPE_NAME (object));
+ return FALSE;
+ }
+
+ sig->callback (GTK_WIDGET (object), sig->args, sig->user_data);
+
+ return TRUE;
+}
+
+static gboolean
+gtk_binding_entry_activate (GtkBindingEntry *entry,
+ GObject *object)
+{
+ GtkBindingSignal *sig;
+ gboolean old_emission;
+ gboolean handled = FALSE;
+
+ old_emission = entry->in_emission;
+ entry->in_emission = TRUE;
+
+ g_object_ref (object);
+
+ for (sig = entry->signals; sig; sig = sig->next)
+ {
+ switch (sig->action_type)
+ {
+ case GTK_BINDING_SIGNAL:
+ handled = binding_signal_activate_signal ((GtkBindingSignalSignal *) sig, object);
+ break;
+
+ case GTK_BINDING_ACTION:
+ handled = binding_signal_activate_action ((GtkBindingSignalAction *) sig, object);
+ break;
+
+ case GTK_BINDING_CALLBACK:
+ handled = binding_signal_activate_callback ((GtkBindingSignalCallback *) sig, object);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (entry->destroyed)
+ break;
+ }
+
+ g_object_unref (object);
+
+ entry->in_emission = old_emission;
+ if (entry->destroyed && !entry->in_emission)
+ binding_entry_free (entry);
+
+ return handled;
+}
+
+/**
+ * gtk_binding_set_new: (skip)
+ * @set_name: unique name of this binding set
+ *
+ * GTK+ maintains a global list of binding sets. Each binding set has
+ * a unique name which needs to be specified upon creation.
+ *
+ * Returns: (transfer none): new binding set
+ */
+GtkBindingSet*
+gtk_binding_set_new (const gchar *set_name)
+{
+ GtkBindingSet *binding_set;
+
+ g_return_val_if_fail (set_name != NULL, NULL);
+
+ binding_set = g_new (GtkBindingSet, 1);
+ binding_set->set_name = (gchar *) g_intern_string (set_name);
+ binding_set->entries = NULL;
+ binding_set->current = NULL;
+
+ binding_set_list = g_slist_prepend (binding_set_list, binding_set);
+
+ return binding_set;
+}
+
+/**
+ * gtk_binding_set_by_class: (skip)
+ * @object_class: a valid #GObject class
+ *
+ * This function returns the binding set named after the type name of
+ * the passed in class structure. New binding sets are created on
+ * demand by this function.
+ *
+ * Returns: (transfer none): the binding set corresponding to
+ * @object_class
+ */
+GtkBindingSet*
+gtk_binding_set_by_class (gpointer object_class)
+{
+ GObjectClass *class = object_class;
+ GtkBindingSet* binding_set;
+
+ g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
+
+ if (!key_id_class_binding_set)
+ key_id_class_binding_set = g_quark_from_static_string (key_class_binding_set);
+
+ binding_set = g_dataset_id_get_data (class, key_id_class_binding_set);
+
+ if (binding_set)
+ return binding_set;
+
+ binding_set = gtk_binding_set_new (g_type_name (G_OBJECT_CLASS_TYPE (class)));
+ g_dataset_id_set_data (class, key_id_class_binding_set, binding_set);
+
+ return binding_set;
+}
+
+static GtkBindingSet*
+gtk_binding_set_find_interned (const gchar *set_name)
+{
+ GSList *slist;
+
+ for (slist = binding_set_list; slist; slist = slist->next)
+ {
+ GtkBindingSet *binding_set;
+
+ binding_set = slist->data;
+ if (binding_set->set_name == set_name)
+ return binding_set;
+ }
+
+ return NULL;
+}
+
+/**
+ * gtk_binding_set_find:
+ * @set_name: unique binding set name
+ *
+ * Find a binding set by its globally unique name.
+ *
+ * The @set_name can either be a name used for gtk_binding_set_new()
+ * or the type name of a class used in gtk_binding_set_by_class().
+ *
+ * Returns: (nullable) (transfer none): %NULL or the specified binding set
+ */
+GtkBindingSet*
+gtk_binding_set_find (const gchar *set_name)
+{
+ g_return_val_if_fail (set_name != NULL, NULL);
+
+ return gtk_binding_set_find_interned (g_intern_string (set_name));
+}
+
+/**
+ * gtk_binding_set_activate:
+ * @binding_set: a #GtkBindingSet set to activate
+ * @keyval: key value of the binding
+ * @modifiers: key modifier of the binding
+ * @object: object to activate when binding found
+ *
+ * Find a key binding matching @keyval and @modifiers within
+ * @binding_set and activate the binding on @object.
+ *
+ * Returns: %TRUE if a binding was found and activated
+ */
+gboolean
+gtk_binding_set_activate (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GObject *object)
+{
+ GtkBindingEntry *entry;
+
+ g_return_val_if_fail (binding_set != NULL, FALSE);
+ g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
+
+ keyval = gdk_keyval_to_lower (keyval);
+ modifiers = modifiers & BINDING_MOD_MASK ();
+
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ if (entry)
+ return gtk_binding_entry_activate (entry, object);
+
+ return FALSE;
+}
+
+static void
+gtk_binding_entry_clear_internal (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GtkBindingEntry *entry;
+
+ keyval = gdk_keyval_to_lower (keyval);
+ modifiers = modifiers & BINDING_MOD_MASK ();
+
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ if (entry)
+ binding_entry_destroy (entry);
+
+ entry = binding_entry_new (binding_set, keyval, modifiers);
+}
+
+/**
+ * gtk_binding_entry_skip:
+ * @binding_set: a #GtkBindingSet to skip an entry of
+ * @keyval: key value of binding to skip
+ * @modifiers: key modifier of binding to skip
+ *
+ * Install a binding on @binding_set which causes key lookups
+ * to be aborted, to prevent bindings from lower priority sets
+ * to be activated.
+ */
+void
+gtk_binding_entry_skip (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GtkBindingEntry *entry;
+
+ g_return_if_fail (binding_set != NULL);
+
+ keyval = gdk_keyval_to_lower (keyval);
+ modifiers = modifiers & BINDING_MOD_MASK ();
+
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ if (entry)
+ binding_entry_destroy (entry);
+
+ entry = binding_entry_new (binding_set, keyval, modifiers);
+ entry->marks_unbound = TRUE;
+}
+
+/**
+ * gtk_binding_entry_remove:
+ * @binding_set: a #GtkBindingSet to remove an entry of
+ * @keyval: key value of binding to remove
+ * @modifiers: key modifier of binding to remove
+ *
+ * Remove a binding previously installed via
+ * gtk_binding_entry_add_signal() on @binding_set.
+ */
+void
+gtk_binding_entry_remove (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GtkBindingEntry *entry;
+
+ g_return_if_fail (binding_set != NULL);
+
+ keyval = gdk_keyval_to_lower (keyval);
+ modifiers = modifiers & BINDING_MOD_MASK ();
+
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ if (entry)
+ binding_entry_destroy (entry);
+}
+
+static void
+gtk_binding_entry_add_binding_signal (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GtkBindingSignal *signal)
+{
+ GtkBindingEntry *entry;
+ GtkBindingSignal **signal_p;
+
+ keyval = gdk_keyval_to_lower (keyval);
+ modifiers = modifiers & BINDING_MOD_MASK ();
+
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ if (!entry)
+ {
+ gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
+ entry = binding_ht_lookup_entry (binding_set, keyval, modifiers);
+ }
+ signal_p = &entry->signals;
+ while (*signal_p)
+ signal_p = &(*signal_p)->next;
+ *signal_p = signal;
+}
+
+/*
+ * gtk_binding_entry_add_signall:
+ * @binding_set: a #GtkBindingSet to add a signal to
+ * @keyval: key value
+ * @modifiers: key modifier
+ * @signal_name: signal name to be bound
+ * @binding_args: (transfer none) (element-type GtkBindingArg):
+ * list of #GtkBindingArg signal arguments
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set.
+ */
+static void
+gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const gchar *signal_name,
+ GSList *binding_args)
+{
+ GtkBindingSignal *signal;
+ GSList *slist;
+ guint n = 0;
+ GtkBindingArg *arg;
+
+ g_return_if_fail (binding_set != NULL);
+ g_return_if_fail (signal_name != NULL);
+
+ signal = binding_signal_new_signal (signal_name, g_slist_length (binding_args));
+
+ arg = ((GtkBindingSignalSignal *) signal)->args;
+ for (slist = binding_args; slist; slist = slist->next)
+ {
+ GtkBindingArg *tmp_arg;
+
+ tmp_arg = slist->data;
+ if (!tmp_arg)
+ {
+ g_warning ("gtk_binding_entry_add_signall(): arg[%u] is 'NULL'", n);
+ binding_signal_free (signal);
+ return;
+ }
+ switch (G_TYPE_FUNDAMENTAL (tmp_arg->arg_type))
+ {
+ case G_TYPE_LONG:
+ arg->arg_type = G_TYPE_LONG;
+ arg->d.long_data = tmp_arg->d.long_data;
+ break;
+ case G_TYPE_DOUBLE:
+ arg->arg_type = G_TYPE_DOUBLE;
+ arg->d.double_data = tmp_arg->d.double_data;
+ break;
+ case G_TYPE_STRING:
+ arg->arg_type = G_TYPE_STRING;
+ arg->d.string_data = g_strdup (tmp_arg->d.string_data);
+ if (!arg->d.string_data)
+ {
+ g_warning ("gtk_binding_entry_add_signall(): value of 'string' arg[%u] is 'NULL'", n);
+ binding_signal_free (signal);
+ return;
+ }
+ break;
+ default:
+ g_warning ("gtk_binding_entry_add_signall(): unsupported type '%s' for arg[%u]",
+ g_type_name (arg->arg_type), n);
+ binding_signal_free (signal);
+ return;
+ }
+ arg++;
+ n++;
+ }
+
+ gtk_binding_entry_add_binding_signal (binding_set, keyval, modifiers, signal);
+}
+
+/**
+ * gtk_binding_entry_add_signal:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval: key value of binding to install
+ * @modifiers: key modifier of binding to install
+ * @signal_name: signal to execute upon activation
+ * @n_args: number of arguments to @signal_name
+ * @...: arguments to @signal_name
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @signal_name will be
+ * emitted on the target widget, with @n_args @Varargs used as
+ * arguments.
+ *
+ * Each argument to the signal must be passed as a pair of varargs: the
+ * #GType of the argument, followed by the argument value (which must
+ * be of the given type). There must be @n_args pairs in total.
+ *
+ * ## Adding a Key Binding
+ *
+ * |[<!-- language="C" -->
+ * GtkBindingSet *binding_set;
+ * GdkModifierType modmask = GDK_CONTROL_MASK;
+ * int count = 1;
+ * gtk_binding_entry_add_signal (binding_set,
+ * GDK_KEY_space,
+ * modmask,
+ * "move-cursor", 2,
+ * GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_PAGES,
+ * G_TYPE_INT, count,
+ * G_TYPE_BOOLEAN, FALSE);
+ * ]|
+ */
+void
+gtk_binding_entry_add_signal (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const gchar *signal_name,
+ guint n_args,
+ ...)
+{
+ GSList *slist, *free_slist;
+ va_list args;
+ guint i;
+
+ g_return_if_fail (binding_set != NULL);
+ g_return_if_fail (signal_name != NULL);
+
+ va_start (args, n_args);
+ slist = NULL;
+ for (i = 0; i < n_args; i++)
+ {
+ GtkBindingArg *arg;
+
+ arg = g_slice_new0 (GtkBindingArg);
+ slist = g_slist_prepend (slist, arg);
+
+ arg->arg_type = va_arg (args, GType);
+ switch (G_TYPE_FUNDAMENTAL (arg->arg_type))
+ {
+ case G_TYPE_CHAR:
+ case G_TYPE_UCHAR:
+ case G_TYPE_INT:
+ case G_TYPE_UINT:
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_ENUM:
+ case G_TYPE_FLAGS:
+ arg->arg_type = G_TYPE_LONG;
+ arg->d.long_data = va_arg (args, gint);
+ break;
+ case G_TYPE_LONG:
+ case G_TYPE_ULONG:
+ arg->arg_type = G_TYPE_LONG;
+ arg->d.long_data = va_arg (args, glong);
+ break;
+ case G_TYPE_FLOAT:
+ case G_TYPE_DOUBLE:
+ arg->arg_type = G_TYPE_DOUBLE;
+ arg->d.double_data = va_arg (args, gdouble);
+ break;
+ case G_TYPE_STRING:
+ arg->arg_type = G_TYPE_STRING;
+ arg->d.string_data = va_arg (args, gchar*);
+ if (!arg->d.string_data)
+ {
+ g_warning ("gtk_binding_entry_add_signal(): type '%s' arg[%u] is 'NULL'",
+ g_type_name (arg->arg_type),
+ i);
+ i += n_args + 1;
+ }
+ break;
+ default:
+ g_warning ("gtk_binding_entry_add_signal(): unsupported type '%s' for arg[%u]",
+ g_type_name (arg->arg_type), i);
+ i += n_args + 1;
+ break;
+ }
+ }
+ va_end (args);
+
+ if (i == n_args || i == 0)
+ {
+ slist = g_slist_reverse (slist);
+ gtk_binding_entry_add_signall (binding_set, keyval, modifiers, signal_name, slist);
+ }
+
+ free_slist = slist;
+ while (slist)
+ {
+ g_slice_free (GtkBindingArg, slist->data);
+ slist = slist->next;
+ }
+ g_slist_free (free_slist);
+}
+
+/**
+ * gtk_binding_entry_add_action_variant:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval: key value of binding to install
+ * @modifiers: key modifier of binding to install
+ * @action_name: signal to execute upon activation
+ * @args: #GVariant of the arguments or %NULL if none
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @action_name will be
+ * activated on the target widget, with @args used as arguments.
+ */
+void
+gtk_binding_entry_add_action_variant (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const gchar *action_name,
+ GVariant *args)
+{
+ g_return_if_fail (binding_set != NULL);
+ g_return_if_fail (action_name != NULL);
+
+ gtk_binding_entry_add_binding_signal (binding_set,
+ keyval,
+ modifiers,
+ binding_signal_new_action (action_name, args));
+}
+
+/**
+ * gtk_binding_entry_add_action:
+ * @binding_set: a #GtkBindingSet to install an entry for
+ * @keyval: key value of binding to install
+ * @modifiers: key modifier of binding to install
+ * @action_name: signal to execute upon activation
+ * @format_string: GVariant format string for arguments or %NULL
+ * for no arguments
+ * @...: arguments, as given by format string
+ *
+ * Override or install a new key binding for @keyval with @modifiers on
+ * @binding_set. When the binding is activated, @action_name will be
+ * activated on the target widget, with arguments read according to
+ * @format_string.
+ */
+void
+gtk_binding_entry_add_action (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const char *action_name,
+ const char *format_string,
+ ...)
+{
+ GVariant *parameters = NULL;
+
+ g_return_if_fail (binding_set != NULL);
+ g_return_if_fail (action_name != NULL);
+
+ if (format_string != NULL)
+ {
+ va_list args;
+
+ va_start (args, format_string);
+ parameters = g_variant_new_va (format_string, NULL, &args);
+ va_end (args);
+
+ g_variant_ref_sink (parameters);
+ }
+
+ gtk_binding_entry_add_action_variant (binding_set, keyval, modifiers, action_name, parameters);
+
+ g_clear_pointer (&parameters, g_variant_unref);
+}
+
+void
+gtk_binding_entry_add_callback (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GtkBindingCallback callback,
+ GVariant *args,
+ gpointer user_data,
+ GDestroyNotify user_destroy)
+{
+ g_return_if_fail (binding_set != NULL);
+ g_return_if_fail (callback != NULL);
+
+ gtk_binding_entry_add_binding_signal (binding_set,
+ keyval,
+ modifiers,
+ binding_signal_new_callback (callback, args, user_data, user_destroy));
+
+}
+
+static guint
+gtk_binding_parse_signal (GScanner *scanner,
+ GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ gchar *signal;
+ guint expected_token = 0;
+ GSList *args;
+ GSList *slist;
+ gboolean done;
+ gboolean negate;
+ gboolean need_arg;
+ gboolean seen_comma;
+
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token != G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ g_scanner_peek_next_token (scanner);
+
+ if (scanner->next_token != '(')
+ {
+ g_scanner_get_next_token (scanner);
+ return '(';
+ }
+
+ signal = g_strdup (scanner->value.v_string);
+ g_scanner_get_next_token (scanner);
+
+ negate = FALSE;
+ args = NULL;
+ done = FALSE;
+ need_arg = TRUE;
+ seen_comma = FALSE;
+ scanner->config->scan_symbols = FALSE;
+
+ do
+ {
+ GtkBindingArg *arg;
+
+ if (need_arg)
+ expected_token = G_TOKEN_INT;
+ else
+ expected_token = ')';
+
+ g_scanner_get_next_token (scanner);
+
+ switch ((guint) scanner->token)
+ {
+ case G_TOKEN_FLOAT:
+ if (need_arg)
+ {
+ need_arg = FALSE;
+ arg = g_new (GtkBindingArg, 1);
+ arg->arg_type = G_TYPE_DOUBLE;
+ arg->d.double_data = scanner->value.v_float;
+
+ if (negate)
+ {
+ arg->d.double_data = - arg->d.double_data;
+ negate = FALSE;
+ }
+ args = g_slist_prepend (args, arg);
+ }
+ else
+ done = TRUE;
+
+ break;
+ case G_TOKEN_INT:
+ if (need_arg)
+ {
+ need_arg = FALSE;
+ arg = g_new (GtkBindingArg, 1);
+ arg->arg_type = G_TYPE_LONG;
+ arg->d.long_data = scanner->value.v_int;
+
+ if (negate)
+ {
+ arg->d.long_data = - arg->d.long_data;
+ negate = FALSE;
+ }
+ args = g_slist_prepend (args, arg);
+ }
+ else
+ done = TRUE;
+ break;
+ case G_TOKEN_STRING:
+ if (need_arg && !negate)
+ {
+ need_arg = FALSE;
+ arg = g_new (GtkBindingArg, 1);
+ arg->arg_type = G_TYPE_STRING;
+ arg->d.string_data = g_strdup (scanner->value.v_string);
+ args = g_slist_prepend (args, arg);
+ }
+ else
+ done = TRUE;
+
+ break;
+ case G_TOKEN_IDENTIFIER:
+ if (need_arg && !negate)
+ {
+ need_arg = FALSE;
+ arg = g_new (GtkBindingArg, 1);
+ arg->arg_type = G_TYPE_STRING;
+ arg->d.string_data = g_strdup (scanner->value.v_identifier);
+ args = g_slist_prepend (args, arg);
+ }
+ else
+ done = TRUE;
+
+ break;
+ case '-':
+ if (!need_arg)
+ done = TRUE;
+ else if (negate)
+ {
+ expected_token = G_TOKEN_INT;
+ done = TRUE;
+ }
+ else
+ negate = TRUE;
+
+ break;
+ case ',':
+ seen_comma = TRUE;
+ if (need_arg)
+ done = TRUE;
+ else
+ need_arg = TRUE;
+
+ break;
+ case ')':
+ if (!(need_arg && seen_comma) && !negate)
+ {
+ args = g_slist_reverse (args);
+ gtk_binding_entry_add_signall (binding_set,
+ keyval,
+ modifiers,
+ signal,
+ args);
+ expected_token = G_TOKEN_NONE;
+ }
+
+ done = TRUE;
+ break;
+ default:
+ done = TRUE;
+ break;
+ }
+ }
+ while (!done);
+
+ scanner->config->scan_symbols = TRUE;
+
+ for (slist = args; slist; slist = slist->next)
+ {
+ GtkBindingArg *arg;
+
+ arg = slist->data;
+
+ if (G_TYPE_FUNDAMENTAL (arg->arg_type) == G_TYPE_STRING)
+ g_free (arg->d.string_data);
+ g_free (arg);
+ }
+
+ g_slist_free (args);
+ g_free (signal);
+
+ return expected_token;
+}
+
+static inline guint
+gtk_binding_parse_bind (GScanner *scanner,
+ GtkBindingSet *binding_set)
+{
+ guint keyval = 0;
+ GdkModifierType modifiers = 0;
+ gboolean unbind = FALSE;
+
+ g_return_val_if_fail (scanner != NULL, G_TOKEN_ERROR);
+
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token != G_TOKEN_SYMBOL)
+ return G_TOKEN_SYMBOL;
+
+ if (scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND) &&
+ scanner->value.v_symbol != GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND))
+ return G_TOKEN_SYMBOL;
+
+ unbind = (scanner->value.v_symbol == GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token != (guint) G_TOKEN_STRING)
+ return G_TOKEN_STRING;
+
+ gtk_accelerator_parse (scanner->value.v_string, &keyval, &modifiers);
+ modifiers &= BINDING_MOD_MASK ();
+
+ if (keyval == 0)
+ return G_TOKEN_STRING;
+
+ if (unbind)
+ {
+ gtk_binding_entry_skip (binding_set, keyval, modifiers);
+ return G_TOKEN_NONE;
+ }
+
+ g_scanner_get_next_token (scanner);
+
+ if (scanner->token != '{')
+ return '{';
+
+ gtk_binding_entry_clear_internal (binding_set, keyval, modifiers);
+ g_scanner_peek_next_token (scanner);
+
+ while (scanner->next_token != '}')
+ {
+ guint expected_token;
+
+ if (scanner->next_token == G_TOKEN_STRING)
+ {
+ expected_token = gtk_binding_parse_signal (scanner,
+ binding_set,
+ keyval,
+ modifiers);
+ if (expected_token != G_TOKEN_NONE)
+ return expected_token;
+ }
+ else
+ {
+ g_scanner_get_next_token (scanner);
+ return '}';
+ }
+
+ g_scanner_peek_next_token (scanner);
+ }
+
+ g_scanner_get_next_token (scanner);
+
+ return G_TOKEN_NONE;
+}
+
+static GScanner *
+create_signal_scanner (void)
+{
+ GScanner *scanner;
+
+ scanner = g_scanner_new (NULL);
+ scanner->config->cset_identifier_nth = (char *) G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_";
+
+ g_scanner_scope_add_symbol (scanner, 0, "bind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_BIND));
+ g_scanner_scope_add_symbol (scanner, 0, "unbind", GUINT_TO_POINTER (GTK_BINDING_TOKEN_UNBIND));
+
+ g_scanner_set_scope (scanner, 0);
+
+ return scanner;
+}
+
+/**
+ * gtk_binding_entry_add_signal_from_string:
+ * @binding_set: a #GtkBindingSet
+ * @signal_desc: a signal description
+ *
+ * Parses a signal description from @signal_desc and incorporates
+ * it into @binding_set.
+ *
+ * Signal descriptions may either bind a key combination to
+ * one or more signals:
+ * |[
+ * bind "key" {
+ * "signalname" (param, ...)
+ * ...
+ * }
+ * ]|
+ *
+ * Or they may also unbind a key combination:
+ * |[
+ * unbind "key"
+ * ]|
+ *
+ * Key combinations must be in a format that can be parsed by
+ * gtk_accelerator_parse().
+ *
+ * Returns: %G_TOKEN_NONE if the signal was successfully parsed and added,
+ * the expected token otherwise
+ */
+GTokenType
+gtk_binding_entry_add_signal_from_string (GtkBindingSet *binding_set,
+ const gchar *signal_desc)
+{
+ static GScanner *scanner = NULL;
+ GTokenType ret;
+
+ g_return_val_if_fail (binding_set != NULL, G_TOKEN_NONE);
+ g_return_val_if_fail (signal_desc != NULL, G_TOKEN_NONE);
+
+ if (G_UNLIKELY (!scanner))
+ scanner = create_signal_scanner ();
+
+ g_scanner_input_text (scanner, signal_desc,
+ (guint) strlen (signal_desc));
+
+ ret = gtk_binding_parse_bind (scanner, binding_set);
+
+ /* Reset for next use */
+ g_scanner_set_scope (scanner, 0);
+
+ return ret;
+}
+
+static gint
+find_entry_with_binding (GtkBindingEntry *entry,
+ GtkBindingSet *binding_set)
+{
+ return (entry->binding_set == binding_set) ? 0 : 1;
+}
+
+static gboolean
+binding_activate (GtkBindingSet *binding_set,
+ GSList *entries,
+ GObject *object,
+ gboolean is_release,
+ gboolean *unbound)
+{
+ GtkBindingEntry *entry;
+ GSList *elem;
+
+ elem = g_slist_find_custom (entries, binding_set,
+ (GCompareFunc) find_entry_with_binding);
+
+ if (!elem)
+ return FALSE;
+
+ entry = elem->data;
+
+ if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
+ return FALSE;
+
+ if (entry->marks_unbound)
+ {
+ *unbound = TRUE;
+ return FALSE;
+ }
+
+ if (gtk_binding_entry_activate (entry, object))
+ return TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+gtk_bindings_activate_list (GObject *object,
+ GSList *entries,
+ gboolean is_release)
+{
+ GtkBindingSet *binding_set;
+ gboolean handled = FALSE;
+ gboolean unbound = FALSE;
+
+ if (!entries)
+ return FALSE;
+
+ if (!handled)
+ {
+ GType class_type;
+
+ class_type = G_TYPE_FROM_INSTANCE (object);
+
+ while (class_type && !handled)
+ {
+ binding_set = gtk_binding_set_find_interned (g_type_name (class_type));
+ class_type = g_type_parent (class_type);
+
+ if (!binding_set)
+ continue;
+
+ handled = binding_activate (binding_set, entries,
+ object, is_release,
+ &unbound);
+ if (unbound)
+ break;
+ }
+
+ if (unbound)
+ return FALSE;
+ }
+
+ return handled;
+}
+
+/**
+ * gtk_bindings_activate:
+ * @object: object to activate when binding found
+ * @keyval: key value of the binding
+ * @modifiers: key modifier of the binding
+ *
+ * Find a key binding matching @keyval and @modifiers and activate the
+ * binding on @object.
+ *
+ * Returns: %TRUE if a binding was found and activated
+ */
+gboolean
+gtk_bindings_activate (GObject *object,
+ guint keyval,
+ GdkModifierType modifiers)
+{
+ GSList *entries = NULL;
+ GdkDisplay *display;
+ GtkKeyHash *key_hash;
+ gboolean handled = FALSE;
+ gboolean is_release;
+
+ if (!GTK_IS_WIDGET (object))
+ return FALSE;
+
+ is_release = (modifiers & GDK_RELEASE_MASK) != 0;
+ modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
+
+ display = gtk_widget_get_display (GTK_WIDGET (object));
+ key_hash = binding_key_hash_for_keymap (gdk_display_get_keymap (display));
+
+ entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
+
+ handled = gtk_bindings_activate_list (object, entries, is_release);
+
+ g_slist_free (entries);
+
+ return handled;
+}
+
+/**
+ * gtk_bindings_activate_event:
+ * @object: a #GObject (generally must be a widget)
+ * @event: a key event
+ *
+ * Looks up key bindings for @object to find one matching
+ * @event, and if one was found, activate it.
+ *
+ * Returns: %TRUE if a matching key binding was found
+ */
+gboolean
+gtk_bindings_activate_event (GObject *object,
+ GdkEvent *event)
+{
+ GSList *entries = NULL;
+ GdkDisplay *display;
+ GtkKeyHash *key_hash;
+ gboolean handled = FALSE;
+
+ if (!GTK_IS_WIDGET (object))
+ return FALSE;
+
+ display = gtk_widget_get_display (GTK_WIDGET (object));
+ key_hash = binding_key_hash_for_keymap (gdk_display_get_keymap (display));
+
+ entries = _gtk_key_hash_lookup (key_hash,
+ gdk_key_event_get_keycode (event),
+ gdk_event_get_modifier_state (event),
+ BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
+ gdk_key_event_get_group(event));
+
+ handled = gtk_bindings_activate_list (object, entries,
+ gdk_event_get_event_type (event) == GDK_KEY_RELEASE);
+
+ g_slist_free (entries);
+
+ return handled;
+}
diff --git a/gtk/gtkbindings.h b/gtk/gtkbindings.h
new file mode 100644
index 0000000000..ef8756f6bd
--- /dev/null
+++ b/gtk/gtkbindings.h
@@ -0,0 +1,124 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * GtkBindingSet: Keybinding manager for GObjects.
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GTK+ Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __GTK_BINDINGS_H__
+#define __GTK_BINDINGS_H__
+
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gdk/gdk.h>
+#include <gtk/gtkenums.h>
+#include <gtk/gtktypes.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkBindingSet GtkBindingSet;
+
+/**
+ * GtkBindingCallback:
+ * @widget: The object to invoke the callback on
+ * @args: (allow-none): The arguments or %NULL if none
+ * @user_data: The user data passed when registering the callback
+ *
+ * Prototype of the callback function registered with
+ * gtk_binding_entry_add_callback.
+ */
+typedef void (* GtkBindingCallback) (GtkWidget *widget,
+ GVariant *args,
+ gpointer user_data);
+
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_new (const gchar *set_name);
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_by_class (gpointer object_class);
+GDK_AVAILABLE_IN_ALL
+GtkBindingSet *gtk_binding_set_find (const gchar *set_name);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bindings_activate (GObject *object,
+ guint keyval,
+ GdkModifierType modifiers);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_bindings_activate_event (GObject *object,
+ GdkEvent *event);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_binding_set_activate (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GObject *object);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_skip (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers);
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_add_signal (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const gchar *signal_name,
+ guint n_args,
+ ...);
+
+GDK_AVAILABLE_IN_ALL
+GTokenType gtk_binding_entry_add_signal_from_string
+ (GtkBindingSet *binding_set,
+ const gchar *signal_desc);
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_add_action_variant
+ (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const char *action_name,
+ GVariant *args);
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_add_action (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ const char *action_name,
+ const char *format_string,
+ ...);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_add_callback(GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers,
+ GtkBindingCallback callback,
+ GVariant *args,
+ gpointer user_data,
+ GDestroyNotify user_destroy);
+
+GDK_AVAILABLE_IN_ALL
+void gtk_binding_entry_remove (GtkBindingSet *binding_set,
+ guint keyval,
+ GdkModifierType modifiers);
+
+G_END_DECLS
+
+#endif /* __GTK_BINDINGS_H__ */
diff --git a/gtk/inspector/shortcuts.h b/gtk/gtkbindingsprivate.h
index 145cb86408..b99126119b 100644
--- a/gtk/inspector/shortcuts.h
+++ b/gtk/gtkbindingsprivate.h
@@ -1,5 +1,5 @@
-/*
- * Copyright (c) 2020 Red Hat, Inc.
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -15,17 +15,16 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _GTK_INSPECTOR_SHORTCUTS_H_
-#define _GTK_INSPECTOR_SHORTCUTS_H_
+#ifndef __GTK_BINDINGS_PRIVATE_H__
+#define __GTK_BINDINGS_PRIVATE_H__
-#include <gtk/gtkbox.h>
+#include "gtkbindings.h"
-#define GTK_TYPE_INSPECTOR_SHORTCUTS (gtk_inspector_shortcuts_get_type ())
+G_BEGIN_DECLS
-G_DECLARE_FINAL_TYPE (GtkInspectorShortcuts, gtk_inspector_shortcuts, GTK, INSPECTOR_SHORTCUTS, GtkWidget)
+guint _gtk_binding_parse_binding (GScanner *scanner);
+void _gtk_binding_reset_parsed (void);
+G_END_DECLS
-void gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *sl,
- GObject *object);
-
-#endif
+#endif /* __GTK_BINDINGS_PRIVATE_H__ */
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index a101faab5c..ba3f367ddc 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -215,20 +215,16 @@
#include "gtkbuilderprivate.h"
-#include "gdkpixbufutilsprivate.h"
#include "gtkbuildable.h"
#include "gtkbuilderscopeprivate.h"
#include "gtkdebug.h"
#include "gtkmain.h"
-#include "gtkicontheme.h"
#include "gtkintl.h"
#include "gtkprivate.h"
-#include "gtkshortcutactionprivate.h"
-#include "gtkshortcuttrigger.h"
-#include "gtktestutils.h"
#include "gtktypebuiltins.h"
#include "gtkicontheme.h"
#include "gtkiconthemeprivate.h"
+#include "gdkpixbufutilsprivate.h"
static void gtk_builder_finalize (GObject *object);
static void gtk_builder_set_property (GObject *object,
@@ -2096,29 +2092,6 @@ gtk_builder_value_from_string_type (GtkBuilder *builder,
ret = FALSE;
}
}
- else if (G_VALUE_HOLDS (value, GTK_TYPE_SHORTCUT_TRIGGER))
- {
- GtkShortcutTrigger *trigger = gtk_shortcut_trigger_parse_string (string);
-
- if (trigger)
- g_value_take_boxed (value, trigger);
- else
- {
- g_set_error (error,
- GTK_BUILDER_ERROR,
- GTK_BUILDER_ERROR_INVALID_VALUE,
- "Could not parse shortcut trigger '%s'",
- string);
- ret = FALSE;
- }
- }
- else if (G_VALUE_HOLDS (value, GTK_TYPE_SHORTCUT_ACTION))
- {
- GtkShortcutAction *action = gtk_shortcut_action_parse_builder (builder, string, error);
-
- /* Works for success and failure (NULL) case */
- g_value_take_boxed (value, action);
- }
else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
{
gchar **vector = g_strsplit (string, "\n", 0);
diff --git a/gtk/gtkcoloreditor.c b/gtk/gtkcoloreditor.c
index 9fb73fa027..6f3ac11b6d 100644
--- a/gtk/gtkcoloreditor.c
+++ b/gtk/gtkcoloreditor.c
@@ -189,44 +189,35 @@ dismiss_current_popup (GtkColorEditor *editor)
}
static void
-popup_edit (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+popup_edit (GtkWidget *widget,
+ GtkColorEditor *editor)
{
- GtkColorEditor *editor = GTK_COLOR_EDITOR (widget);
GtkWidget *popup = NULL;
GtkRoot *root;
GtkWidget *focus;
gint position;
gint s, e;
- const char *param;
-
- param = g_variant_get_string (parameters, NULL);
- if (strcmp (param, "sv") == 0)
+ if (widget == editor->priv->sv_plane)
{
popup = editor->priv->sv_popup;
focus = editor->priv->s_entry;
position = 0;
}
- else if (strcmp (param, "h") == 0)
+ else if (widget == editor->priv->h_slider)
{
popup = editor->priv->h_popup;
focus = editor->priv->h_entry;
gtk_range_get_slider_range (GTK_RANGE (editor->priv->h_slider), &s, &e);
position = (s + e) / 2;
}
- else if (strcmp (param, "a") == 0)
+ else if (widget == editor->priv->a_slider)
{
popup = editor->priv->a_popup;
focus = editor->priv->a_entry;
gtk_range_get_slider_range (GTK_RANGE (editor->priv->a_slider), &s, &e);
position = (s + e) / 2;
}
- else
- {
- g_warning ("unsupported popup_edit parameter %s", param);
- }
if (popup == editor->priv->current_popup)
dismiss_current_popup (editor);
@@ -553,12 +544,8 @@ gtk_color_editor_class_init (GtkColorEditorClass *class)
gtk_widget_class_bind_template_callback (widget_class, entry_text_changed);
gtk_widget_class_bind_template_callback (widget_class, entry_apply);
gtk_widget_class_bind_template_callback (widget_class, entry_focus_changed);
+ gtk_widget_class_bind_template_callback (widget_class, popup_edit);
gtk_widget_class_bind_template_callback (widget_class, pick_color);
-
- gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
- gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
- gtk_widget_class_install_action (widget_class, "color.edit", "s", popup_edit);
-
}
static void
diff --git a/gtk/gtkcolorplane.c b/gtk/gtkcolorplane.c
index 36a9ca6b8e..c73b9eec22 100644
--- a/gtk/gtkcolorplane.c
+++ b/gtk/gtkcolorplane.c
@@ -28,10 +28,6 @@
#include "gtksnapshot.h"
#include "gtkprivate.h"
#include "gtkeventcontrollerkey.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
struct _GtkColorPlanePrivate
{
@@ -248,11 +244,11 @@ static void
hold_action (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
- GtkWidget *plane)
+ GtkColorPlane *plane)
{
- gtk_widget_activate_action (plane,
- "color.edit",
- "s", gtk_widget_get_name (plane));
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
}
static void
@@ -348,7 +344,7 @@ static void
plane_drag_gesture_begin (GtkGestureDrag *gesture,
gdouble start_x,
gdouble start_y,
- GtkWidget *plane)
+ GtkColorPlane *plane)
{
guint button;
@@ -356,9 +352,9 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
if (button == GDK_BUTTON_SECONDARY)
{
- gtk_widget_activate_action (plane,
- "color.edit",
- "s", gtk_widget_get_name (plane));
+ gboolean handled;
+
+ g_signal_emit_by_name (plane, "popup-menu", &handled);
}
if (button != GDK_BUTTON_PRIMARY)
@@ -367,9 +363,9 @@ plane_drag_gesture_begin (GtkGestureDrag *gesture,
return;
}
- set_cross_cursor (plane, TRUE);
- update_color (GTK_COLOR_PLANE (plane), start_x, start_y);
- gtk_widget_grab_focus (plane);
+ set_cross_cursor (GTK_WIDGET (plane), TRUE);
+ update_color (plane, start_x, start_y);
+ gtk_widget_grab_focus (GTK_WIDGET (plane));
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
}
@@ -401,9 +397,6 @@ gtk_color_plane_init (GtkColorPlane *plane)
GtkEventController *controller;
GtkGesture *gesture;
AtkObject *atk_obj;
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- GtkShortcut *shortcut;
plane->priv = gtk_color_plane_get_instance_private (plane);
@@ -437,14 +430,6 @@ gtk_color_plane_init (GtkColorPlane *plane)
g_signal_connect (controller, "key-pressed",
G_CALLBACK (key_controller_key_pressed), plane);
gtk_widget_add_controller (GTK_WIDGET (plane), controller);
-
- controller = gtk_shortcut_controller_new ();
- trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
- gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
- action = gtk_action_action_new ("color.edit");
- shortcut = gtk_shortcut_new_with_arguments (trigger, action, "s", "sv");
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (plane), controller);
}
static void
diff --git a/gtk/gtkcolorscale.c b/gtk/gtkcolorscale.c
index 56d120b111..d4bc48452a 100644
--- a/gtk/gtkcolorscale.c
+++ b/gtk/gtkcolorscale.c
@@ -29,10 +29,6 @@
#include "gtkprivate.h"
#include "gtkintl.h"
#include "gtksnapshot.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
#include <math.h>
@@ -52,7 +48,7 @@ enum
static void hold_action (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
- GtkWidget *scale);
+ GtkColorScale *scale);
G_DEFINE_TYPE_WITH_PRIVATE (GtkColorScale, gtk_color_scale, GTK_TYPE_SCALE)
@@ -165,29 +161,6 @@ gtk_color_scale_init (GtkColorScale *scale)
}
static void
-scale_constructed (GObject *object)
-{
- GtkColorScale *scale = GTK_COLOR_SCALE (object);
- GtkColorScalePrivate *priv = gtk_color_scale_get_instance_private (scale);
- GtkEventController *controller;
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- GtkShortcut *shortcut;
-
- controller = gtk_shortcut_controller_new ();
- trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
- gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
- action = gtk_action_action_new ("color.edit");
- shortcut = gtk_shortcut_new_with_arguments (trigger,
- action,
- "s",
- priv->type == GTK_COLOR_SCALE_ALPHA
- ? "a" : "h");
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (scale), controller);
-}
-
-static void
scale_get_property (GObject *object,
guint prop_id,
GValue *value,
@@ -250,11 +223,11 @@ static void
hold_action (GtkGestureLongPress *gesture,
gdouble x,
gdouble y,
- GtkWidget *scale)
+ GtkColorScale *scale)
{
- gtk_widget_activate_action (scale,
- "color.edit",
- "s", gtk_widget_get_name (scale));
+ gboolean handled;
+
+ g_signal_emit_by_name (scale, "popup-menu", &handled);
}
static void
@@ -272,7 +245,6 @@ gtk_color_scale_class_init (GtkColorScaleClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
- object_class->constructed = scale_constructed;
object_class->finalize = scale_finalize;
object_class->get_property = scale_get_property;
object_class->set_property = scale_set_property;
@@ -281,7 +253,6 @@ gtk_color_scale_class_init (GtkColorScaleClass *class)
g_param_spec_int ("scale-type", P_("Scale type"), P_("Scale type"),
0, 1, 0,
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
}
void
diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c
index f68003cc69..ca6ab4d54f 100644
--- a/gtk/gtkcolorswatch.c
+++ b/gtk/gtkcolorswatch.c
@@ -348,12 +348,13 @@ gtk_color_swatch_measure (GtkWidget *widget,
*natural = MAX (*natural, min);
}
-static void
-swatch_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+
+
+static gboolean
+swatch_popup_menu (GtkWidget *widget)
{
do_popup (GTK_COLOR_SWATCH (widget));
+ return TRUE;
}
static void
@@ -479,6 +480,7 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
widget_class->measure = gtk_color_swatch_measure;
widget_class->snapshot = swatch_snapshot;
+ widget_class->popup_menu = swatch_popup_menu;
widget_class->size_allocate = swatch_size_allocate;
widget_class->state_flags_changed = swatch_state_flags_changed;
@@ -495,17 +497,6 @@ gtk_color_swatch_class_init (GtkColorSwatchClass *class)
g_param_spec_boolean ("can-drop", P_("Can Drop"), P_("Whether the swatch should accept drops"),
FALSE, GTK_PARAM_READWRITE));
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, swatch_popup_menu);
-
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
-
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_COLOR_SWATCH_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("colorswatch"));
}
diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c
index cdf69804e9..5e5bdd1c39 100644
--- a/gtk/gtkcombobox.c
+++ b/gtk/gtkcombobox.c
@@ -19,12 +19,12 @@
#include "gtkcomboboxprivate.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkcellareabox.h"
#include "gtkcelllayout.h"
#include "gtkcellrenderertext.h"
#include "gtkcellview.h"
-#include "gtkeventcontrollerkey.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkframe.h"
#include "gtkbuiltiniconprivate.h"
@@ -33,11 +33,10 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkprivate.h"
-#include "gtkshortcutcontroller.h"
#include "gtktogglebutton.h"
#include "gtktreepopoverprivate.h"
#include "gtktypebuiltins.h"
-#include "gtkwidgetprivate.h"
+#include "gtkeventcontrollerkey.h"
#include "a11y/gtkcomboboxaccessible.h"
@@ -410,6 +409,7 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
GObjectClass *object_class;
GtkContainerClass *container_class;
GtkWidgetClass *widget_class;
+ GtkBindingSet *binding_set;
container_class = (GtkContainerClass *)klass;
container_class->forall = gtk_combo_box_forall;
@@ -560,77 +560,57 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
G_TYPE_STRING, 1, G_TYPE_STRING);
/* key bindings */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Down, GDK_MOD1_MASK,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Down, GDK_MOD1_MASK,
- "popup",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Up, GDK_MOD1_MASK,
- "popdown",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Up, GDK_MOD1_MASK,
- "popdown",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "popdown",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Up, 0,
- "move-active",
- "(i)", GTK_SCROLL_STEP_UP);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Up, 0,
- "move-active",
- "(i)", GTK_SCROLL_STEP_UP);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Up, 0,
- "move-active",
- "(i)", GTK_SCROLL_PAGE_UP);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Page_Up, 0,
- "move-active",
- "(i)", GTK_SCROLL_PAGE_UP);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Home, 0,
- "move-active",
- "(i)", GTK_SCROLL_START);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Home, 0,
- "move-active",
- "(i)", GTK_SCROLL_START);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Down, 0,
- "move-active",
- "(i)", GTK_SCROLL_STEP_DOWN);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Down, 0,
- "move-active",
- "(i)", GTK_SCROLL_STEP_DOWN);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Down, 0,
- "move-active",
- "(i)", GTK_SCROLL_PAGE_DOWN);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Page_Down, 0,
- "move-active",
- "(i)", GTK_SCROLL_PAGE_DOWN);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_End, 0,
- "move-active",
- "(i)", GTK_SCROLL_END);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_End, 0,
- "move-active",
- "(i)", GTK_SCROLL_END);
+ binding_set = gtk_binding_set_by_class (widget_class);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Down, GDK_MOD1_MASK,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Down, GDK_MOD1_MASK,
+ "popup", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Up, GDK_MOD1_MASK,
+ "popdown", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Up, GDK_MOD1_MASK,
+ "popdown", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+ "popdown", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Up, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Up, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Page_Up, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Page_Up, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_UP);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Home, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_START);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Home, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_START);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Down, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Down, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_STEP_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Page_Down, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Page_Down, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_PAGE_DOWN);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_End, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_End, 0,
+ "move-active", 1,
+ GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
/* properties */
g_object_class_override_property (object_class,
@@ -846,7 +826,6 @@ gtk_combo_box_init (GtkComboBox *combo_box)
{
GtkComboBoxPrivate *priv = gtk_combo_box_get_instance_private (combo_box);
GtkEventController *controller;
- GList *controllers, *list;
priv->active = -1;
priv->active_row = NULL;
@@ -881,19 +860,6 @@ gtk_combo_box_init (GtkComboBox *combo_box)
G_CALLBACK (gtk_combo_box_scroll_controller_scroll),
combo_box);
gtk_widget_add_controller (GTK_WIDGET (combo_box), controller);
-
- controllers = gtk_widget_list_controllers (priv->popup_widget, GTK_PHASE_BUBBLE);
- for (list = controllers; list; list = list->next)
- {
- if (GTK_IS_SHORTCUT_CONTROLLER (list->data))
- {
- g_object_ref (list->data);
- gtk_widget_remove_controller (priv->popup_widget, list->data);
- gtk_widget_add_controller (priv->popup_widget, list->data);
- break;
- }
- }
- g_list_free (controllers);
}
static void
@@ -1823,7 +1789,18 @@ gtk_combo_box_menu_key (GtkEventControllerKey *key,
GdkModifierType modifiers,
GtkComboBox *combo_box)
{
- gtk_event_controller_key_forward (key, GTK_WIDGET (combo_box));
+ GtkWidget *widget;
+ GdkEvent *event;
+
+ widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (key));
+ event = gtk_get_current_event ();
+
+ if (!gtk_bindings_activate_event (G_OBJECT (widget), event))
+ {
+ gtk_event_controller_key_forward (key, GTK_WIDGET (combo_box));
+ }
+
+ gdk_event_unref (event);
return TRUE;
}
diff --git a/gtk/gtkconcatmodel.c b/gtk/gtkconcatmodel.c
deleted file mode 100644
index d96290e6f3..0000000000
--- a/gtk/gtkconcatmodel.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/*
- * SECTION:gtkconcatmodel
- * @Short_description: concatenation list model
- * @Title: GtkConcatModel
- * @See_also: #GListModel
- *
- * #GtkConcatModel is a #GListModel implementation that takes a list of list models
- * and presents them as one concatenated list.
- *
- * Node that all the types of the passed in list models must match the concat model's
- * type. If they are not, you must use a common ancestor type for the #GtkConcatModel,
- * %G_TYPE_OBJECT being the ultimate option.
- **/
-
-#include "config.h"
-
-#include "gtkconcatmodelprivate.h"
-
-struct _GtkConcatModel
-{
- GObject parent_instance;
-
- GType item_type;
- guint n_items;
-
- GList *models;
-};
-
-struct _GtkConcatModelClass
-{
- GObjectClass parent_class;
-};
-
-static GType
-gtk_concat_model_list_model_get_item_type (GListModel *list)
-{
- GtkConcatModel *self = GTK_CONCAT_MODEL (list);
-
- return self->item_type;
-}
-
-static guint
-gtk_concat_model_list_model_get_n_items (GListModel *list)
-{
- GtkConcatModel *self = GTK_CONCAT_MODEL (list);
-
- return self->n_items;
-}
-
-static gpointer
-gtk_concat_model_list_model_get_item (GListModel *list,
- guint position)
-{
- GtkConcatModel *self = GTK_CONCAT_MODEL (list);
- GList *l;
-
- /* FIXME: Use an RBTree to make this O(log N) */
- for (l = self->models; l; l = l->next)
- {
- guint n = g_list_model_get_n_items (l->data);
-
- if (position < n)
- return g_list_model_get_item (l->data, position);
-
- position -= n;
- }
-
- return NULL;
-}
-
-static void
-gtk_concat_model_list_model_init (GListModelInterface *iface)
-{
- iface->get_item_type = gtk_concat_model_list_model_get_item_type;
- iface->get_n_items = gtk_concat_model_list_model_get_n_items;
- iface->get_item = gtk_concat_model_list_model_get_item;
-}
-
-G_DEFINE_TYPE_WITH_CODE (GtkConcatModel, gtk_concat_model,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_concat_model_list_model_init))
-
-static void
-gtk_concat_model_items_changed (GListModel *model,
- guint position,
- guint removed,
- guint added,
- GtkConcatModel *self)
-{
- GList *l;
-
- for (l = self->models; l; l = l->next)
- {
- if (l->data == model)
- break;
-
- position += g_list_model_get_n_items (l->data);
- }
-
- self->n_items -= removed;
- self->n_items += added;
-
- g_list_model_items_changed (G_LIST_MODEL (self),
- position,
- removed,
- added);
-}
-
-static void
-gtk_concat_model_remove_internal (GtkConcatModel *self,
- GListModel *model,
- gboolean emit_signals)
-{
- guint n_items, position;
- GList *l;
-
- position = 0;
- for (l = self->models; l; l = l->next)
- {
- if (l->data == model)
- break;
-
- position += g_list_model_get_n_items (l->data);
- }
-
- g_return_if_fail (l != NULL);
-
- self->models = g_list_delete_link (self->models, l);
- n_items = g_list_model_get_n_items (model);
- self->n_items -= n_items;
- g_signal_handlers_disconnect_by_func (model, gtk_concat_model_items_changed, self);
- g_object_unref (model);
-
- if (n_items && emit_signals)
- g_list_model_items_changed (G_LIST_MODEL (self),
- position,
- n_items,
- 0);
-}
-
-static void
-gtk_concat_model_dispose (GObject *object)
-{
- GtkConcatModel *self = GTK_CONCAT_MODEL (object);
-
- /* FIXME: Make this work without signal emissions */
- while (self->models)
- gtk_concat_model_remove_internal (self, self->models->data, FALSE);
-
- G_OBJECT_CLASS (gtk_concat_model_parent_class)->dispose (object);
-}
-
-static void
-gtk_concat_model_class_init (GtkConcatModelClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = gtk_concat_model_dispose;
-}
-
-static void
-gtk_concat_model_init (GtkConcatModel *self)
-{
-}
-
-GtkConcatModel *
-gtk_concat_model_new (GType item_type)
-{
- GtkConcatModel *self;
-
- g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
-
- self = g_object_new (GTK_TYPE_CONCAT_MODEL, NULL);
-
- self->item_type = item_type;
-
- return self;
-}
-
-void
-gtk_concat_model_append (GtkConcatModel *self,
- GListModel *model)
-{
- guint n_items;
-
- g_return_if_fail (GTK_IS_CONCAT_MODEL (self));
- g_return_if_fail (G_IS_LIST_MODEL (model));
- g_return_if_fail (g_type_is_a (g_list_model_get_item_type (model), self->item_type));
-
- g_object_ref (model);
- g_signal_connect (model, "items-changed", G_CALLBACK (gtk_concat_model_items_changed), self);
- self->models = g_list_append (self->models, model);
- n_items = g_list_model_get_n_items (model);
- self->n_items += n_items;
-
- if (n_items)
- g_list_model_items_changed (G_LIST_MODEL (self),
- self->n_items - n_items,
- 0,
- n_items);
-}
-
-void
-gtk_concat_model_remove (GtkConcatModel *self,
- GListModel *model)
-{
- g_return_if_fail (GTK_IS_CONCAT_MODEL (self));
- g_return_if_fail (G_IS_LIST_MODEL (model));
-
- gtk_concat_model_remove_internal (self, model, TRUE);
-}
-
-GListModel *
-gtk_concat_model_get_model_for_item (GtkConcatModel *self,
- guint position)
-{
- GList *l;
-
- g_return_val_if_fail (GTK_IS_CONCAT_MODEL (self), NULL);
-
- /* FIXME: Use an RBTree to make this O(log N) */
- for (l = self->models; l; l = l->next)
- {
- guint n = g_list_model_get_n_items (l->data);
-
- if (position < n)
- return l->data;
-
- position -= n;
- }
-
- return NULL;
-}
-
diff --git a/gtk/gtkconcatmodelprivate.h b/gtk/gtkconcatmodelprivate.h
deleted file mode 100644
index 005a9f3da8..0000000000
--- a/gtk/gtkconcatmodelprivate.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_CONCAT_MODEL_H__
-#define __GTK_CONCAT_MODEL_H__
-
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_CONCAT_MODEL (gtk_concat_model_get_type ())
-#define GTK_CONCAT_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_CONCAT_MODEL, GtkConcatModel))
-#define GTK_CONCAT_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_CONCAT_MODEL, GtkConcatModelClass))
-#define GTK_IS_CONCAT_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_CONCAT_MODEL))
-#define GTK_IS_CONCAT_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_CONCAT_MODEL))
-#define GTK_CONCAT_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_CONCAT_MODEL, GtkConcatModelClass))
-
-typedef struct _GtkConcatModel GtkConcatModel;
-typedef struct _GtkConcatModelClass GtkConcatModelClass;
-
-GType gtk_concat_model_get_type (void) G_GNUC_CONST;
-
-GtkConcatModel * gtk_concat_model_new (GType item_type);
-
-void gtk_concat_model_append (GtkConcatModel *self,
- GListModel *model);
-void gtk_concat_model_remove (GtkConcatModel *self,
- GListModel *model);
-
-GListModel * gtk_concat_model_get_model_for_item (GtkConcatModel *self,
- guint position);
-
-G_END_DECLS
-
-#endif /* __GTK_CONCAT_MODEL_H__ */
diff --git a/gtk/gtkdialog.c b/gtk/gtkdialog.c
index a2cc9e15ef..bf9e412cfd 100644
--- a/gtk/gtkdialog.c
+++ b/gtk/gtkdialog.c
@@ -38,6 +38,7 @@
#include "gtkcontainerprivate.h"
#include "gtkmain.h"
#include "gtkintl.h"
+#include "gtkbindings.h"
#include "gtkprivate.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
@@ -489,6 +490,7 @@ gtk_dialog_class_init (GtkDialogClass *class)
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
GtkWindowClass *window_class;
+ GtkBindingSet *binding_set;
gobject_class = G_OBJECT_CLASS (class);
widget_class = GTK_WIDGET_CLASS (class);
@@ -563,7 +565,8 @@ gtk_dialog_class_init (GtkDialogClass *class)
-1, 1, -1,
GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT_ONLY));
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Escape, 0, "close", NULL);
+ binding_set = gtk_binding_set_by_class (class);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
/* Bind class to template
*/
diff --git a/gtk/gtkemojichooser.c b/gtk/gtkemojichooser.c
index 7d31123bf8..66594db645 100644
--- a/gtk/gtkemojichooser.c
+++ b/gtk/gtkemojichooser.c
@@ -119,39 +119,12 @@ gtk_emoji_chooser_child_focus (GtkWidget *widget,
return GTK_WIDGET_CLASS (gtk_emoji_chooser_child_parent_class)->focus (widget, direction);
}
-static void show_variations (GtkEmojiChooser *chooser,
- GtkWidget *child);
-
-static void
-gtk_emoji_chooser_child_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *paramters)
-{
- GtkWidget *chooser;
-
- chooser = gtk_widget_get_ancestor (widget, GTK_TYPE_EMOJI_CHOOSER);
-
- show_variations (GTK_EMOJI_CHOOSER (chooser), widget);
-}
-
static void
gtk_emoji_chooser_child_class_init (GtkEmojiChooserChildClass *class)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
widget_class->size_allocate = gtk_emoji_chooser_child_size_allocate;
widget_class->focus = gtk_emoji_chooser_child_focus;
-
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_emoji_chooser_child_popup_menu);
-
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
-
gtk_widget_class_set_css_name (widget_class, "emoji");
}
@@ -448,6 +421,16 @@ pressed_cb (GtkGesture *gesture,
show_variations (chooser, child);
}
+static gboolean
+popup_menu (GtkWidget *widget,
+ gpointer data)
+{
+ GtkEmojiChooser *chooser = data;
+
+ show_variations (chooser, widget);
+ return TRUE;
+}
+
static void
add_emoji (GtkWidget *box,
gboolean prepend,
@@ -505,6 +488,9 @@ add_emoji (GtkWidget *box,
if (modifier != 0)
g_object_set_data (G_OBJECT (child), "modifier", GUINT_TO_POINTER (modifier));
+ if (chooser)
+ g_signal_connect (child, "popup-menu", G_CALLBACK (popup_menu), chooser);
+
gtk_container_add (GTK_CONTAINER (child), label);
gtk_flow_box_insert (GTK_FLOW_BOX (box), child, prepend ? 0 : -1);
}
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index 13fd885acf..21f7cfe16e 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -31,6 +31,7 @@
#include "gtkentryprivate.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbutton.h"
#include "gtkcelleditable.h"
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 658be5f338..8cb42cff20 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -973,25 +973,6 @@ typedef enum
} GtkPanDirection;
/**
- * GtkShortcutScope:
- * @GTK_SHORTCUT_SCOPE_LOCAL: Shortcuts are handled inside
- * the widget the controller belongs to.
- * @GTK_SHORTCUT_SCOPE_MANAGED: Shortcuts are handled by
- * the first ancestor that is a #GtkShortcutManager
- * @GTK_SHORTCUT_SCOPE_GLOBAL: Shortcuts are handled by
- * the root widget.
- *
- * Describes where #GtkShortcuts added to a
- * #GtkShortcutController get handled.
- */
-typedef enum
-{
- GTK_SHORTCUT_SCOPE_LOCAL,
- GTK_SHORTCUT_SCOPE_MANAGED,
- GTK_SHORTCUT_SCOPE_GLOBAL
-} GtkShortcutScope;
-
-/**
* GtkPopoverConstraint:
* @GTK_POPOVER_CONSTRAINT_NONE: Don't constrain the popover position
* beyond what is imposed by the implementation
diff --git a/gtk/gtkeventcontrollerfocus.c b/gtk/gtkeventcontrollerfocus.c
index 500a09b99a..a8a6aaa296 100644
--- a/gtk/gtkeventcontrollerfocus.c
+++ b/gtk/gtkeventcontrollerfocus.c
@@ -35,6 +35,7 @@
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerprivate.h"
#include "gtkeventcontrollerfocus.h"
+#include "gtkbindings.h"
#include "gtkenums.h"
#include "gtkmain.h"
#include "gtktypebuiltins.h"
diff --git a/gtk/gtkeventcontrollerkey.c b/gtk/gtkeventcontrollerkey.c
index 62614dbf79..efb1befb58 100644
--- a/gtk/gtkeventcontrollerkey.c
+++ b/gtk/gtkeventcontrollerkey.c
@@ -35,6 +35,7 @@
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerprivate.h"
#include "gtkeventcontrollerkey.h"
+#include "gtkbindings.h"
#include "gtkenums.h"
#include "gtkmain.h"
#include "gtktypebuiltins.h"
@@ -367,6 +368,9 @@ gtk_event_controller_key_forward (GtkEventControllerKey *controller,
GTK_PHASE_BUBBLE))
return TRUE;
+ if (gtk_bindings_activate_event (G_OBJECT (widget), controller->current_event))
+ return TRUE;
+
return FALSE;
}
diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c
index ec809192e5..c2c852a134 100644
--- a/gtk/gtkfilechooserwidget.c
+++ b/gtk/gtkfilechooserwidget.c
@@ -23,6 +23,7 @@
#include "gtkfilechooserwidgetprivate.h"
#include "gtkbookmarksmanagerprivate.h"
+#include "gtkbindings.h"
#include "gtkbutton.h"
#include "gtkcelllayout.h"
#include "gtkcellrendererpixbuf.h"
@@ -84,10 +85,6 @@
#include "gtkbinlayout.h"
#include "gtkwidgetprivate.h"
#include "gtkpopovermenuprivate.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
#include <cairo-gobject.h>
@@ -1193,22 +1190,125 @@ places_sidebar_show_error_message_cb (GtkPlacesSidebar *sidebar,
}
static gboolean
-trigger_location_entry (GtkWidget *widget,
- GVariant *arguments,
- gpointer unused)
+should_trigger_location_entry (GtkFileChooserWidget *impl,
+ guint keyval,
+ GdkModifierType state,
+ const char **string)
{
- GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (widget);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+ GdkModifierType no_text_input_mask;
if (priv->operation_mode == OPERATION_MODE_SEARCH)
return FALSE;
- if (priv->action != GTK_FILE_CHOOSER_ACTION_OPEN &&
- priv->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ no_text_input_mask =
+ gtk_widget_get_modifier_mask (GTK_WIDGET (impl), GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
+
+ if (state & no_text_input_mask)
return FALSE;
- location_popup_handler (impl, g_variant_get_string (arguments, NULL));
- return TRUE;
+ switch (keyval)
+ {
+ case GDK_KEY_slash:
+ case GDK_KEY_KP_Divide:
+ *string = "/";
+ return TRUE;
+
+ case GDK_KEY_period:
+ *string = ".";
+ return TRUE;
+
+ case GDK_KEY_asciitilde:
+ *string = "~";
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+/* Handles key press events on the file list, so that we can trap Enter to
+ * activate the default button on our own. Also, checks to see if “/” has been
+ * pressed.
+ */
+static gboolean
+treeview_key_press_cb (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ gpointer data)
+{
+ GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
+ GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+ const char *string;
+
+ if (should_trigger_location_entry (impl, keyval, state, &string) &&
+ (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER))
+ {
+ location_popup_handler (impl, string);
+ return GDK_EVENT_STOP;
+ }
+
+ if ((keyval == GDK_KEY_Return ||
+ keyval == GDK_KEY_ISO_Enter ||
+ keyval == GDK_KEY_KP_Enter ||
+ keyval == GDK_KEY_space ||
+ keyval == GDK_KEY_KP_Space) &&
+ !(state & gtk_accelerator_get_default_mod_mask ()) &&
+ priv->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ gtk_widget_activate_default (GTK_WIDGET (impl));
+ return GDK_EVENT_STOP;
+ }
+
+ if (keyval == GDK_KEY_Escape &&
+ priv->operation_mode == OPERATION_MODE_SEARCH)
+ {
+ return gtk_event_controller_key_forward (controller,
+ GTK_WIDGET (gtk_search_entry_get_text_widget (GTK_SEARCH_ENTRY (priv->search_entry))));
+ }
+
+ return GDK_EVENT_PROPAGATE;
+}
+
+static gboolean
+widget_key_press_cb (GtkEventControllerKey *controller,
+ guint keyval,
+ guint keycode,
+ GdkModifierType state,
+ gpointer data)
+{
+ GtkFileChooserWidget *impl = (GtkFileChooserWidget *) data;
+ GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
+ gboolean handled = FALSE;
+ const char *string;
+
+ if (should_trigger_location_entry (impl, keyval, state, &string))
+ {
+ if (priv->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+ priv->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ {
+ location_popup_handler (impl, string);
+ handled = TRUE;
+ }
+ }
+ else
+ {
+ priv->starting_search = TRUE;
+ if (gtk_event_controller_key_forward (controller, priv->search_entry))
+ {
+ gtk_widget_grab_focus (priv->search_entry);
+
+ if (priv->operation_mode != OPERATION_MODE_SEARCH &&
+ priv->starting_search)
+ operation_mode_set (impl, OPERATION_MODE_SEARCH);
+
+ handled = TRUE;
+ }
+ }
+
+ return handled;
}
/* Callback used from gtk_tree_selection_selected_foreach(); adds a bookmark for
@@ -2032,12 +2132,11 @@ file_list_show_popover (GtkFileChooserWidget *impl,
gtk_popover_popup (GTK_POPOVER (priv->browse_files_popover));
}
+/* Callback used for the GtkWidget::popup-menu signal of the file list */
static gboolean
-list_popup_menu_cb (GtkWidget *widget,
- GVariant *args,
- gpointer user_data)
+list_popup_menu_cb (GtkWidget *widget,
+ GtkFileChooserWidget *impl)
{
- GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (user_data);
GtkFileChooserWidgetPrivate *priv = gtk_file_chooser_widget_get_instance_private (impl);
graphene_rect_t bounds;
@@ -2052,16 +2151,6 @@ list_popup_menu_cb (GtkWidget *widget,
return FALSE;
}
-static void
-files_list_clicked (GtkGesture *gesture,
- int n_press,
- double x,
- double y,
- GtkFileChooserWidget *impl)
-{
- list_popup_menu_cb (NULL, NULL, impl);
-}
-
/* Callback used when a button is pressed on the file list. We trap button 3 to
* bring up a popup menu.
*/
@@ -7372,20 +7461,18 @@ show_hidden_handler (GtkFileChooserWidget *impl)
}
static void
-add_normal_and_shifted_binding (GtkWidgetClass *widget_class,
+add_normal_and_shifted_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType modifiers,
const gchar *signal_name)
{
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modifiers,
- signal_name,
- NULL);
+ gtk_binding_entry_add_signal (binding_set,
+ keyval, modifiers,
+ signal_name, 0);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modifiers | GDK_SHIFT_MASK,
- signal_name,
- NULL);
+ gtk_binding_entry_add_signal (binding_set,
+ keyval, modifiers | GDK_SHIFT_MASK,
+ signal_name, 0);
}
static void
@@ -7396,6 +7483,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
};
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkBindingSet *binding_set;
gint i;
gobject_class->finalize = gtk_file_chooser_widget_finalize;
@@ -7676,84 +7764,71 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
NULL,
G_TYPE_NONE, 0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_l, GDK_CONTROL_MASK,
- "location-toggle-popup",
- NULL);
+ binding_set = gtk_binding_set_by_class (class);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_v, GDK_CONTROL_MASK,
- "location-popup-on-paste",
- NULL);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_l, GDK_CONTROL_MASK,
+ "location-toggle-popup",
+ 0);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_v, GDK_CONTROL_MASK,
+ "location-popup-on-paste",
+ 0);
- add_normal_and_shifted_binding (widget_class,
+ add_normal_and_shifted_binding (binding_set,
GDK_KEY_Up, GDK_MOD1_MASK,
"up-folder");
- add_normal_and_shifted_binding (widget_class,
+
+ add_normal_and_shifted_binding (binding_set,
GDK_KEY_KP_Up, GDK_MOD1_MASK,
"up-folder");
- add_normal_and_shifted_binding (widget_class,
+ add_normal_and_shifted_binding (binding_set,
GDK_KEY_Down, GDK_MOD1_MASK,
"down-folder");
- add_normal_and_shifted_binding (widget_class,
+ add_normal_and_shifted_binding (binding_set,
GDK_KEY_KP_Down, GDK_MOD1_MASK,
"down-folder");
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Home, GDK_MOD1_MASK,
- "home-folder",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Home, GDK_MOD1_MASK,
- "home-folder",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_d, GDK_MOD1_MASK,
- "desktop-folder",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_h, GDK_CONTROL_MASK,
- "show-hidden",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_s, GDK_MOD1_MASK,
- "search-shortcut",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_f, GDK_CONTROL_MASK,
- "search-shortcut",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_r, GDK_MOD1_MASK,
- "recent-shortcut",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_p, GDK_MOD1_MASK,
- "places-shortcut",
- NULL);
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_slash, 0,
- trigger_location_entry,
- "s", "/");
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_KP_Divide, 0,
- trigger_location_entry,
- "s", "/");
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_period, 0,
- trigger_location_entry,
- "s", ".");
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_asciitilde, 0,
- trigger_location_entry,
- "s", "~");
-
- for (i = 0; i < G_N_ELEMENTS (quick_bookmark_keyvals); i++)
- gtk_widget_class_add_binding_signal (widget_class,
- quick_bookmark_keyvals[i], GDK_MOD1_MASK,
- "quick-bookmark",
- "(i)", i);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Home, GDK_MOD1_MASK,
+ "home-folder",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_Home, GDK_MOD1_MASK,
+ "home-folder",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_d, GDK_MOD1_MASK,
+ "desktop-folder",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_h, GDK_CONTROL_MASK,
+ "show-hidden",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_s, GDK_MOD1_MASK,
+ "search-shortcut",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_f, GDK_CONTROL_MASK,
+ "search-shortcut",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_r, GDK_MOD1_MASK,
+ "recent-shortcut",
+ 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_p, GDK_MOD1_MASK,
+ "places-shortcut",
+ 0);
+
+ for (i = 0; i < 10; i++)
+ gtk_binding_entry_add_signal (binding_set,
+ quick_bookmark_keyvals[i], GDK_MOD1_MASK,
+ "quick-bookmark",
+ 1, G_TYPE_INT, i);
g_object_class_install_property (gobject_class, PROP_SEARCH_MODE,
g_param_spec_boolean ("search-mode",
@@ -7818,6 +7893,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_child_private (widget_class, GtkFileChooserWidget, box);
/* And a *lot* of callbacks to bind ... */
+ gtk_widget_class_bind_template_callback (widget_class, list_popup_menu_cb);
gtk_widget_class_bind_template_callback (widget_class, file_list_query_tooltip_cb);
gtk_widget_class_bind_template_callback (widget_class, list_row_activated);
gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
@@ -7837,6 +7913,8 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
gtk_widget_class_bind_template_callback (widget_class, rename_file_end);
gtk_widget_class_bind_template_callback (widget_class, click_cb);
gtk_widget_class_bind_template_callback (widget_class, long_press_cb);
+ gtk_widget_class_bind_template_callback (widget_class, treeview_key_press_cb);
+ gtk_widget_class_bind_template_callback (widget_class, widget_key_press_cb);
gtk_widget_class_set_css_name (widget_class, I_("filechooser"));
@@ -7852,11 +7930,6 @@ post_process_ui (GtkFileChooserWidget *impl)
GList *cells;
GFile *file;
GtkDropTarget *target;
- GtkGesture *gesture;
- GtkEventController *controller;
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- GtkShortcut *shortcut;
/* Setup file list treeview */
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->browse_files_tree_view));
@@ -7915,20 +7988,6 @@ post_process_ui (GtkFileChooserWidget *impl)
priv->item_actions);
gtk_search_entry_set_key_capture_widget (GTK_SEARCH_ENTRY (priv->search_entry), priv->search_entry);
-
- gesture = gtk_gesture_click_new ();
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
- g_signal_connect (gesture, "pressed", G_CALLBACK (files_list_clicked), impl);
- gtk_widget_add_controller (GTK_WIDGET (priv->browse_files_tree_view), GTK_EVENT_CONTROLLER (gesture));
-
- controller = gtk_shortcut_controller_new ();
- trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
- gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
- action = gtk_callback_action_new (list_popup_menu_cb, impl, NULL);
- shortcut = gtk_shortcut_new (trigger, action);
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (priv->browse_files_tree_view), controller);
-
}
void
diff --git a/gtk/gtkflowbox.c b/gtk/gtkflowbox.c
index afaa8c38f2..1a269e8528 100644
--- a/gtk/gtkflowbox.c
+++ b/gtk/gtkflowbox.c
@@ -78,6 +78,7 @@
#include "gtkflowbox.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkcontainerprivate.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssnodeprivate.h"
@@ -2986,7 +2987,7 @@ gtk_flow_box_focus (GtkWidget *widget,
}
static void
-gtk_flow_box_add_move_binding (GtkWidgetClass *widget_class,
+gtk_flow_box_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType modmask,
GtkMovementStep step,
@@ -2997,7 +2998,7 @@ gtk_flow_box_add_move_binding (GtkWidgetClass *widget_class,
GdkModifierType modify_mod_mask = GDK_CONTROL_MASK;
display = gdk_display_get_default ();
- if (display != NULL)
+ if (display)
{
extend_mod_mask = gdk_keymap_get_modifier_mask (gdk_display_get_keymap (display),
GDK_MODIFIER_INTENT_EXTEND_SELECTION);
@@ -3005,22 +3006,26 @@ gtk_flow_box_add_move_binding (GtkWidgetClass *widget_class,
GDK_MODIFIER_INTENT_MODIFY_SELECTION);
}
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | extend_mod_mask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | modify_mod_mask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | extend_mod_mask | modify_mod_mask,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
}
static void
@@ -3382,6 +3387,7 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GtkBindingSet *binding_set;
object_class->finalize = gtk_flow_box_finalize;
object_class->get_property = gtk_flow_box_get_property;
@@ -3658,57 +3664,50 @@ gtk_flow_box_class_init (GtkFlowBoxClass *class)
widget_class->activate_signal = signals[ACTIVATE_CURSOR_CHILD];
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Home, 0,
+ binding_set = gtk_binding_set_by_class (class);
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_End, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Up, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Down, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Right, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_Left, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- gtk_flow_box_add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+ gtk_flow_box_add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, GDK_CONTROL_MASK,
- "toggle-cursor-child",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, GDK_CONTROL_MASK,
- "toggle-cursor-child",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- "select-all",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "unselect-all",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
+ "toggle-cursor-child", 0, NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+ "toggle-cursor-child", 0, NULL);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "unselect-all", 0);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_FLOW_BOX_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("flowbox"));
diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c
index f3bb6ead98..ab9a9edced 100644
--- a/gtk/gtkiconview.c
+++ b/gtk/gtkiconview.c
@@ -21,6 +21,7 @@
#include "gtkaccessible.h"
#include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
#include "gtkcellareabox.h"
#include "gtkcellareacontext.h"
#include "gtkcelllayout.h"
@@ -234,7 +235,7 @@ static gboolean gtk_icon_view_unselect_all_internal (GtkIco
static void gtk_icon_view_update_rubberband (GtkIconView *icon_view);
static void gtk_icon_view_item_invalidate_size (GtkIconViewItem *item);
static void gtk_icon_view_invalidate_sizes (GtkIconView *icon_view);
-static void gtk_icon_view_add_move_binding (GtkWidgetClass *widget_class,
+static void gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
GtkMovementStep step,
@@ -336,9 +337,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkIconView, gtk_icon_view, GTK_TYPE_CONTAINER,
static void
gtk_icon_view_class_init (GtkIconViewClass *klass)
{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
+
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gobject_class = (GObjectClass *) klass;
+ widget_class = (GtkWidgetClass *) klass;
+ container_class = (GtkContainerClass *) klass;
gobject_class->constructed = gtk_icon_view_constructed;
gobject_class->dispose = gtk_icon_view_dispose;
@@ -805,88 +813,70 @@ gtk_icon_view_class_init (GtkIconViewClass *klass)
_gtk_marshal_BOOLEAN__ENUM_INTv);
/* Key bindings */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- "select-all",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "unselect-all",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, GDK_CONTROL_MASK,
- "toggle-cursor-item",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, GDK_CONTROL_MASK,
- "toggle-cursor-item",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, 0,
- "activate-cursor-item",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, 0,
- "activate-cursor-item",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Return, 0,
- "activate-cursor-item",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_ISO_Enter, 0,
- "activate-cursor-item",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Enter, 0,
- "activate-cursor-item",
- NULL);
-
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Up, 0,
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "unselect-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
+ "toggle-cursor-item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+ "toggle-cursor-item", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+ "activate-cursor-item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+ "activate-cursor-item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate-cursor-item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate-cursor-item", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate-cursor-item", 0);
+
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Down, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_p, GDK_CONTROL_MASK,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_n, GDK_CONTROL_MASK,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Home, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_End, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Right, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_Left, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- gtk_icon_view_add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+ gtk_icon_view_add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ICON_VIEW_ACCESSIBLE);
@@ -3415,35 +3405,35 @@ gtk_icon_view_build_items (GtkIconView *icon_view)
}
static void
-gtk_icon_view_add_move_binding (GtkWidgetClass *widget_class,
+gtk_icon_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
GtkMovementStep step,
gint count)
{
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- I_("move-cursor"),
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ I_("move-cursor"), 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, GDK_SHIFT_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
return;
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
}
static gboolean
diff --git a/gtk/gtkinfobar.c b/gtk/gtkinfobar.c
index 49c98a391d..b265373831 100644
--- a/gtk/gtkinfobar.c
+++ b/gtk/gtkinfobar.c
@@ -39,6 +39,7 @@
#include "gtklabel.h"
#include "gtkbutton.h"
#include "gtkenums.h"
+#include "gtkbindings.h"
#include "gtkdialog.h"
#include "gtkrevealer.h"
#include "gtkintl.h"
@@ -377,9 +378,14 @@ gtk_info_bar_dispose (GObject *object)
static void
gtk_info_bar_class_init (GtkInfoBarClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
+
+ object_class = G_OBJECT_CLASS (klass);
+ widget_class = GTK_WIDGET_CLASS (klass);
+ container_class = GTK_CONTAINER_CLASS (klass);
object_class->get_property = gtk_info_bar_get_property;
object_class->set_property = gtk_info_bar_set_property;
@@ -463,10 +469,9 @@ gtk_info_bar_class_init (GtkInfoBarClass *klass)
NULL,
G_TYPE_NONE, 0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "close",
- NULL);
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
gtk_widget_class_set_css_name (widget_class, I_("infobar"));
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c
index b1f12d12e7..7cd4f4856d 100644
--- a/gtk/gtklabel.c
+++ b/gtk/gtklabel.c
@@ -26,6 +26,7 @@
#include "gtklabelprivate.h"
+#include "gtkbindings.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtkcssnodeprivate.h"
@@ -41,9 +42,6 @@
#include "gtknotebook.h"
#include "gtkpango.h"
#include "gtkprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
#include "gtkshow.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
@@ -278,7 +276,7 @@ struct _GtkLabelPrivate
{
GtkLabelSelectionInfo *select_info;
GtkWidget *mnemonic_widget;
- GtkEventController *mnemonic_controller;
+ GtkWindow *mnemonic_window;
PangoAttrList *attrs;
PangoAttrList *markup_attrs;
@@ -416,6 +414,7 @@ static GParamSpec *label_props[NUM_PROPERTIES] = { NULL, };
static guint signals[LAST_SIGNAL] = { 0 };
static GQuark quark_shortcuts_connected;
+static GQuark quark_mnemonic_menu;
static GQuark quark_mnemonics_visible_connected;
static GQuark quark_gtk_signal;
static GQuark quark_link;
@@ -480,9 +479,7 @@ static void gtk_label_set_markup_internal (GtkLabel *label,
static void gtk_label_recalculate (GtkLabel *label);
static void gtk_label_root (GtkWidget *widget);
static void gtk_label_unroot (GtkWidget *widget);
-static void gtk_label_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters);
+static gboolean gtk_label_popup_menu (GtkWidget *widget);
static void gtk_label_do_popup (GtkLabel *label,
double x,
double y);
@@ -502,7 +499,9 @@ static void gtk_label_update_active_link (GtkWidget *widget,
static gboolean gtk_label_mnemonic_activate (GtkWidget *widget,
gboolean group_cycling);
-static void gtk_label_setup_mnemonic (GtkLabel *label);
+static void gtk_label_setup_mnemonic (GtkLabel *label,
+ GtkWidget *toplevel,
+ guint last_key);
static void gtk_label_buildable_interface_init (GtkBuildableIface *iface);
static gboolean gtk_label_buildable_custom_tag_start (GtkBuildable *buildable,
@@ -607,7 +606,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkLabel, gtk_label, GTK_TYPE_WIDGET,
gtk_label_buildable_interface_init))
static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
GtkMovementStep step,
@@ -615,16 +614,18 @@ add_move_binding (GtkWidgetClass *widget_class,
{
g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(iib)", step, count, FALSE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, FALSE);
/* Selection-extending version */
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | GDK_SHIFT_MASK,
- "move-cursor",
- "(iib)", step, count, TRUE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, TRUE);
}
static void
@@ -632,6 +633,7 @@ gtk_label_class_init (GtkLabelClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkBindingSet *binding_set;
gobject_class->set_property = gtk_label_set_property;
gobject_class->get_property = gtk_label_get_property;
@@ -647,6 +649,7 @@ gtk_label_class_init (GtkLabelClass *class)
widget_class->root = gtk_label_root;
widget_class->unroot = gtk_label_unroot;
widget_class->mnemonic_activate = gtk_label_mnemonic_activate;
+ widget_class->popup_menu = gtk_label_popup_menu;
widget_class->grab_focus = gtk_label_grab_focus;
widget_class->focus = gtk_label_focus;
widget_class->get_request_mode = gtk_label_get_request_mode;
@@ -1023,127 +1026,127 @@ gtk_label_class_init (GtkLabelClass *class)
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, label_props);
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_label_popup_menu);
-
/*
* Key bindings
*/
-
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
+ binding_set = gtk_binding_set_by_class (class);
/* Moving the insertion point */
- add_move_binding (widget_class, GDK_KEY_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_f, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_f, GDK_CONTROL_MASK,
GTK_MOVEMENT_LOGICAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_b, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_b, GDK_CONTROL_MASK,
GTK_MOVEMENT_LOGICAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
/* select all */
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- (GtkShortcutFunc) gtk_label_select_all,
- NULL);
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_slash, GDK_CONTROL_MASK,
- (GtkShortcutFunc) gtk_label_select_all,
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, -1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, -1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, 1,
+ G_TYPE_BOOLEAN, TRUE);
/* unselect all */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "move-cursor",
- "(iib)", GTK_MOVEMENT_PARAGRAPH_ENDS, 0, FALSE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_backslash, GDK_CONTROL_MASK,
- "move-cursor",
- "(iib)", GTK_MOVEMENT_PARAGRAPH_ENDS, 0, FALSE);
-
- add_move_binding (widget_class, GDK_KEY_f, GDK_MOD1_MASK,
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, 0,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, GTK_MOVEMENT_PARAGRAPH_ENDS,
+ G_TYPE_INT, 0,
+ G_TYPE_BOOLEAN, FALSE);
+
+ add_move_binding (binding_set, GDK_KEY_f, GDK_MOD1_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_b, GDK_MOD1_MASK,
+ add_move_binding (binding_set, GDK_KEY_b, GDK_MOD1_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, 0,
+ add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
/* copy */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_c, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Return, 0,
- "activate-current-link",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_ISO_Enter, 0,
- "activate-current-link",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Enter, 0,
- "activate-current-link",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate-current-link", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate-current-link", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate-current-link", 0);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LABEL_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("label"));
quark_shortcuts_connected = g_quark_from_static_string ("gtk-label-shortcuts-connected");
+ quark_mnemonic_menu = g_quark_from_static_string ("gtk-mnemonic-menu");
quark_mnemonics_visible_connected = g_quark_from_static_string ("gtk-label-mnemonics-visible-connected");
quark_gtk_signal = g_quark_from_static_string ("gtk-signal");
quark_link = g_quark_from_static_string ("link");
@@ -1346,6 +1349,7 @@ gtk_label_init (GtkLabel *label)
priv->attrs = NULL;
priv->mnemonic_widget = NULL;
+ priv->mnemonic_window = NULL;
priv->mnemonics_visible = FALSE;
}
@@ -1813,41 +1817,30 @@ gtk_label_mnemonic_activate (GtkWidget *widget,
}
static void
-gtk_label_setup_mnemonic (GtkLabel *label)
+gtk_label_setup_mnemonic (GtkLabel *label,
+ GtkWidget *toplevel,
+ guint last_key)
{
GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkWidget *widget = GTK_WIDGET (label);
- GtkShortcut *shortcut;
- if (priv->mnemonic_keyval == GDK_KEY_VoidSymbol)
+ if (last_key != GDK_KEY_VoidSymbol)
{
- if (priv->mnemonic_controller)
- {
- gtk_widget_remove_controller (widget, priv->mnemonic_controller);
- priv->mnemonic_controller = NULL;
- }
- return;
+ if (priv->mnemonic_window)
+ {
+ gtk_window_remove_mnemonic (priv->mnemonic_window,
+ last_key,
+ widget);
+ priv->mnemonic_window = NULL;
+ }
}
- if (priv->mnemonic_controller == NULL)
- {
- priv->mnemonic_controller = gtk_shortcut_controller_new ();
- gtk_event_controller_set_propagation_phase (priv->mnemonic_controller, GTK_PHASE_CAPTURE);
- gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (priv->mnemonic_controller), GTK_SHORTCUT_SCOPE_MANAGED);
- shortcut = gtk_shortcut_new (gtk_mnemonic_trigger_new (priv->mnemonic_keyval),
- gtk_mnemonic_action_new ());
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (priv->mnemonic_controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (label), priv->mnemonic_controller);
- g_object_unref (shortcut);
- }
- else
- {
- shortcut = g_list_model_get_item (G_LIST_MODEL (priv->mnemonic_controller), 0);
- gtk_shortcut_set_trigger (shortcut, gtk_mnemonic_trigger_new (priv->mnemonic_keyval));
- g_object_unref (shortcut);
- }
+ if (priv->mnemonic_keyval == GDK_KEY_VoidSymbol)
+ goto done;
connect_mnemonics_visible_notify (GTK_LABEL (widget));
+
+ done:;
}
static void
@@ -1890,12 +1883,13 @@ static void
gtk_label_root (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
GtkSettings *settings;
gboolean shortcuts_connected;
GTK_WIDGET_CLASS (gtk_label_parent_class)->root (widget);
- gtk_label_setup_mnemonic (label);
+ gtk_label_setup_mnemonic (label, GTK_WIDGET (gtk_widget_get_root (widget)), priv->mnemonic_keyval);
/* The PangoContext is replaced when the display changes, so clear the layouts */
gtk_label_clear_layout (GTK_LABEL (widget));
@@ -1922,8 +1916,9 @@ static void
gtk_label_unroot (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
+ GtkLabelPrivate *priv = gtk_label_get_instance_private (label);
- gtk_label_setup_mnemonic (label);
+ gtk_label_setup_mnemonic (label, NULL, priv->mnemonic_keyval);
GTK_WIDGET_CLASS (gtk_label_parent_class)->unroot (widget);
}
@@ -2171,7 +2166,7 @@ gtk_label_recalculate (GtkLabel *label)
if (keyval != priv->mnemonic_keyval)
{
- gtk_label_setup_mnemonic (label);
+ gtk_label_setup_mnemonic (label, GTK_WIDGET (gtk_widget_get_root (GTK_WIDGET (label))), keyval);
g_object_notify_by_pspec (G_OBJECT (label), label_props[PROP_MNEMONIC_KEYVAL]);
}
@@ -6071,14 +6066,13 @@ gtk_label_do_popup (GtkLabel *label,
gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
}
-static void
-gtk_label_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+static gboolean
+gtk_label_popup_menu (GtkWidget *widget)
{
GtkLabel *label = GTK_LABEL (widget);
gtk_label_do_popup (label, -1, -1);
+ return TRUE;
}
static void
diff --git a/gtk/gtklinkbutton.c b/gtk/gtklinkbutton.c
index 96831ec083..d64c3f3a83 100644
--- a/gtk/gtklinkbutton.c
+++ b/gtk/gtklinkbutton.c
@@ -123,9 +123,7 @@ static void gtk_link_button_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec);
static void gtk_link_button_clicked (GtkButton *button);
-static void gtk_link_button_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters);
+static gboolean gtk_link_button_popup_menu (GtkWidget *widget);
static gboolean gtk_link_button_query_tooltip_cb (GtkWidget *widget,
gint x,
gint y,
@@ -171,6 +169,8 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
gobject_class->get_property = gtk_link_button_get_property;
gobject_class->finalize = gtk_link_button_finalize;
+ widget_class->popup_menu = gtk_link_button_popup_menu;
+
button_class->clicked = gtk_link_button_clicked;
klass->activate_link = gtk_link_button_activate_link;
@@ -230,17 +230,6 @@ gtk_link_button_class_init (GtkLinkButtonClass *klass)
gtk_widget_class_install_action (widget_class, "clipboard.copy", NULL,
gtk_link_button_activate_clipboard_copy);
-
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_link_button_popup_menu);
-
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
}
static GMenuModel *
@@ -514,12 +503,11 @@ gtk_link_button_clicked (GtkButton *button)
g_signal_emit (button, link_signals[ACTIVATE_LINK], 0, &retval);
}
-static void
-gtk_link_button_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+static gboolean
+gtk_link_button_popup_menu (GtkWidget *widget)
{
gtk_link_button_do_popup (GTK_LINK_BUTTON (widget), -1, -1);
+ return TRUE;
}
/**
diff --git a/gtk/gtklistbox.c b/gtk/gtklistbox.c
index c5de939513..ffa4a0112c 100644
--- a/gtk/gtklistbox.c
+++ b/gtk/gtklistbox.c
@@ -21,6 +21,7 @@
#include "gtkactionhelperprivate.h"
#include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
#include "gtkbuildable.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
@@ -231,7 +232,7 @@ static GSequenceIter * gtk_list_box_get_next_visible (GtkListBo
GSequenceIter *iter);
static void gtk_list_box_apply_filter (GtkListBox *box,
GtkListBoxRow *row);
-static void gtk_list_box_add_move_binding (GtkWidgetClass *widget_class,
+static void gtk_list_box_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType modmask,
GtkMovementStep step,
@@ -435,6 +436,9 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set;
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LIST_BOX_ACCESSIBLE);
object_class->get_property = gtk_list_box_get_property;
object_class->set_property = gtk_list_box_set_property;
@@ -607,52 +611,43 @@ gtk_list_box_class_init (GtkListBoxClass *klass)
widget_class->activate_signal = signals[ACTIVATE_CURSOR_ROW];
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_Home, 0,
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_End, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_Up, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_Down, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_list_box_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+ gtk_list_box_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, GDK_CONTROL_MASK,
- "toggle-cursor-row",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, GDK_CONTROL_MASK,
- "toggle-cursor-row",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- "select-all",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "unselect-all",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK,
+ "toggle-cursor-row", 0, NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK,
+ "toggle-cursor-row", 0, NULL);
- gtk_widget_class_set_css_name (widget_class, I_("list"));
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "unselect-all", 0);
- gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_LIST_BOX_ACCESSIBLE);
+ gtk_widget_class_set_css_name (widget_class, I_("list"));
}
static void
@@ -1440,7 +1435,7 @@ gtk_list_box_set_accept_unpaired_release (GtkListBox *box,
}
static void
-gtk_list_box_add_move_binding (GtkWidgetClass *widget_class,
+gtk_list_box_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType modmask,
GtkMovementStep step,
@@ -1459,22 +1454,26 @@ gtk_list_box_add_move_binding (GtkWidgetClass *widget_class,
GDK_MODIFIER_INTENT_MODIFY_SELECTION);
}
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | extend_mod_mask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | modify_mod_mask,
- "move-cursor",
- "(ii)", step, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | extend_mod_mask | modify_mod_mask,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | extend_mod_mask | modify_mod_mask,
+ "move-cursor", 2,
+ GTK_TYPE_MOVEMENT_STEP, step,
+ G_TYPE_INT, count,
+ NULL);
}
static void
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 9fd83c07dc..bc164008bb 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -114,6 +114,7 @@
#include "gtkintl.h"
+#include "gtkaccelmapprivate.h"
#include "gtkbox.h"
#include "gtkdebug.h"
#include "gtkdropprivate.h"
@@ -662,6 +663,8 @@ do_post_parse_initialization (void)
gsk_ensure_resources ();
_gtk_ensure_resources ();
+ _gtk_accel_map_init ();
+
gtk_initialized = TRUE;
#ifdef G_OS_UNIX
@@ -1694,11 +1697,14 @@ gtk_main_do_event (GdkEvent *event)
current_events = g_list_prepend (current_events, event);
if (is_pointing_event (event))
- {
- target_widget = handle_pointing_event (event);
- }
+ target_widget = handle_pointing_event (event);
else if (is_key_event (event))
{
+ if (gdk_event_get_event_type (event) == GDK_KEY_PRESS &&
+ GTK_IS_WINDOW (target_widget) &&
+ gtk_window_activate_key (GTK_WINDOW (target_widget), event))
+ goto cleanup;
+
target_widget = handle_key_event (event);
}
else if (is_focus_event (event))
diff --git a/gtk/gtkmnemonichash.c b/gtk/gtkmnemonichash.c
new file mode 100644
index 0000000000..e6504842e1
--- /dev/null
+++ b/gtk/gtkmnemonichash.c
@@ -0,0 +1,201 @@
+/* gtkmnemonichash.c: Sets of mnemonics with cycling
+ *
+ * GTK - The GIMP Toolkit
+ * Copyright (C) 2002, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtkmnemonichash.h"
+#include "gtknative.h"
+
+struct _GtkMnemnonicHash
+{
+ GHashTable *hash;
+};
+
+
+GtkMnemonicHash *
+_gtk_mnemonic_hash_new (void)
+{
+ GtkMnemonicHash *mnemonic_hash = g_new (GtkMnemonicHash, 1);
+
+ mnemonic_hash->hash = g_hash_table_new (g_direct_hash, NULL);
+
+ return mnemonic_hash;
+}
+
+static void
+mnemonic_hash_free_foreach (gpointer key,
+ gpointer value,
+ gpointer user)
+{
+ guint keyval = GPOINTER_TO_UINT (key);
+ GSList *targets = value;
+
+ gchar *name = gtk_accelerator_name (keyval, 0);
+
+ g_warning ("mnemonic \"%s\" wasn't removed for widget (%p)",
+ name, targets->data);
+ g_free (name);
+
+ g_slist_free (targets);
+}
+
+void
+_gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash)
+{
+ g_hash_table_foreach (mnemonic_hash->hash,
+ mnemonic_hash_free_foreach,
+ NULL);
+
+ g_hash_table_destroy (mnemonic_hash->hash);
+ g_free (mnemonic_hash);
+}
+
+void
+_gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
+ guint keyval,
+ GtkWidget *target)
+{
+ gpointer key = GUINT_TO_POINTER (keyval);
+ GSList *targets, *new_targets;
+
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ targets = g_hash_table_lookup (mnemonic_hash->hash, key);
+ g_return_if_fail (g_slist_find (targets, target) == NULL);
+
+ new_targets = g_slist_append (targets, target);
+ if (new_targets != targets)
+ g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
+}
+
+void
+_gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
+ guint keyval,
+ GtkWidget *target)
+{
+ gpointer key = GUINT_TO_POINTER (keyval);
+ GSList *targets, *new_targets;
+
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ targets = g_hash_table_lookup (mnemonic_hash->hash, key);
+
+ g_return_if_fail (targets && g_slist_find (targets, target) != NULL);
+
+ new_targets = g_slist_remove (targets, target);
+ if (new_targets != targets)
+ {
+ if (new_targets == NULL)
+ g_hash_table_remove (mnemonic_hash->hash, key);
+ else
+ g_hash_table_insert (mnemonic_hash->hash, key, new_targets);
+ }
+}
+
+gboolean
+_gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
+ guint keyval)
+{
+ GSList *list, *targets;
+ GtkWidget *widget, *chosen_widget;
+ GdkSurface *surface;
+ gboolean overloaded;
+
+ targets = g_hash_table_lookup (mnemonic_hash->hash,
+ GUINT_TO_POINTER (keyval));
+ if (!targets)
+ return FALSE;
+
+ overloaded = FALSE;
+ chosen_widget = NULL;
+ for (list = targets; list; list = list->next)
+ {
+ widget = GTK_WIDGET (list->data);
+ surface = gtk_native_get_surface (gtk_widget_get_native (widget));
+
+ if (gtk_widget_is_sensitive (widget) &&
+ gtk_widget_get_mapped (widget) &&
+ surface && gdk_surface_is_viewable (surface))
+ {
+ if (chosen_widget)
+ {
+ overloaded = TRUE;
+ break;
+ }
+ else
+ chosen_widget = widget;
+ }
+ }
+
+ if (chosen_widget)
+ {
+ /* For round robin we put the activated entry on
+ * the end of the list after activation
+ */
+ targets = g_slist_remove (targets, chosen_widget);
+ targets = g_slist_append (targets, chosen_widget);
+ g_hash_table_insert (mnemonic_hash->hash,
+ GUINT_TO_POINTER (keyval),
+ targets);
+
+ return gtk_widget_mnemonic_activate (chosen_widget, overloaded);
+ }
+ return FALSE;
+}
+
+GSList *
+_gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
+ guint keyval)
+{
+ return g_hash_table_lookup (mnemonic_hash->hash, GUINT_TO_POINTER (keyval));
+}
+
+static void
+mnemonic_hash_foreach_func (gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ struct {
+ GtkMnemonicHashForeach func;
+ gpointer func_data;
+ } *info = data;
+
+ guint keyval = GPOINTER_TO_UINT (key);
+ GSList *targets = value;
+
+ (*info->func) (keyval, targets, info->func_data);
+}
+
+void
+_gtk_mnemonic_hash_foreach (GtkMnemonicHash *mnemonic_hash,
+ GtkMnemonicHashForeach func,
+ gpointer func_data)
+{
+ struct {
+ GtkMnemonicHashForeach func;
+ gpointer func_data;
+ } info;
+
+ info.func = func;
+ info.func_data = func_data;
+
+ g_hash_table_foreach (mnemonic_hash->hash,
+ mnemonic_hash_foreach_func,
+ &info);
+}
diff --git a/gtk/gtkmnemonichash.h b/gtk/gtkmnemonichash.h
new file mode 100644
index 0000000000..832b2eee39
--- /dev/null
+++ b/gtk/gtkmnemonichash.h
@@ -0,0 +1,52 @@
+/* gtkmnemonichash.h: Sets of mnemonics with cycling
+ *
+ * GTK - The GIMP Toolkit
+ * Copyright (C) 2002, Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_MNEMONIC_HASH_H__
+#define __GTK_MNEMONIC_HASH_H__
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GtkMnemnonicHash GtkMnemonicHash;
+
+typedef void (*GtkMnemonicHashForeach) (guint keyval,
+ GSList *targets,
+ gpointer data);
+
+GtkMnemonicHash *_gtk_mnemonic_hash_new (void);
+void _gtk_mnemonic_hash_free (GtkMnemonicHash *mnemonic_hash);
+void _gtk_mnemonic_hash_add (GtkMnemonicHash *mnemonic_hash,
+ guint keyval,
+ GtkWidget *target);
+void _gtk_mnemonic_hash_remove (GtkMnemonicHash *mnemonic_hash,
+ guint keyval,
+ GtkWidget *target);
+gboolean _gtk_mnemonic_hash_activate (GtkMnemonicHash *mnemonic_hash,
+ guint keyval);
+GSList * _gtk_mnemonic_hash_lookup (GtkMnemonicHash *mnemonic_hash,
+ guint keyval);
+void _gtk_mnemonic_hash_foreach (GtkMnemonicHash *mnemonic_hash,
+ GtkMnemonicHashForeach func,
+ gpointer func_data);
+
+G_END_DECLS
+
+#endif /* __GTK_MNEMONIC_HASH_H__ */
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index 49b69b28e8..25c75087ef 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -727,6 +727,7 @@ update_accel (GtkModelButton *self,
{
guint key;
GdkModifierType mods;
+ GtkAccelLabelClass *accel_class;
char *str;
if (!self->accel_label)
@@ -738,9 +739,12 @@ update_accel (GtkModelButton *self,
}
gtk_accelerator_parse (accel, &key, &mods);
- str = gtk_accelerator_get_label (key, mods);
+
+ accel_class = g_type_class_ref (GTK_TYPE_ACCEL_LABEL);
+ str = _gtk_accel_label_class_get_accelerator_label (accel_class, key, mods);
gtk_label_set_label (GTK_LABEL (self->accel_label), str);
g_free (str);
+ g_type_class_unref (accel_class);
}
else
{
diff --git a/gtk/gtkmountoperation.c b/gtk/gtkmountoperation.c
index a3debb0861..51d926c401 100644
--- a/gtk/gtkmountoperation.c
+++ b/gtk/gtkmountoperation.c
@@ -57,10 +57,6 @@
#include "gtkpopover.h"
#include "gtksnapshot.h"
#include "gdktextureprivate.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcut.h"
#include <glib/gprintf.h>
/**
@@ -1462,7 +1458,6 @@ do_popup_menu_for_process_tree_view (GtkWidget *widget,
static gboolean
on_popup_menu_for_process_tree_view (GtkWidget *widget,
- GVariant *args,
gpointer user_data)
{
GtkMountOperation *op = GTK_MOUNT_OPERATION (user_data);
@@ -1508,10 +1503,6 @@ create_show_processes_dialog (GtkMountOperation *op,
gchar *s;
gboolean use_header;
GtkGesture *gesture;
- GtkEventController *controller;
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- GtkShortcut *shortcut;
priv = op->priv;
@@ -1598,15 +1589,9 @@ create_show_processes_dialog (GtkMountOperation *op,
gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
gtk_container_add (GTK_CONTAINER (vbox), scrolled_window);
- controller = gtk_shortcut_controller_new ();
- trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
- gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
- action = gtk_callback_action_new (on_popup_menu_for_process_tree_view,
- op,
- NULL);
- shortcut = gtk_shortcut_new_with_arguments (trigger, action, "s", "sv");
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (tree_view), controller);
+ g_signal_connect (tree_view, "popup-menu",
+ G_CALLBACK (on_popup_menu_for_process_tree_view),
+ op);
gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
diff --git a/gtk/gtknotebook.c b/gtk/gtknotebook.c
index a625013109..d20342b1f2 100644
--- a/gtk/gtknotebook.c
+++ b/gtk/gtknotebook.c
@@ -27,6 +27,7 @@
#include "gtknotebook.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkboxlayout.h"
#include "gtkbuildable.h"
@@ -772,9 +773,7 @@ static void gtk_notebook_dispose (GObject *object);
/*** GtkWidget Methods ***/
static void gtk_notebook_destroy (GtkWidget *widget);
static void gtk_notebook_unmap (GtkWidget *widget);
-static void gtk_notebook_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters);
+static gboolean gtk_notebook_popup_menu (GtkWidget *widget);
static void gtk_notebook_motion (GtkEventController *controller,
double x,
double y,
@@ -936,53 +935,49 @@ G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
gtk_notebook_buildable_init))
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
+add_tab_bindings (GtkBindingSet *binding_set,
GdkModifierType modifiers,
GtkDirectionType direction)
{
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Tab, modifiers,
- "move_focus_out",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Tab, modifiers,
- "move_focus_out",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
-add_arrow_bindings (GtkWidgetClass *widget_class,
+add_arrow_bindings (GtkBindingSet *binding_set,
guint keysym,
GtkDirectionType direction)
{
guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class,
- keysym, GDK_CONTROL_MASK,
- "move_focus_out",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class,
- keypad_keysym, GDK_CONTROL_MASK,
- "move_focus_out",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move_focus_out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
-add_reorder_bindings (GtkWidgetClass *widget_class,
+add_reorder_bindings (GtkBindingSet *binding_set,
guint keysym,
GtkDirectionType direction,
gboolean move_to_last)
{
guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class,
- keysym, GDK_MOD1_MASK,
- "reorder_tab",
- "(ib)", direction, move_to_last);
- gtk_widget_class_add_binding_signal (widget_class,
- keypad_keysym, GDK_MOD1_MASK,
- "reorder_tab",
- "(ib)", direction, move_to_last);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
+ "reorder_tab", 2,
+ GTK_TYPE_DIRECTION_TYPE, direction,
+ G_TYPE_BOOLEAN, move_to_last);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
+ "reorder_tab", 2,
+ GTK_TYPE_DIRECTION_TYPE, direction,
+ G_TYPE_BOOLEAN, move_to_last);
}
static gboolean
@@ -1040,6 +1035,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GtkBindingSet *binding_set;
gobject_class->set_property = gtk_notebook_set_property;
gobject_class->get_property = gtk_notebook_get_property;
@@ -1048,6 +1044,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
widget_class->destroy = gtk_notebook_destroy;
widget_class->unmap = gtk_notebook_unmap;
+ widget_class->popup_menu = gtk_notebook_popup_menu;
widget_class->grab_notify = gtk_notebook_grab_notify;
widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
widget_class->direction_changed = gtk_notebook_direction_changed;
@@ -1311,77 +1308,67 @@ gtk_notebook_class_init (GtkNotebookClass *class)
G_TYPE_FROM_CLASS (gobject_class),
_gtk_marshal_OBJECT__OBJECTv);
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_notebook_popup_menu);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, 0,
- "select-page",
- "(b)", FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, 0,
- "select-page",
- "(b)", FALSE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Home, 0,
- "focus-tab",
- "(i)", GTK_NOTEBOOK_TAB_FIRST);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Home, 0,
- "focus-tab",
- "(i)", GTK_NOTEBOOK_TAB_FIRST);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_End, 0,
- "focus-tab",
- "(i)", GTK_NOTEBOOK_TAB_LAST);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_End, 0,
- "focus-tab",
- "(i)", GTK_NOTEBOOK_TAB_LAST);
-
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Up, GDK_CONTROL_MASK,
- "change-current-page",
- "(i)", -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Down, GDK_CONTROL_MASK,
- "change-current-page",
- "(i)", 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
- "change-current-page",
- "(i)", -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
- "change-current-page",
- "(i)", 1);
-
- add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
- add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
- add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
- add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
- add_reorder_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP, FALSE);
- add_reorder_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN, FALSE);
- add_reorder_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT, FALSE);
- add_reorder_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT, FALSE);
- add_reorder_bindings (widget_class, GDK_KEY_Home, GTK_DIR_LEFT, TRUE);
- add_reorder_bindings (widget_class, GDK_KEY_Home, GTK_DIR_UP, TRUE);
- add_reorder_bindings (widget_class, GDK_KEY_End, GTK_DIR_RIGHT, TRUE);
- add_reorder_bindings (widget_class, GDK_KEY_End, GTK_DIR_DOWN, TRUE);
-
- add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ binding_set = gtk_binding_set_by_class (class);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_space, 0,
+ "select-page", 1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_Space, 0,
+ "select-page", 1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Home, 0,
+ "focus-tab", 1,
+ GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_Home, 0,
+ "focus-tab", 1,
+ GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_End, 0,
+ "focus-tab", 1,
+ GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_End, 0,
+ "focus-tab", 1,
+ GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, 1);
+
+ add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+ add_reorder_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP, FALSE);
+ add_reorder_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN, FALSE);
+ add_reorder_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT, FALSE);
+ add_reorder_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT, FALSE);
+ add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_LEFT, TRUE);
+ add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_UP, TRUE);
+ add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_RIGHT, TRUE);
+ add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_DOWN, TRUE);
+
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_NOTEBOOK_ACCESSIBLE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
@@ -2611,16 +2598,20 @@ gtk_notebook_gesture_pressed (GtkGestureClick *gesture,
}
}
-static void
-gtk_notebook_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+
+static gboolean
+gtk_notebook_popup_menu (GtkWidget *widget)
{
GtkNotebook *notebook = GTK_NOTEBOOK (widget);
GtkNotebookPrivate *priv = notebook->priv;
if (priv->menu)
- gtk_popover_popup (GTK_POPOVER (priv->menu));
+ {
+ gtk_popover_popup (GTK_POPOVER (priv->menu));
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
diff --git a/gtk/gtkpaned.c b/gtk/gtkpaned.c
index 96c937ca13..b396957906 100644
--- a/gtk/gtkpaned.c
+++ b/gtk/gtkpaned.c
@@ -26,6 +26,7 @@
#include "gtkpaned.h"
+#include "gtkbindings.h"
#include "gtkcontainerprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcssstylepropertyprivate.h"
@@ -277,29 +278,24 @@ static guint signals[LAST_SIGNAL] = { 0 };
static GParamSpec *paned_props[LAST_PROP] = { NULL, };
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
- GdkModifierType modifiers)
+add_tab_bindings (GtkBindingSet *binding_set,
+ GdkModifierType modifiers)
{
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Tab, modifiers,
- "toggle-handle-focus",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Tab, modifiers,
- "toggle-handle-focus",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "toggle-handle-focus", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "toggle-handle-focus", 0);
}
static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType mask,
GtkScrollType scroll)
{
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, mask,
- "move-handle",
- "(i)", scroll);
+ gtk_binding_entry_add_signal (binding_set, keyval, mask,
+ "move-handle", 1,
+ GTK_TYPE_SCROLL_TYPE, scroll);
}
static void
@@ -341,9 +337,16 @@ gtk_paned_handle_contains (GtkGizmo *handle,
static void
gtk_paned_class_init (GtkPanedClass *class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkPanedClass *paned_class;
+ GtkBindingSet *binding_set;
+
+ object_class = (GObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ container_class = (GtkContainerClass *) class;
+ paned_class = (GtkPanedClass *) class;
object_class->set_property = gtk_paned_set_property;
object_class->get_property = gtk_paned_get_property;
@@ -361,12 +364,12 @@ gtk_paned_class_init (GtkPanedClass *class)
container_class->child_type = gtk_paned_child_type;
container_class->set_focus_child = gtk_paned_set_focus_child;
- class->cycle_child_focus = gtk_paned_cycle_child_focus;
- class->toggle_handle_focus = gtk_paned_toggle_handle_focus;
- class->move_handle = gtk_paned_move_handle;
- class->cycle_handle_focus = gtk_paned_cycle_handle_focus;
- class->accept_position = gtk_paned_accept_position;
- class->cancel_position = gtk_paned_cancel_position;
+ paned_class->cycle_child_focus = gtk_paned_cycle_child_focus;
+ paned_class->toggle_handle_focus = gtk_paned_toggle_handle_focus;
+ paned_class->move_handle = gtk_paned_move_handle;
+ paned_class->cycle_handle_focus = gtk_paned_cycle_handle_focus;
+ paned_class->accept_position = gtk_paned_accept_position;
+ paned_class->cancel_position = gtk_paned_cancel_position;
paned_props[PROP_POSITION] =
@@ -604,87 +607,84 @@ gtk_paned_class_init (GtkPanedClass *class)
_gtk_marshal_BOOLEAN__VOID,
G_TYPE_BOOLEAN, 0);
+ binding_set = gtk_binding_set_by_class (class);
+
/* F6 and friends */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_F6, 0,
- "cycle-child-focus",
- "(b)", FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_F6, GDK_SHIFT_MASK,
- "cycle-child-focus",
- "(b)", TRUE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_F6, 0,
+ "cycle-child-focus", 1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_F6, GDK_SHIFT_MASK,
+ "cycle-child-focus", 1,
+ G_TYPE_BOOLEAN, TRUE);
/* F8 and friends */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_F8, 0,
- "cycle-handle-focus",
- "(b)", FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_F8, GDK_SHIFT_MASK,
- "cycle-handle-focus",
- "(b)", TRUE);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_F8, 0,
+ "cycle-handle-focus", 1,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_F8, GDK_SHIFT_MASK,
+ "cycle-handle-focus", 1,
+ G_TYPE_BOOLEAN, TRUE);
- add_tab_bindings (widget_class, 0);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK);
- add_tab_bindings (widget_class, GDK_SHIFT_MASK);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
+ add_tab_bindings (binding_set, 0);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK);
/* accept and cancel positions */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "cancel-position",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Return, 0,
- "accept-position",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_ISO_Enter, 0,
- "accept-position",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Enter, 0,
- "accept-position",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, 0,
- "accept-position",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, 0,
- "accept-position",
- NULL);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Escape, 0,
+ "cancel-position", 0);
+
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Return, 0,
+ "accept-position", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_ISO_Enter, 0,
+ "accept-position", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_Enter, 0,
+ "accept-position", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_space, 0,
+ "accept-position", 0);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_KP_Space, 0,
+ "accept-position", 0);
/* move handle */
- add_move_binding (widget_class, GDK_KEY_Left, 0, GTK_SCROLL_STEP_LEFT);
- add_move_binding (widget_class, GDK_KEY_KP_Left, 0, GTK_SCROLL_STEP_LEFT);
- add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
- add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
-
- add_move_binding (widget_class, GDK_KEY_Right, 0, GTK_SCROLL_STEP_RIGHT);
- add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
- add_move_binding (widget_class, GDK_KEY_KP_Right, 0, GTK_SCROLL_STEP_RIGHT);
- add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
-
- add_move_binding (widget_class, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
- add_move_binding (widget_class, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
- add_move_binding (widget_class, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
- add_move_binding (widget_class, GDK_KEY_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
- add_move_binding (widget_class, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP);
-
- add_move_binding (widget_class, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
- add_move_binding (widget_class, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
- add_move_binding (widget_class, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
- add_move_binding (widget_class, GDK_KEY_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
- add_move_binding (widget_class, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
-
- add_move_binding (widget_class, GDK_KEY_Home, 0, GTK_SCROLL_START);
- add_move_binding (widget_class, GDK_KEY_KP_Home, 0, GTK_SCROLL_START);
- add_move_binding (widget_class, GDK_KEY_End, 0, GTK_SCROLL_END);
- add_move_binding (widget_class, GDK_KEY_KP_End, 0, GTK_SCROLL_END);
+ add_move_binding (binding_set, GDK_KEY_Left, 0, GTK_SCROLL_STEP_LEFT);
+ add_move_binding (binding_set, GDK_KEY_KP_Left, 0, GTK_SCROLL_STEP_LEFT);
+ add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+ add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_LEFT);
+
+ add_move_binding (binding_set, GDK_KEY_Right, 0, GTK_SCROLL_STEP_RIGHT);
+ add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+ add_move_binding (binding_set, GDK_KEY_KP_Right, 0, GTK_SCROLL_STEP_RIGHT);
+ add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_RIGHT);
+
+ add_move_binding (binding_set, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
+ add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+ add_move_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
+ add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_UP);
+ add_move_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+
+ add_move_binding (binding_set, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
+ add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+ add_move_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
+ add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_DOWN);
+ add_move_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, GTK_SCROLL_PAGE_RIGHT);
+
+ add_move_binding (binding_set, GDK_KEY_Home, 0, GTK_SCROLL_START);
+ add_move_binding (binding_set, GDK_KEY_KP_Home, 0, GTK_SCROLL_START);
+ add_move_binding (binding_set, GDK_KEY_End, 0, GTK_SCROLL_END);
+ add_move_binding (binding_set, GDK_KEY_KP_End, 0, GTK_SCROLL_END);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_PANED_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("paned"));
diff --git a/gtk/gtkpasswordentry.c b/gtk/gtkpasswordentry.c
index 0ed1fe043f..f39531639b 100644
--- a/gtk/gtkpasswordentry.c
+++ b/gtk/gtkpasswordentry.c
@@ -23,6 +23,7 @@
#include "gtkpasswordentry.h"
#include "gtkaccessible.h"
+#include "gtkbindings.h"
#include "gtktextprivate.h"
#include "gtkeditable.h"
#include "gtkgestureclick.h"
diff --git a/gtk/gtkplacesview.c b/gtk/gtkplacesview.c
index 61938f345c..b7b431a944 100644
--- a/gtk/gtkplacesview.c
+++ b/gtk/gtkplacesview.c
@@ -106,15 +106,7 @@ static void mount_volume (GtkPlacesView
static void on_eject_button_clicked (GtkWidget *widget,
GtkPlacesViewRow *row);
-static gboolean on_row_popup_menu (GtkWidget *widget,
- GVariant *args,
- gpointer user_data);
-
-static void click_cb (GtkGesture *gesture,
- int n_press,
- double x,
- double y,
- gpointer user_data);
+static gboolean on_row_popup_menu (GtkPlacesViewRow *row);
static void populate_servers (GtkPlacesView *view);
@@ -681,28 +673,12 @@ insert_row (GtkPlacesView *view,
gboolean is_network)
{
GtkPlacesViewPrivate *priv;
- GtkEventController *controller;
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- GtkShortcut *shortcut;
- GtkGesture *gesture;
priv = gtk_places_view_get_instance_private (view);
g_object_set_data (G_OBJECT (row), "is-network", GINT_TO_POINTER (is_network));
- controller = gtk_shortcut_controller_new ();
- trigger = gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_F10, GDK_SHIFT_MASK),
- gtk_keyval_trigger_new (GDK_KEY_Menu, 0));
- action = gtk_callback_action_new (on_row_popup_menu, row, NULL);
- shortcut = gtk_shortcut_new (trigger, action);
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_widget_add_controller (GTK_WIDGET (row), controller);
-
- gesture = gtk_gesture_click_new ();
- gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
- g_signal_connect (gesture, "pressed", G_CALLBACK (click_cb), row);
- gtk_widget_add_controller (row, GTK_EVENT_CONTROLLER (gesture));
+ g_signal_connect (row, "popup-menu", G_CALLBACK (on_row_popup_menu), row);
g_signal_connect (gtk_places_view_row_get_eject_button (GTK_PLACES_VIEW_ROW (row)),
"clicked",
@@ -1723,12 +1699,10 @@ get_menu_model (void)
return G_MENU_MODEL (menu);
}
-static gboolean
-on_row_popup_menu (GtkWidget *widget,
- GVariant *args,
- gpointer user_data)
+static void
+popup_menu (GtkPlacesViewRow *row,
+ GdkEventButton *event)
{
- GtkPlacesViewRow *row = GTK_PLACES_VIEW_ROW (widget);
GtkPlacesViewPrivate *priv;
GtkWidget *view;
GMount *mount;
@@ -1756,39 +1730,27 @@ on_row_popup_menu (GtkWidget *widget,
GMenuModel *model = get_menu_model ();
priv->popup_menu = gtk_popover_menu_new_from_model (model);
+ gtk_widget_set_parent (priv->popup_menu, GTK_WIDGET (view));
gtk_popover_set_position (GTK_POPOVER (priv->popup_menu), GTK_POS_BOTTOM);
gtk_popover_set_has_arrow (GTK_POPOVER (priv->popup_menu), FALSE);
- gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_CENTER);
+ gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_START);
g_object_unref (model);
}
- if (priv->row_for_action)
- g_object_set_data (G_OBJECT (priv->row_for_action), "menu", NULL);
-
- g_object_ref (priv->popup_menu);
- gtk_widget_unparent (priv->popup_menu);
+ gtk_widget_set_halign (priv->popup_menu, GTK_ALIGN_CENTER);
gtk_widget_set_parent (priv->popup_menu, GTK_WIDGET (row));
- g_object_unref (priv->popup_menu);
priv->row_for_action = row;
- if (priv->row_for_action)
- g_object_set_data (G_OBJECT (priv->row_for_action), "menu", priv->popup_menu);
-
gtk_popover_popup (GTK_POPOVER (priv->popup_menu));
-
- return TRUE;
}
-static void
-click_cb (GtkGesture *gesture,
- int n_press,
- double x,
- double y,
- gpointer user_data)
+static gboolean
+on_row_popup_menu (GtkPlacesViewRow *row)
{
- on_row_popup_menu (GTK_WIDGET (user_data), NULL, NULL);
+ popup_menu (row, NULL);
+ return TRUE;
}
static gboolean
diff --git a/gtk/gtkplacesviewrow.c b/gtk/gtkplacesviewrow.c
index e3deff9a84..3df575aa42 100644
--- a/gtk/gtkplacesviewrow.c
+++ b/gtk/gtkplacesviewrow.c
@@ -35,7 +35,6 @@
#include "gtkspinner.h"
#include "gtkstack.h"
#include "gtktypebuiltins.h"
-#include "gtknative.h"
#else
#include <gtk/gtk.h>
#endif
@@ -195,6 +194,18 @@ measure_available_space (GtkPlacesViewRow *row)
}
static void
+pressed_cb (GtkGesture *gesture,
+ int n_pressed,
+ double x,
+ double y,
+ GtkPlacesViewRow *row)
+{
+ gboolean menu_activated;
+
+ g_signal_emit_by_name (row, "popup-menu", &menu_activated);
+}
+
+static void
gtk_places_view_row_finalize (GObject *object)
{
GtkPlacesViewRow *self = GTK_PLACES_VIEW_ROW (object);
@@ -310,19 +321,6 @@ gtk_places_view_row_set_property (GObject *object,
}
static void
-gtk_places_view_row_size_allocate (GtkWidget *widget,
- int width,
- int height,
- int baseline)
-{
- GtkWidget *menu = GTK_WIDGET (g_object_get_data (G_OBJECT (widget), "menu"));
-
- GTK_WIDGET_CLASS (gtk_places_view_row_parent_class)->size_allocate (widget, width, height, baseline);
- if (menu)
- gtk_native_check_resize (GTK_NATIVE (menu));
-}
-
-static void
gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -332,8 +330,6 @@ gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
object_class->get_property = gtk_places_view_row_get_property;
object_class->set_property = gtk_places_view_row_set_property;
- widget_class->size_allocate = gtk_places_view_row_size_allocate;
-
properties[PROP_ICON] =
g_param_spec_object ("icon",
P_("Icon of the row"),
@@ -395,6 +391,8 @@ gtk_places_view_row_class_init (GtkPlacesViewRowClass *klass)
gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, icon_image);
gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, name_label);
gtk_widget_class_bind_template_child (widget_class, GtkPlacesViewRow, path_label);
+
+ gtk_widget_class_bind_template_callback (widget_class, pressed_cb);
}
static void
diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c
index 5644413929..ef7253d123 100644
--- a/gtk/gtkpopover.c
+++ b/gtk/gtkpopover.c
@@ -103,9 +103,11 @@
#include "gtkwidgetprivate.h"
#include "gtkeventcontrollerkey.h"
#include "gtkcssnodeprivate.h"
+#include "gtkbindings.h"
#include "gtkbinlayout.h"
#include "gtkenums.h"
#include "gtktypebuiltins.h"
+#include "gtkmnemonichash.h"
#include "gtkgizmoprivate.h"
#include "gtkintl.h"
#include "gtkprivate.h"
@@ -119,8 +121,6 @@
#include "gtkcsscolorvalueprivate.h"
#include "gtkcssnumbervalueprivate.h"
#include "gtksnapshot.h"
-#include "gtkshortcut.h"
-#include "gtkshortcuttrigger.h"
#include "gtkrender.h"
#include "gtkstylecontextprivate.h"
@@ -1445,41 +1445,37 @@ gtk_popover_remove (GtkContainer *container,
}
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
+add_tab_bindings (GtkBindingSet *binding_set,
GdkModifierType modifiers,
GtkDirectionType direction)
{
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Tab, modifiers,
- "move-focus",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Tab, modifiers,
- "move-focus",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
-add_arrow_bindings (GtkWidgetClass *widget_class,
+add_arrow_bindings (GtkBindingSet *binding_set,
guint keysym,
GtkDirectionType direction)
{
guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)",
- direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
@@ -1488,6 +1484,7 @@ gtk_popover_class_init (GtkPopoverClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set;
object_class->dispose = gtk_popover_dispose;
object_class->finalize = gtk_popover_finalize;
@@ -1566,22 +1563,24 @@ gtk_popover_class_init (GtkPopoverClass *klass)
G_TYPE_NONE,
0);
- add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
- add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
- add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
- add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
- add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
- "activate-default", NULL);
+ binding_set = gtk_binding_set_by_class (klass);
+
+ add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+ add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate-default", 0);
gtk_widget_class_set_css_name (widget_class, "popover");
}
diff --git a/gtk/gtkpopovermenu.c b/gtk/gtkpopovermenu.c
index edfbdb078c..d9779bd2f7 100644
--- a/gtk/gtkpopovermenu.c
+++ b/gtk/gtkpopovermenu.c
@@ -32,6 +32,7 @@
#include "gtkeventcontrollermotion.h"
#include "gtkmain.h"
#include "gtktypebuiltins.h"
+#include "gtkbindings.h"
#include "gtkmodelbuttonprivate.h"
#include "gtkpopovermenubar.h"
@@ -361,37 +362,37 @@ gtk_popover_menu_focus (GtkWidget *widget,
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
+add_tab_bindings (GtkBindingSet *binding_set,
GdkModifierType modifiers,
GtkDirectionType direction)
{
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Tab, modifiers,
- "move-focus",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Tab, modifiers,
- "move-focus",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
-add_arrow_bindings (GtkWidgetClass *widget_class,
+add_arrow_bindings (GtkBindingSet *binding_set,
guint keysym,
GtkDirectionType direction)
{
guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
- "move-focus",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
- "move-focus",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
@@ -407,6 +408,7 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkBindingSet *binding_set;
object_class->dispose = gtk_popover_menu_dispose;
object_class->set_property = gtk_popover_menu_set_property;
@@ -433,26 +435,28 @@ gtk_popover_menu_class_init (GtkPopoverMenuClass *klass)
G_TYPE_MENU_MODEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
- add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
- add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
- add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
- add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
- "activate-default", NULL);
+ binding_set = gtk_binding_set_by_class (klass);
+
+ add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+ add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+ "activate-default", 0);
}
/**
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c
index b204596650..7ab475d2a3 100644
--- a/gtk/gtkrange.c
+++ b/gtk/gtkrange.c
@@ -1883,6 +1883,16 @@ gtk_range_click_gesture_pressed (GtkGestureClick *gesture,
mouse_location == priv->highlight_widget)
mouse_location = priv->trough_widget;
+ if (mouse_location == priv->slider_widget &&
+ gdk_event_triggers_context_menu (event))
+ {
+ gboolean handled;
+
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+ g_signal_emit_by_name (widget, "popup-menu", &handled);
+ return;
+ }
+
if (mouse_location == priv->slider_widget)
{
/* Shift-click in the slider = fine adjustment */
diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c
index 3e6a7b78b6..dce284a57f 100644
--- a/gtk/gtkroot.c
+++ b/gtk/gtkroot.c
@@ -27,8 +27,6 @@
#include "gtkprivate.h"
#include "gtkintl.h"
-#include "gtkshortcutmanager.h"
-
/**
* SECTION:gtkroot
* @Title: GtkRoot
diff --git a/gtk/gtkscale.c b/gtk/gtkscale.c
index 9583c3ea9c..244c095251 100644
--- a/gtk/gtkscale.c
+++ b/gtk/gtkscale.c
@@ -28,6 +28,7 @@
#include "gtkscale.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtkgizmoprivate.h"
@@ -622,11 +623,10 @@ gtk_scale_size_allocate (GtkWidget *widget,
}
}
-#define add_slider_binding(binding_set, keyval, mask, scroll) \
- gtk_widget_class_add_binding_signal (widget_class, \
- keyval, mask, \
- I_("move-slider"), \
- "(i)", scroll)
+#define add_slider_binding(binding_set, keyval, mask, scroll) \
+ gtk_binding_entry_add_signal (binding_set, keyval, mask, \
+ I_("move-slider"), 1, \
+ GTK_TYPE_SCROLL_TYPE, scroll)
static void
gtk_scale_value_changed (GtkRange *range)
@@ -650,6 +650,7 @@ gtk_scale_class_init (GtkScaleClass *class)
GObjectClass *gobject_class;
GtkWidgetClass *widget_class;
GtkRangeClass *range_class;
+ GtkBindingSet *binding_set;
gobject_class = G_OBJECT_CLASS (class);
range_class = (GtkRangeClass*) class;
@@ -705,6 +706,8 @@ gtk_scale_class_init (GtkScaleClass *class)
* blind users etc. don't care about scale orientation.
*/
+ binding_set = gtk_binding_set_by_class (class);
+
add_slider_binding (binding_set, GDK_KEY_Left, 0,
GTK_SCROLL_STEP_LEFT);
diff --git a/gtk/gtkscalebutton.c b/gtk/gtkscalebutton.c
index 76c2173d49..3b41e6a64c 100644
--- a/gtk/gtkscalebutton.c
+++ b/gtk/gtkscalebutton.c
@@ -37,6 +37,7 @@
#include "gtkscalebutton.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbuttonprivate.h"
#include "gtkimage.h"
@@ -170,6 +171,7 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkButtonClass *button_class = GTK_BUTTON_CLASS (klass);
+ GtkBindingSet *binding_set;
gobject_class->constructed = gtk_scale_button_constructed;
gobject_class->finalize = gtk_scale_button_finalize;
@@ -296,30 +298,20 @@ gtk_scale_button_class_init (GtkScaleButtonClass *klass)
G_TYPE_NONE, 0);
/* Key bindings */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_space, 0,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Space, 0,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Return, 0,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_ISO_Enter, 0,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Enter, 0,
- "popup",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "popdown",
- NULL);
+ binding_set = gtk_binding_set_by_class (widget_class);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "popup", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+ "popdown", 0);
/* Bind class to template
*/
diff --git a/gtk/gtkscrollbar.c b/gtk/gtkscrollbar.c
index f97d3d7647..432000ae5f 100644
--- a/gtk/gtkscrollbar.c
+++ b/gtk/gtkscrollbar.c
@@ -209,6 +209,16 @@ gtk_scrollbar_class_init (GtkScrollbarClass *class)
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
}
+static gboolean
+emit_popup_menu (GtkWidget *self)
+{
+ gboolean handled;
+
+ g_signal_emit_by_name (self, "popup-menu", &handled);
+
+ return handled;
+}
+
static void
gtk_scrollbar_init (GtkScrollbar *self)
{
@@ -217,6 +227,7 @@ gtk_scrollbar_init (GtkScrollbar *self)
priv->orientation = GTK_ORIENTATION_HORIZONTAL;
priv->range = g_object_new (GTK_TYPE_RANGE, NULL);
+ g_signal_connect_swapped (priv->range, "popup-menu", G_CALLBACK (emit_popup_menu), self);
gtk_widget_set_hexpand (priv->range, TRUE);
gtk_widget_set_vexpand (priv->range, TRUE);
gtk_widget_set_parent (priv->range, GTK_WIDGET (self));
diff --git a/gtk/gtkscrolledwindow.c b/gtk/gtkscrolledwindow.c
index 3bb8d023b8..6debc150ae 100644
--- a/gtk/gtkscrolledwindow.c
+++ b/gtk/gtkscrolledwindow.c
@@ -28,6 +28,7 @@
#include "gtkadjustment.h"
#include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
#include "gtkeventcontrollermotion.h"
#include "gtkeventcontrollerscroll.h"
#include "gtkgesturedrag.h"
@@ -412,7 +413,7 @@ static GParamSpec *properties[NUM_PROPERTIES];
G_DEFINE_TYPE_WITH_PRIVATE (GtkScrolledWindow, gtk_scrolled_window, GTK_TYPE_BIN)
static void
-add_scroll_binding (GtkWidgetClass *widget_class,
+add_scroll_binding (GtkBindingSet *binding_set,
guint keyval,
GdkModifierType mask,
GtkScrollType scroll,
@@ -420,29 +421,27 @@ add_scroll_binding (GtkWidgetClass *widget_class,
{
guint keypad_keyval = keyval - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, mask,
- "scroll-child",
- "(ib)", scroll, horizontal);
- gtk_widget_class_add_binding_signal (widget_class,
- keypad_keyval, mask,
- "scroll-child",
- "(ib)", scroll, horizontal);
+ gtk_binding_entry_add_signal (binding_set, keyval, mask,
+ "scroll-child", 2,
+ GTK_TYPE_SCROLL_TYPE, scroll,
+ G_TYPE_BOOLEAN, horizontal);
+ gtk_binding_entry_add_signal (binding_set, keypad_keyval, mask,
+ "scroll-child", 2,
+ GTK_TYPE_SCROLL_TYPE, scroll,
+ G_TYPE_BOOLEAN, horizontal);
}
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
+add_tab_bindings (GtkBindingSet *binding_set,
GdkModifierType modifiers,
GtkDirectionType direction)
{
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Tab, modifiers,
- "move-focus-out",
- "(i)", direction);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Tab, modifiers,
- "move-focus-out",
- "(i)", direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move-focus-out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move-focus-out", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
@@ -518,6 +517,7 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GtkBindingSet *binding_set;
gobject_class->set_property = gtk_scrolled_window_set_property;
gobject_class->get_property = gtk_scrolled_window_get_property;
@@ -789,23 +789,25 @@ gtk_scrolled_window_class_init (GtkScrolledWindowClass *class)
NULL, NULL, NULL,
G_TYPE_NONE, 1, GTK_TYPE_POSITION_TYPE);
- add_scroll_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE);
- add_scroll_binding (widget_class, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, FALSE);
+ binding_set = gtk_binding_set_by_class (class);
- add_scroll_binding (widget_class, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_BACKWARD, FALSE);
- add_scroll_binding (widget_class, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_FORWARD, FALSE);
+ add_scroll_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK, GTK_SCROLL_STEP_BACKWARD, FALSE);
+ add_scroll_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK, GTK_SCROLL_STEP_FORWARD, FALSE);
- add_scroll_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END, TRUE);
- add_scroll_binding (widget_class, GDK_KEY_Home, 0, GTK_SCROLL_START, FALSE);
- add_scroll_binding (widget_class, GDK_KEY_End, 0, GTK_SCROLL_END, FALSE);
+ add_scroll_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_BACKWARD, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_PAGE_FORWARD, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_BACKWARD, FALSE);
+ add_scroll_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_FORWARD, FALSE);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ add_scroll_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END, TRUE);
+ add_scroll_binding (binding_set, GDK_KEY_Home, 0, GTK_SCROLL_START, FALSE);
+ add_scroll_binding (binding_set, GDK_KEY_End, 0, GTK_SCROLL_END, FALSE);
+
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SCROLLED_WINDOW_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("scrolledwindow"));
diff --git a/gtk/gtksearchentry.c b/gtk/gtksearchentry.c
index 5d92aeebba..535aaf946a 100644
--- a/gtk/gtksearchentry.c
+++ b/gtk/gtksearchentry.c
@@ -30,6 +30,7 @@
#include "gtksearchentryprivate.h"
#include "gtkaccessible.h"
+#include "gtkbindings.h"
#include "gtkeditable.h"
#include "gtkboxlayout.h"
#include "gtkgestureclick.h"
@@ -266,6 +267,7 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GtkBindingSet *binding_set;
object_class->finalize = gtk_search_entry_finalize;
object_class->get_property = gtk_search_entry_get_property;
@@ -399,18 +401,14 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
NULL,
G_TYPE_NONE, 0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_g, GDK_CONTROL_MASK,
- "next-match",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_g, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "previous-match",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "stop-search",
- NULL);
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_CONTROL_MASK,
+ "next-match", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_g, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "previous-match", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0,
+ "stop-search", 0);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
diff --git a/gtk/gtkshortcut.c b/gtk/gtkshortcut.c
deleted file mode 100644
index 6a7ff1a148..0000000000
--- a/gtk/gtkshortcut.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#include "config.h"
-
-#include "gtkshortcut.h"
-
-#include "gtkintl.h"
-#include "gtkshortcutaction.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkwidget.h"
-
-/**
- * SECTION:gtkshortcut
- * @title: GtkShortcut
- * @short_description: An object describing a keyboard shortcut
- * @see_also: #GtkShortcutController, #GtkShortcutAction,
- * #GtkShortcutTrigger
- *
- * GtkShortcut is the low level object used for managing keyboard
- * shortcuts.
- *
- * It contains a description of how to trigger the shortcut via a
- * #GtkShortcutTrigger and a way to activate the shortcut on a widget
- * via #GtkShortcutAction.
- *
- * The actual work is usually done via #GtkShortcutController, which
- * decides if and when to activate a shortcut. Using that controller
- * directly however is rarely necessary as various higher level
- * convenience APIs exist on #GtkWidgets that make it easier to use
- * shortcuts in GTK.
- *
- * #GtkShortcut does provide functionality to make it easy for users
- * to work with shortcuts, either by providing informational strings
- * for display purposes or by allowing shortcuts to be configured.
- */
-
-struct _GtkShortcut
-{
- GObject parent_instance;
-
- GtkShortcutAction *action;
- GtkShortcutTrigger *trigger;
- GVariant *args;
-};
-
-enum
-{
- PROP_0,
- PROP_ACTION,
- PROP_ARGUMENTS,
- PROP_TRIGGER,
-
- N_PROPS
-};
-
-G_DEFINE_TYPE (GtkShortcut, gtk_shortcut, G_TYPE_OBJECT)
-
-static GParamSpec *properties[N_PROPS] = { NULL, };
-
-static void
-gtk_shortcut_dispose (GObject *object)
-{
- GtkShortcut *self = GTK_SHORTCUT (object);
-
- g_clear_pointer (&self->action, gtk_shortcut_action_unref);
- g_clear_pointer (&self->trigger, gtk_shortcut_trigger_unref);
- g_clear_pointer (&self->args, g_variant_unref);
-
- G_OBJECT_CLASS (gtk_shortcut_parent_class)->dispose (object);
-}
-
-static void
-gtk_shortcut_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkShortcut *self = GTK_SHORTCUT (object);
-
- switch (property_id)
- {
- case PROP_ACTION:
- g_value_set_boxed (value, self->action);
- break;
-
- case PROP_ARGUMENTS:
- g_value_set_variant (value, self->args);
- break;
-
- case PROP_TRIGGER:
- g_value_set_boxed (value, self->trigger);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gtk_shortcut_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkShortcut *self = GTK_SHORTCUT (object);
-
- switch (property_id)
- {
- case PROP_ACTION:
- gtk_shortcut_set_action (self, g_value_dup_boxed (value));
- break;
-
- case PROP_ARGUMENTS:
- gtk_shortcut_set_arguments (self, g_value_get_variant (value));
- break;
-
- case PROP_TRIGGER:
- gtk_shortcut_set_trigger (self, g_value_dup_boxed (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gtk_shortcut_class_init (GtkShortcutClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->dispose = gtk_shortcut_dispose;
- gobject_class->get_property = gtk_shortcut_get_property;
- gobject_class->set_property = gtk_shortcut_set_property;
-
- /**
- * GtkShortcut:action:
- *
- * The action that gets activated by this shortcut.
- */
- properties[PROP_ACTION] =
- g_param_spec_boxed ("action",
- P_("Action"),
- P_("The action activated by this shortcut"),
- GTK_TYPE_SHORTCUT_ACTION,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- /**
- * GtkShortcut:arguments:
- *
- * Arguments passed to activation.
- */
- properties[PROP_ARGUMENTS] =
- g_param_spec_variant ("arguments",
- P_("Arguments"),
- P_("Arguments passed to activation"),
- G_VARIANT_TYPE_ANY,
- NULL,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- /**
- * GtkShortcut:trigger:
- *
- * The trigger that triggers this shortcut.
- */
- properties[PROP_TRIGGER] =
- g_param_spec_boxed ("trigger",
- P_("Trigger"),
- P_("The trigger for this shortcut"),
- GTK_TYPE_SHORTCUT_TRIGGER,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (gobject_class, N_PROPS, properties);
-}
-
-static void
-gtk_shortcut_init (GtkShortcut *self)
-{
- self->action = gtk_nothing_action_new ();
- self->trigger = gtk_shortcut_trigger_ref (gtk_never_trigger_get ());
-}
-
-/**
- * gtk_shortcut_new:
- * @trigger: (transfer full) (allow-none): The trigger that will trigger the shortcut
- * @action: (transfer full) (allow-none): The action that will be activated upon
- * triggering
- *
- * Creates a new #GtkShortcut that is triggered by @trigger and then activates
- * @action.
- *
- * Returns: a new #GtkShortcut
- **/
-GtkShortcut *
-gtk_shortcut_new (GtkShortcutTrigger *trigger,
- GtkShortcutAction *action)
-{
- GtkShortcut *shortcut;
-
- shortcut = g_object_new (GTK_TYPE_SHORTCUT,
- "action", action,
- "trigger", trigger,
- NULL);
-
- if (trigger)
- gtk_shortcut_trigger_unref (trigger);
- if (action)
- gtk_shortcut_action_unref (action);
-
- return shortcut;
-}
-
-/**
- * gtk_shortcut_new_with_arguments: (skip)
- * @trigger: (transfer full) (allow-none): The trigger that will trigger the shortcut
- * @action: (transfer full) (allow-none): The action that will be activated upon
- * triggering
- * @format_string: (allow-none): GVariant format string for arguments or %NULL for
- * no arguments
- * @...: arguments, as given by format string.
- *
- * Creates a new #GtkShortcut that is triggered by @trigger and then activates
- * @action with arguments given by @format_string.
- *
- * Returns: a new #GtkShortcut
- **/
-GtkShortcut *
-gtk_shortcut_new_with_arguments (GtkShortcutTrigger *trigger,
- GtkShortcutAction *action,
- const gchar *format_string,
- ...)
-{
- GtkShortcut *shortcut;
- GVariant *args;
-
- if (format_string)
- {
- va_list valist;
- va_start (valist, format_string);
- args = g_variant_new_va (format_string, NULL, &valist);
- va_end (valist);
- }
- else
- {
- args = NULL;
- }
-
- shortcut = g_object_new (GTK_TYPE_SHORTCUT,
- "action", action,
- "arguments", args,
- "trigger", trigger,
- NULL);
-
- if (trigger)
- gtk_shortcut_trigger_unref (trigger);
- if (action)
- gtk_shortcut_action_unref (action);
-
- return shortcut;
-}
-
-/**
- * gtk_shortcut_get_action:
- * @self: a #GtkShortcut
- *
- * Gets the action that is activated by this shortcut.
- *
- * Returns: (transfer none): the action
- **/
-GtkShortcutAction *
-gtk_shortcut_get_action (GtkShortcut *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
- return self->action;
-}
-
-/**
- * gtk_shortcut_set_action:
- * @self: a #GtkShortcut
- * @action: (transfer full) (nullable): The new action.
- * If the @action is %NULL, the nothing action will be used.
- *
- * Sets the new action for @self to be @action.
- **/
-void
-gtk_shortcut_set_action (GtkShortcut *self,
- GtkShortcutAction *action)
-{
- g_return_if_fail (GTK_IS_SHORTCUT (self));
-
- if (action == NULL)
- action = gtk_nothing_action_new ();
-
- if (self->action == action)
- {
- gtk_shortcut_action_unref (action);
- return;
- }
-
- gtk_shortcut_action_unref (self->action);
- self->action = action;
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTION]);
-}
-
-/**
- * gtk_shortcut_get_trigger:
- * @self: a #GtkShortcut
- *
- * Gets the trigger used to trigger @self.
- *
- * Returns: (transfer none): the trigger used
- **/
-GtkShortcutTrigger *
-gtk_shortcut_get_trigger (GtkShortcut *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
- return self->trigger;
-}
-
-/**
- * gtk_shortcut_set_trigger:
- * @self: a #GtkShortcut
- * @trigger: (transfer full) (nullable): The new trigger.
- * If the @trigger is %NULL, the never trigger will be used.
- *
- * Sets the new trigger for @self to be @trigger.
- **/
-void
-gtk_shortcut_set_trigger (GtkShortcut *self,
- GtkShortcutTrigger *trigger)
-{
- g_return_if_fail (GTK_IS_SHORTCUT (self));
-
- if (trigger == NULL)
- trigger = gtk_shortcut_trigger_ref (gtk_never_trigger_get ());
-
- if (self->trigger == trigger)
- {
- gtk_shortcut_trigger_unref (trigger);
- return;
- }
-
- gtk_shortcut_trigger_unref (self->trigger);
- self->trigger = trigger;
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TRIGGER]);
-}
-
-GVariant *
-gtk_shortcut_get_arguments (GtkShortcut *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT (self), NULL);
-
- return self->args;
-}
-
-void
-gtk_shortcut_set_arguments (GtkShortcut *self,
- GVariant *args)
-{
- g_return_if_fail (GTK_IS_SHORTCUT (self));
-
- if (self->args == args)
- return;
-
- g_clear_pointer (&self->args, g_variant_unref);
- if (args)
- self->args = g_variant_ref_sink (args);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ARGUMENTS]);
-}
diff --git a/gtk/gtkshortcut.h b/gtk/gtkshortcut.h
deleted file mode 100644
index 77c89754a2..0000000000
--- a/gtk/gtkshortcut.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_H__
-#define __GTK_SHORTCUT_H__
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT (gtk_shortcut_get_type ())
-
-GDK_AVAILABLE_IN_ALL
-G_DECLARE_FINAL_TYPE (GtkShortcut, gtk_shortcut, GTK, SHORTCUT, GObject)
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcut * gtk_shortcut_new (GtkShortcutTrigger *trigger,
- GtkShortcutAction *action);
-GDK_AVAILABLE_IN_ALL
-GtkShortcut * gtk_shortcut_new_with_arguments (GtkShortcutTrigger *trigger,
- GtkShortcutAction *action,
- const gchar *format_string,
- ...);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger *
- gtk_shortcut_get_trigger (GtkShortcut *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_set_trigger (GtkShortcut *self,
- GtkShortcutTrigger *trigger);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction *
- gtk_shortcut_get_action (GtkShortcut *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_set_action (GtkShortcut *self,
- GtkShortcutAction *action);
-
-GDK_AVAILABLE_IN_ALL
-GVariant * gtk_shortcut_get_arguments (GtkShortcut *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_set_arguments (GtkShortcut *self,
- GVariant *args);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_H__ */
diff --git a/gtk/gtkshortcutaction.c b/gtk/gtkshortcutaction.c
deleted file mode 100644
index 86f59e7809..0000000000
--- a/gtk/gtkshortcutaction.c
+++ /dev/null
@@ -1,1134 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-/**
- * SECTION:gtkshortcutaction
- * @Title: GtkShortcutAction
- * @Short_description: Tracking if shortcuts should be activated
- * @See_also: #GtkShortcut
- *
- * #GtkShortcutAction is the object used to track if a #GtkShortcut should be
- * activated. For this purpose, gtk_shortcut_action_action() can be called
- * on a #GdkEvent.
- *
- * #GtkShortcutActions contain functions that allow easy presentation to end
- * users as well as being printed for debugging.
- *
- * All #GtkShortcutActions are immutable, you can only specify their properties
- * during construction. If you want to change a action, you have to replace it
- * with a new one.
- */
-
-#include "config.h"
-
-#include "gtkshortcutactionprivate.h"
-
-#include "gtkbuilder.h"
-#include "gtkwidgetprivate.h"
-
-typedef struct _GtkShortcutActionClass GtkShortcutActionClass;
-
-#define GTK_IS_SHORTCUT_ACTION_TYPE(action,type) (GTK_IS_SHORTCUT_ACTION (action) && (action)->action_class->action_type == (type))
-
-struct _GtkShortcutAction
-{
- const GtkShortcutActionClass *action_class;
-
- gatomicrefcount ref_count;
-};
-
-struct _GtkShortcutActionClass
-{
- GtkShortcutActionType action_type;
- gsize struct_size;
- const char *type_name;
-
- void (* finalize) (GtkShortcutAction *action);
- gboolean (* activate) (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args);
- void (* print) (GtkShortcutAction *action,
- GString *string);
-};
-
-G_DEFINE_BOXED_TYPE (GtkShortcutAction, gtk_shortcut_action,
- gtk_shortcut_action_ref,
- gtk_shortcut_action_unref)
-
-static void
-gtk_shortcut_action_finalize (GtkShortcutAction *self)
-{
- self->action_class->finalize (self);
-
- g_free (self);
-}
-
-/*< private >
- * gtk_shortcut_action_new:
- * @action_class: class structure for this action
- *
- * Returns: (transfer full): the newly created #GtkShortcutAction
- */
-static GtkShortcutAction *
-gtk_shortcut_action_new (const GtkShortcutActionClass *action_class)
-{
- GtkShortcutAction *self;
-
- g_return_val_if_fail (action_class != NULL, NULL);
-
- self = g_malloc0 (action_class->struct_size);
- g_atomic_ref_count_init (&self->ref_count);
-
- self->action_class = action_class;
-
- return self;
-}
-
-/**
- * gtk_shortcut_action_ref:
- * @self: a #GtkShortcutAction
- *
- * Acquires a reference on the given #GtkShortcutAction.
- *
- * Returns: (transfer full): the #GtkShortcutAction with an additional reference
- */
-GtkShortcutAction *
-gtk_shortcut_action_ref (GtkShortcutAction *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), NULL);
-
- g_atomic_ref_count_inc (&self->ref_count);
-
- return self;
-}
-
-/**
- * gtk_shortcut_action_unref:
- * @self: (transfer full): a #GtkShortcutAction
- *
- * Releases a reference on the given #GtkShortcutAction.
- *
- * If the reference was the last, the resources associated to the @action are
- * freed.
- */
-void
-gtk_shortcut_action_unref (GtkShortcutAction *self)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_ACTION (self));
-
- if (g_atomic_ref_count_dec (&self->ref_count))
- gtk_shortcut_action_finalize (self);
-}
-
-/**
- * gtk_shortcut_action_get_action_type:
- * @self: a #GtkShortcutAction
- *
- * Returns the type of the @action.
- *
- * Returns: the type of the #GtkShortcutAction
- */
-GtkShortcutActionType
-gtk_shortcut_action_get_action_type (GtkShortcutAction *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), GTK_SHORTCUT_ACTION_NOTHING);
-
- return self->action_class->action_type;
-}
-
-/**
- * gtk_shortcut_action_to_string:
- * @self: a #GtkShortcutAction
- *
- * Prints the given action into a human-readable string.
- * This is a small wrapper around gtk_shortcut_action_print() to help
- * when debugging.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_action_to_string (GtkShortcutAction *self)
-{
- GString *string;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), NULL);
-
- string = g_string_new (NULL);
- gtk_shortcut_action_print (self, string);
-
- return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_action_print:
- * @self: a #GtkShortcutAction
- * @string: a #GString to print into
- *
- * Prints the given action into a string for the developer.
- * This is meant for debugging and logging.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- **/
-void
-gtk_shortcut_action_print (GtkShortcutAction *self,
- GString *string)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_ACTION (self));
- g_return_if_fail (string != NULL);
-
- return self->action_class->print (self, string);
-}
-
-/**
- * gtk_shortcut_action_activate:
- * @self: a #GtkShortcutAction
- * @flags: flags to activate with
- * @widget: Target of the activation
- * @args: (allow-none): arguments to pass
- *
- * Activates the action on the @widget with the given @args.
- *
- * Note that some actions do ignore the passed in @flags, @widget or
- * @args.
- *
- * Activation of an action can fail for various reasons. If the action
- * is not supported by the @widget, if the @args don't match the action
- * or if the activation otherwise had no effect, %FALSE will be returned.
- *
- * Returns: %TRUE if this action was activated successfully
- **/
-gboolean
-gtk_shortcut_action_activate (GtkShortcutAction *self,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION (self), FALSE);
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
-
- return self->action_class->activate (self, flags, widget, args);
-}
-
-static char *
-string_is_function (const char *string,
- const char *function_name)
-{
- gsize len;
-
- if (!g_str_has_prefix (string, function_name))
- return NULL;
- string += strlen (function_name);
-
- if (string[0] != '(')
- return NULL;
- string ++;
-
- len = strlen (string);
- if (len == 0 || string[len - 1] != ')')
- return NULL;
-
- return g_strndup (string, len - 1);
-}
-
-GtkShortcutAction *
-gtk_shortcut_action_parse_builder (GtkBuilder *builder,
- const char *string,
- GError **error)
-{
- GtkShortcutAction *result;
- char *arg;
-
- if (g_str_equal (string, "nothing"))
- return gtk_nothing_action_new ();
- if (g_str_equal (string, "activate"))
- return gtk_activate_action_new ();
- if (g_str_equal (string, "mnemonic-activate"))
- return gtk_mnemonic_action_new ();
-
- if ((arg = string_is_function (string, "action")))
- {
- result = gtk_action_action_new (arg);
- g_free (arg);
- }
- else if ((arg = string_is_function (string, "signal")))
- {
- result = gtk_signal_action_new (arg);
- g_free (arg);
- }
- else if ((arg = string_is_function (string, "gaction")))
- {
- GObject *object = gtk_builder_get_object (builder, arg);
-
- if (object == NULL)
- {
- g_set_error (error,
- GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_ID,
- "Action with ID \"%s\" not found", arg);
- g_free (arg);
- return NULL;
- }
- else if (!G_IS_ACTION (object))
- {
- g_set_error (error,
- GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_ID,
- "Object with ID \"%s\" is not a GAction", arg);
- g_free (arg);
- return NULL;
- }
-
- result = gtk_gaction_action_new (G_ACTION (object));
- g_free (arg);
- }
- else
- {
- g_set_error (error,
- GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
- "String \"%s\" does not specify a GtkShortcutAction", string);
- return NULL;
- }
-
- return result;
-}
-
-/*** GTK_SHORTCUT_ACTION_NOTHING ***/
-
-typedef struct _GtkNothingAction GtkNothingAction;
-
-struct _GtkNothingAction
-{
- GtkShortcutAction action;
-};
-
-static void
-gtk_nothing_action_finalize (GtkShortcutAction *action)
-{
- g_assert_not_reached ();
-}
-
-static gboolean
-gtk_nothing_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- return FALSE;
-}
-
-static void
-gtk_nothing_action_print (GtkShortcutAction *action,
- GString *string)
-{
- g_string_append (string, "nothing");
-}
-
-static const GtkShortcutActionClass GTK_NOTHING_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_NOTHING,
- sizeof (GtkNothingAction),
- "GtkNothingAction",
- gtk_nothing_action_finalize,
- gtk_nothing_action_activate,
- gtk_nothing_action_print
-};
-
-static GtkNothingAction nothing = { { &GTK_NOTHING_ACTION_CLASS, 1 } };
-
-/**
- * gtk_nothing_action_new:
- *
- * Gets the nothing action. This is an action that does nothing and where
- * activating it always fails.
- *
- * Returns: The nothing action
- */
-GtkShortcutAction *
-gtk_nothing_action_new (void)
-{
- return gtk_shortcut_action_ref (&nothing.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_CALLBACK ***/
-
-typedef struct _GtkCallbackAction GtkCallbackAction;
-
-struct _GtkCallbackAction
-{
- GtkShortcutAction action;
-
- GtkShortcutFunc callback;
- gpointer user_data;
- GDestroyNotify destroy_notify;
-};
-
-static void
-gtk_callback_action_finalize (GtkShortcutAction *action)
-{
- GtkCallbackAction *self = (GtkCallbackAction *) action;
-
- if (self->destroy_notify)
- self->destroy_notify (self->user_data);
-}
-
-static gboolean
-gtk_callback_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- GtkCallbackAction *self = (GtkCallbackAction *) action;
-
- return self->callback (widget, args, self->user_data);
-}
-
-static void
-gtk_callback_action_print (GtkShortcutAction *action,
- GString *string)
-{
- GtkCallbackAction *self = (GtkCallbackAction *) action;
-
- g_string_append_printf (string, "callback(%p)", self->callback);
-}
-
-static const GtkShortcutActionClass GTK_CALLBACK_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_CALLBACK,
- sizeof (GtkCallbackAction),
- "GtkCallbackAction",
- gtk_callback_action_finalize,
- gtk_callback_action_activate,
- gtk_callback_action_print
-};
-
-/**
- * gtk_callback_action_new:
- * @callback: the callback to call
- * @data:
- * @destroy:
- *
- * Create a custom action that calls the given @callback when
- * activated.
- *
- * Returns: A new shortcut action
- **/
-GtkShortcutAction *
-gtk_callback_action_new (GtkShortcutFunc callback,
- gpointer data,
- GDestroyNotify destroy)
-{
- GtkCallbackAction *self;
-
- g_return_val_if_fail (callback != NULL, NULL);
-
- self = (GtkCallbackAction *) gtk_shortcut_action_new (&GTK_CALLBACK_ACTION_CLASS);
-
- self->callback = callback;
- self->user_data = data;
- self->destroy_notify = destroy;
-
- return &self->action;
-}
-
-/*** GTK_SHORTCUT_ACTION_ACTIVATE ***/
-
-typedef struct _GtkActivateAction GtkActivateAction;
-
-struct _GtkActivateAction
-{
- GtkShortcutAction action;
-};
-
-static void
-gtk_activate_action_finalize (GtkShortcutAction *action)
-{
- g_assert_not_reached ();
-}
-
-static gboolean
-gtk_activate_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- return gtk_widget_activate (widget);
-}
-
-static void
-gtk_activate_action_print (GtkShortcutAction *action,
- GString *string)
-{
- g_string_append (string, "activate");
-}
-
-static const GtkShortcutActionClass GTK_ACTIVATE_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_ACTIVATE,
- sizeof (GtkActivateAction),
- "GtkActivateAction",
- gtk_activate_action_finalize,
- gtk_activate_action_activate,
- gtk_activate_action_print
-};
-
-static GtkActivateAction activate = { { &GTK_ACTIVATE_ACTION_CLASS, 1 } };
-
-/**
- * gtk_activate_action_new:
- *
- * Gets the activate action. This is an action that calls gtk_widget_activate()
- * on the given widget upon activation.
- *
- * Returns: The activate action
- */
-GtkShortcutAction *
-gtk_activate_action_new (void)
-{
- return gtk_shortcut_action_ref (&activate.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_MNEMONIC ***/
-
-typedef struct _GtkMnemonicAction GtkMnemonicAction;
-
-struct _GtkMnemonicAction
-{
- GtkShortcutAction action;
-};
-
-static void
-gtk_mnemonic_action_finalize (GtkShortcutAction *action)
-{
- g_assert_not_reached ();
-}
-
-static gboolean
-gtk_mnemonic_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- return gtk_widget_mnemonic_activate (widget, flags & GTK_SHORTCUT_ACTION_EXCLUSIVE ? FALSE : TRUE);
-}
-
-static void
-gtk_mnemonic_action_print (GtkShortcutAction *action,
- GString *string)
-{
- g_string_append (string, "mnemonic-activate");
-}
-
-static const GtkShortcutActionClass GTK_MNEMONIC_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_MNEMONIC,
- sizeof (GtkMnemonicAction),
- "GtkMnemonicAction",
- gtk_mnemonic_action_finalize,
- gtk_mnemonic_action_activate,
- gtk_mnemonic_action_print
-};
-
-static GtkMnemonicAction mnemonic = { { &GTK_MNEMONIC_ACTION_CLASS, 1 } };
-
-/**
- * gtk_mnemonic_action_new:
- *
- * Gets the mnemonic action. This is an action that calls
- * gtk_widget_mnemonic_activate() on the given widget upon activation.
- *
- * Returns: The mnemonic action
- */
-GtkShortcutAction *
-gtk_mnemonic_action_new (void)
-{
- return gtk_shortcut_action_ref (&mnemonic.action);
-}
-
-/*** GTK_SHORTCUT_ACTION_SIGNAL ***/
-
-typedef struct _GtkSignalAction GtkSignalAction;
-
-struct _GtkSignalAction
-{
- GtkShortcutAction action;
-
- char *name;
-};
-
-static void
-gtk_signal_action_finalize (GtkShortcutAction *action)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
-
- g_free (self->name);
-}
-
-static gboolean
-binding_compose_params (GtkWidget *widget,
- GVariantIter *args,
- GSignalQuery *query,
- GValue **params_p)
-{
- GValue *params;
- const GType *types;
- guint i;
- gboolean valid;
-
- params = g_new0 (GValue, query->n_params + 1);
- *params_p = params;
-
- /* The instance we emit on is the first object in the array
- */
- g_value_init (params, G_TYPE_OBJECT);
- g_value_set_object (params, G_OBJECT (widget));
- params++;
-
- types = query->param_types;
- valid = TRUE;
- for (i = 1; i < query->n_params + 1 && valid; i++)
- {
- GValue tmp_value = G_VALUE_INIT;
- GVariant *tmp_variant;
-
- g_value_init (params, *types);
- tmp_variant = g_variant_iter_next_value (args);
-
- switch ((guint) g_variant_classify (tmp_variant))
- {
- case G_VARIANT_CLASS_BOOLEAN:
- g_value_init (&tmp_value, G_TYPE_BOOLEAN);
- g_value_set_boolean (&tmp_value, g_variant_get_boolean (tmp_variant));
- break;
- case G_VARIANT_CLASS_DOUBLE:
- g_value_init (&tmp_value, G_TYPE_DOUBLE);
- g_value_set_double (&tmp_value, g_variant_get_double (tmp_variant));
- break;
- case G_VARIANT_CLASS_INT32:
- g_value_init (&tmp_value, G_TYPE_LONG);
- g_value_set_long (&tmp_value, g_variant_get_int32 (tmp_variant));
- break;
- case G_VARIANT_CLASS_UINT32:
- g_value_init (&tmp_value, G_TYPE_LONG);
- g_value_set_long (&tmp_value, g_variant_get_uint32 (tmp_variant));
- break;
- case G_VARIANT_CLASS_INT64:
- g_value_init (&tmp_value, G_TYPE_LONG);
- g_value_set_long (&tmp_value, g_variant_get_int64 (tmp_variant));
- break;
- case G_VARIANT_CLASS_STRING:
- /* gtk_rc_parse_flags/enum() has fancier parsing for this; we can't call
- * that since we don't have a GParamSpec, so just do something simple
- */
- if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_ENUM)
- {
- GEnumClass *class = G_ENUM_CLASS (g_type_class_ref (*types));
- GEnumValue *enum_value;
- const char *s = g_variant_get_string (tmp_variant, NULL);
-
- valid = FALSE;
-
- enum_value = g_enum_get_value_by_name (class, s);
- if (!enum_value)
- enum_value = g_enum_get_value_by_nick (class, s);
-
- if (enum_value)
- {
- g_value_init (&tmp_value, *types);
- g_value_set_enum (&tmp_value, enum_value->value);
- valid = TRUE;
- }
-
- g_type_class_unref (class);
- }
- /* This is just a hack for compatibility with GTK+-1.2 where a string
- * could be used for a single flag value / without the support for multiple
- * values in gtk_rc_parse_flags(), this isn't very useful.
- */
- else if (G_TYPE_FUNDAMENTAL (*types) == G_TYPE_FLAGS)
- {
- GFlagsClass *class = G_FLAGS_CLASS (g_type_class_ref (*types));
- GFlagsValue *flags_value;
- const char *s = g_variant_get_string (tmp_variant, NULL);
-
- valid = FALSE;
-
- flags_value = g_flags_get_value_by_name (class, s);
- if (!flags_value)
- flags_value = g_flags_get_value_by_nick (class, s);
- if (flags_value)
- {
- g_value_init (&tmp_value, *types);
- g_value_set_flags (&tmp_value, flags_value->value);
- valid = TRUE;
- }
-
- g_type_class_unref (class);
- }
- else
- {
- g_value_init (&tmp_value, G_TYPE_STRING);
- g_value_set_static_string (&tmp_value, g_variant_get_string (tmp_variant, NULL));
- }
- break;
- default:
- valid = FALSE;
- break;
- }
-
- if (valid)
- {
- if (!g_value_transform (&tmp_value, params))
- valid = FALSE;
-
- g_value_unset (&tmp_value);
- }
-
- g_variant_unref (tmp_variant);
- types++;
- params++;
- }
-
- if (!valid)
- {
- guint j;
-
- for (j = 0; j < i; j++)
- g_value_unset (&(*params_p)[j]);
-
- g_free (*params_p);
- *params_p = NULL;
- }
-
- return valid;
-}
-
-static gboolean
-gtk_signal_action_emit_signal (GtkWidget *widget,
- const char *signal,
- GVariant *args,
- gboolean *handled,
- GError **error)
-{
- GSignalQuery query;
- guint signal_id;
- GValue *params = NULL;
- GValue return_val = G_VALUE_INIT;
- GVariantIter args_iter;
- gsize n_args;
- guint i;
-
- *handled = FALSE;
-
- signal_id = g_signal_lookup (signal, G_OBJECT_TYPE (widget));
- if (!signal_id)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Could not find signal \"%s\" in the '%s' class ancestry",
- signal,
- g_type_name (G_OBJECT_TYPE (widget)));
- return FALSE;
- }
-
- g_signal_query (signal_id, &query);
- if (args == NULL)
- n_args = 0;
- else if (g_variant_is_of_type (args, G_VARIANT_TYPE_TUPLE))
- n_args = g_variant_iter_init (&args_iter, args);
- else
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "argument GVariant is not a tuple");
- return FALSE;
- }
- if (query.n_params != n_args ||
- (query.return_type != G_TYPE_NONE && query.return_type != G_TYPE_BOOLEAN) ||
- !binding_compose_params (widget, &args_iter, &query, &params))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "signature mismatch for signal \"%s\" in the '%s' class ancestry",
- signal,
- g_type_name (G_OBJECT_TYPE (widget)));
- return FALSE;
- }
- else if (!(query.signal_flags & G_SIGNAL_ACTION))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "signal \"%s\" in the '%s' class ancestry cannot be used for action emissions",
- signal,
- g_type_name (G_OBJECT_TYPE (widget)));
- return FALSE;
- }
-
- if (query.return_type == G_TYPE_BOOLEAN)
- g_value_init (&return_val, G_TYPE_BOOLEAN);
-
- g_signal_emitv (params, signal_id, 0, &return_val);
-
- if (query.return_type == G_TYPE_BOOLEAN)
- {
- if (g_value_get_boolean (&return_val))
- *handled = TRUE;
- g_value_unset (&return_val);
- }
- else
- *handled = TRUE;
-
- if (params != NULL)
- {
- for (i = 0; i < query.n_params + 1; i++)
- g_value_unset (&params[i]);
-
- g_free (params);
- }
-
- return TRUE;
-}
-
-static gboolean
-gtk_signal_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
- GError *error = NULL;
- gboolean handled;
-
- if (!gtk_signal_action_emit_signal (widget,
- self->name,
- args,
- &handled,
- &error))
- {
- g_warning ("gtk_signal_action_activate(): %s",
- error->message);
- g_clear_error (&error);
- return FALSE;
- }
-
- return handled;
-}
-
-static void
-gtk_signal_action_print (GtkShortcutAction *action,
- GString *string)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
-
- g_string_append_printf (string, "signal(%s)", self->name);
-}
-
-static const GtkShortcutActionClass GTK_SIGNAL_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_SIGNAL,
- sizeof (GtkSignalAction),
- "GtkSignalAction",
- gtk_signal_action_finalize,
- gtk_signal_action_activate,
- gtk_signal_action_print
-};
-
-/**
- * gtk_signal_action_new:
- * @signal_name: name of the signal to emit
- *
- * Creates an action that when activated, emits the given action signal
- * on the provided widget unpacking the given args into arguments passed
- * to the signal.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_signal_action_new (const char *signal_name)
-{
- GtkSignalAction *self;
-
- g_return_val_if_fail (signal_name != NULL, NULL);
-
- self = (GtkSignalAction *) gtk_shortcut_action_new (&GTK_SIGNAL_ACTION_CLASS);
-
- self->name = g_strdup (signal_name);
-
- return &self->action;
-}
-
-/**
- * gtk_signal_action_get_signal_name:
- * @action: a signal action
- *
- * Returns the name of the signal that will be emitted.
- *
- * Returns: the name of the signal to emit
- **/
-const char *
-gtk_signal_action_get_signal_name (GtkShortcutAction *action)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_SIGNAL), NULL);
-
- return self->name;
-}
-
-/*** GTK_SHORTCUT_ACTION_ACTION ***/
-
-typedef struct _GtkActionAction GtkActionAction;
-
-struct _GtkActionAction
-{
- GtkShortcutAction action;
-
- char *name;
-};
-
-static void
-gtk_action_action_finalize (GtkShortcutAction *action)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
-
- g_free (self->name);
-}
-
-static gboolean
-gtk_shortcut_trigger_check_parameter_type (GVariant *args,
- const GVariantType *parameter_type)
-{
- if (args)
- {
- if (parameter_type == NULL)
- {
- g_warning ("Trying to invoke action with arguments, but action has no parameter");
- return FALSE;
- }
-
- if (!g_variant_is_of_type (args, parameter_type))
- {
- gchar *typestr = g_variant_type_dup_string (parameter_type);
- gchar *targetstr = g_variant_print (args, TRUE);
- g_warning ("Trying to invoke action with target '%s',"
- " but action expects parameter with type '%s'", targetstr, typestr);
- g_free (targetstr);
- g_free (typestr);
- return FALSE;
- }
- }
- else
- {
- if (parameter_type != NULL)
- {
- gchar *typestr = g_variant_type_dup_string (parameter_type);
- g_warning ("Trying to invoke action without arguments,"
- " but action expects parameter with type '%s'", typestr);
- g_free (typestr);
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-gtk_action_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- GtkSignalAction *self = (GtkSignalAction *) action;
- GActionGroup *action_group;
- const GVariantType *parameter_type;
- gboolean enabled;
-
- action_group = G_ACTION_GROUP (_gtk_widget_get_action_muxer (widget, FALSE));
- if (action_group == NULL)
- return FALSE;
-
- if (!g_action_group_query_action (action_group, self->name, &enabled, &parameter_type, NULL, NULL, NULL))
- return FALSE;
-
- if (!enabled)
- return FALSE;
-
- /* We found an action with the correct name and it's enabled.
- * This is the action that we are going to try to invoke.
- *
- * There is still the possibility that the args don't
- * match the expected parameter type. In that case, we will print
- * a warning.
- */
- if (!gtk_shortcut_trigger_check_parameter_type (args, parameter_type))
- return FALSE;
-
- g_action_group_activate_action (action_group, self->name, args);
-
- return TRUE;
-}
-
-static void
-gtk_action_action_print (GtkShortcutAction *action,
- GString *string)
-{
- GtkActionAction *self = (GtkActionAction *) action;
-
- g_string_append_printf (string, "action(%s)", self->name);
-}
-
-static const GtkShortcutActionClass GTK_ACTION_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_ACTION,
- sizeof (GtkActionAction),
- "GtkActionAction",
- gtk_action_action_finalize,
- gtk_action_action_activate,
- gtk_action_action_print
-};
-
-/**
- * gtk_action_action_new:
- * @name: the detailed name of the action
- *
- * Creates an action that when activated, activates the action given by
- * the detailed @name on the widget passing the given arguments to it.
- *
- * See gtk_widget_insert_action_group() for how to add actions to widgets.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_action_action_new (const char *name)
-{
- GtkActionAction *self;
-
- g_return_val_if_fail (name != NULL, NULL);
-
- self = (GtkActionAction *) gtk_shortcut_action_new (&GTK_ACTION_ACTION_CLASS);
-
- self->name = g_strdup (name);
-
- return &self->action;
-}
-
-/**
- * gtk_action_action_get_name:
- * @action: an action action
- *
- * Returns the name of the action that will be activated.
- *
- * Returns: the name of the action to activate
- **/
-const char *
-gtk_action_action_get_name (GtkShortcutAction *action)
-{
- GtkActionAction *self = (GtkActionAction *) action;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_ACTION), NULL);
-
- return self->name;
-}
-
-/*** GTK_SHORTCUT_ACTION_GACTION ***/
-
-typedef struct _GtkGActionAction GtkGActionAction;
-
-struct _GtkGActionAction
-{
- GtkShortcutAction action;
-
- GAction *gaction;
-};
-
-static void
-gtk_gaction_action_finalize (GtkShortcutAction *action)
-{
- GtkGActionAction *self = (GtkGActionAction *) action;
-
- g_object_unref (self->gaction);
-}
-
-static gboolean
-gtk_gaction_action_activate (GtkShortcutAction *action,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args)
-{
- GtkGActionAction *self = (GtkGActionAction *) action;
-
- if (!gtk_shortcut_trigger_check_parameter_type (args, g_action_get_parameter_type (self->gaction)))
- return FALSE;
-
- if (!g_action_get_enabled (self->gaction))
- return FALSE;
-
- g_action_activate (self->gaction, args);
-
- return TRUE;
-}
-
-static void
-gtk_gaction_action_print (GtkShortcutAction *action,
- GString *string)
-{
- GtkGActionAction *self = (GtkGActionAction *) action;
-
- g_string_append_printf (string, "gaction(%s %p)", g_action_get_name (self->gaction), self->gaction);
-}
-
-static const GtkShortcutActionClass GTK_GACTION_ACTION_CLASS = {
- GTK_SHORTCUT_ACTION_GACTION,
- sizeof (GtkGActionAction),
- "GtkGActionAction",
- gtk_gaction_action_finalize,
- gtk_gaction_action_activate,
- gtk_gaction_action_print
-};
-
-/**
- * gtk_gaction_action_new:
- * @action: a #GAction
- *
- * Creates a new action that will activate the given @gaction when activated
- * with the passed in arguments.
- *
- * Returns: a new #GtkShortcutAction
- **/
-GtkShortcutAction *
-gtk_gaction_action_new (GAction *action)
-{
- GtkGActionAction *self;
-
- g_return_val_if_fail (G_IS_ACTION (action), NULL);
-
- self = (GtkGActionAction *) gtk_shortcut_action_new (&GTK_GACTION_ACTION_CLASS);
-
- self->gaction = g_object_ref (action);
-
- return &self->action;
-}
-
-/**
- * gtk_gaction_action_get_gaction:
- * @action: a gaction action
- *
- * Queries the #GAction that will be activated when this action is activated.
- *
- * Returns: (transfer none): The #GAction that will be activated
- **/
-GAction *
-gtk_gaction_action_get_gaction (GtkShortcutAction *action)
-{
- GtkGActionAction *self = (GtkGActionAction *) action;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_ACTION_TYPE (action, GTK_SHORTCUT_ACTION_GACTION), NULL);
-
- return self->gaction;
-}
-
diff --git a/gtk/gtkshortcutaction.h b/gtk/gtkshortcutaction.h
deleted file mode 100644
index 95904fbfb8..0000000000
--- a/gtk/gtkshortcutaction.h
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_ACTION_H__
-#define __GTK_SHORTCUT_ACTION_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_ACTION (gtk_shortcut_action_get_type ())
-
-#define GTK_IS_SHORTCUT_ACTION(obj) ((obj) != NULL)
-
-/**
- * GtkShortcutFunc:
- * @widget: The widget passed to the activation
- * @args: The arguments passed to the activation
- * @user_data: The user data provided when activating the action
- *
- * Prototype for shortcuts based on user callbacks.
- */
-typedef gboolean (* GtkShortcutFunc) (GtkWidget *widget,
- GVariant *args,
- gpointer user_data);
-
-/**
- * GtkShortcutActionFlags:
- * @GTK_SHORTCUT_ACTION_EXCLUSIVE: The action is the only
- * action that can be activated. If this flag is not set,
- * a future activation may select a different action.
- *
- * List of flags that can be passed to action activation.
- * More flags may be added in the future.
- **/
-typedef enum {
- GTK_SHORTCUT_ACTION_EXCLUSIVE = 1 << 0
-} GtkShortcutActionFlags;
-
-/**
- * GtkShortcutActionType:
- * @GTK_SHORTCUT_ACTION_NOTHING: Don't ever activate
- * @GTK_SHORTCUT_ACTION_CALLBACK: Call a custom user-provided callback
- * @GTK_SHORTCUT_ACTION_ACTIVATE: Call gtk_widget_activate() on the widget
- * @GTK_SHORTCUT_ACTION_MNEMONIC: Call gtk_widget_mnemonic_activate()
- * on the widget
- * @GTK_SHORTCUT_ACTION_SIGNAL: Emit the given action signal on the widget
- * @GTK_SHORTCUT_ACTION_ACTION: Call the provided action on the widget
- * @GTK_SHORTCUT_ACTION_GACTION: Activate a GAction
- *
- * The type of a action determines what the action does when activated.
- **/
-typedef enum {
- GTK_SHORTCUT_ACTION_NOTHING,
- GTK_SHORTCUT_ACTION_CALLBACK,
- GTK_SHORTCUT_ACTION_ACTIVATE,
- GTK_SHORTCUT_ACTION_MNEMONIC,
- GTK_SHORTCUT_ACTION_SIGNAL,
- GTK_SHORTCUT_ACTION_ACTION,
- GTK_SHORTCUT_ACTION_GACTION
-} GtkShortcutActionType;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_shortcut_action_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_shortcut_action_ref (GtkShortcutAction *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_action_unref (GtkShortcutAction *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutActionType gtk_shortcut_action_get_action_type (GtkShortcutAction *self);
-
-GDK_AVAILABLE_IN_ALL
-char * gtk_shortcut_action_to_string (GtkShortcutAction *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_action_print (GtkShortcutAction *self,
- GString *string);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_shortcut_action_activate (GtkShortcutAction *self,
- GtkShortcutActionFlags flags,
- GtkWidget *widget,
- GVariant *args);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_nothing_action_new (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_callback_action_new (GtkShortcutFunc callback,
- gpointer data,
- GDestroyNotify destroy);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_mnemonic_action_new (void);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_activate_action_new (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_signal_action_new (const char *signal_name);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_signal_action_get_signal_name (GtkShortcutAction *action);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_action_action_new (const char *name);
-GDK_AVAILABLE_IN_ALL
-const char * gtk_action_action_get_name (GtkShortcutAction *action);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutAction * gtk_gaction_action_new (GAction *action);
-GDK_AVAILABLE_IN_ALL
-GAction * gtk_gaction_action_get_gaction (GtkShortcutAction *action);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_ACTION_H__ */
diff --git a/gtk/gtkshortcutactionprivate.h b/gtk/gtkshortcutactionprivate.h
deleted file mode 100644
index 4c5a0db3ef..0000000000
--- a/gtk/gtkshortcutactionprivate.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_ACTION_PRIVATE_H__
-#define __GTK_SHORTCUT_ACTION_PRIVATE_H__
-
-#include "gtkshortcutaction.h"
-
-GtkShortcutAction * gtk_shortcut_action_parse_builder (GtkBuilder *builder,
- const char *string,
- GError **error);
-
-#endif /* __GTK_SHORTCUT_ACTION_PRIVATE_H__ */
diff --git a/gtk/gtkshortcutcontroller.c b/gtk/gtkshortcutcontroller.c
deleted file mode 100644
index 0c2d1ba040..0000000000
--- a/gtk/gtkshortcutcontroller.c
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-/**
- * SECTION:gtkshortcutcontroller
- * @Short_description: Event controller for shortcuts
- * @Title: GtkShortcutController
- * @See_also: #GtkEventController, #GtkShortcut
- *
- * #GtkShortcutController is an event controller that manages shortcuts.
- *
- * #GtkShortcutController implements #GListModel for querying the shortcuts that
- * have been added to it.
- **/
-
-#include "config.h"
-
-#include "gtkshortcutcontrollerprivate.h"
-
-#include "gtkbuildable.h"
-#include "gtkconcatmodelprivate.h"
-#include "gtkeventcontrollerprivate.h"
-#include "gtkintl.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcuttrigger.h"
-#include "gtktypebuiltins.h"
-#include "gtkwidgetprivate.h"
-
-#include <gdk/gdk.h>
-
-struct _GtkShortcutController
-{
- GtkEventController parent_instance;
-
- GListModel *shortcuts;
- GtkShortcutScope scope;
- GdkModifierType mnemonics_modifiers;
-
- guint custom_shortcuts : 1;
-};
-
-struct _GtkShortcutControllerClass
-{
- GtkEventControllerClass parent_class;
-};
-
-enum {
- PROP_0,
- PROP_MNEMONICS_MODIFIERS,
- PROP_MODEL,
- PROP_SCOPE,
-
- N_PROPS
-};
-
-static GParamSpec *properties[N_PROPS] = { NULL, };
-
-static GType
-gtk_shortcut_controller_list_model_get_item_type (GListModel *list)
-{
- return GTK_TYPE_SHORTCUT;
-}
-
-static guint
-gtk_shortcut_controller_list_model_get_n_items (GListModel *list)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
-
- return g_list_model_get_n_items (self->shortcuts);
-}
-
-static gpointer
-gtk_shortcut_controller_list_model_get_item (GListModel *list,
- guint position)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (list);
-
- return g_list_model_get_item (self->shortcuts, position);
-}
-
-static void
-gtk_shortcut_controller_list_model_init (GListModelInterface *iface)
-{
- iface->get_item_type = gtk_shortcut_controller_list_model_get_item_type;
- iface->get_n_items = gtk_shortcut_controller_list_model_get_n_items;
- iface->get_item = gtk_shortcut_controller_list_model_get_item;
-}
-
-static void
-gtk_shortcut_controller_buildable_add_child (GtkBuildable *buildable,
- GtkBuilder *builder,
- GObject *child,
- const gchar *type)
-{
- if (type != NULL)
- {
- GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
- }
- if (GTK_IS_SHORTCUT (child))
- {
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (buildable), GTK_SHORTCUT (child));
- }
- else
- {
- g_warning ("Cannot add an object of type %s to a controller of type %s",
- g_type_name (G_OBJECT_TYPE (child)), g_type_name (G_OBJECT_TYPE (buildable)));
- }
-}
-
-static void
-gtk_shortcut_controller_buildable_init (GtkBuildableIface *iface)
-{
- iface->add_child = gtk_shortcut_controller_buildable_add_child;
-}
-
-G_DEFINE_TYPE_WITH_CODE (GtkShortcutController, gtk_shortcut_controller,
- GTK_TYPE_EVENT_CONTROLLER,
- G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_shortcut_controller_list_model_init)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_shortcut_controller_buildable_init))
-
-static gboolean
-gtk_shortcut_controller_is_rooted (GtkShortcutController *self)
-{
- GtkWidget *widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
-
- if (widget == NULL)
- return FALSE;
-
- return gtk_widget_get_root (widget) != NULL;
-}
-
-static void
-gtk_shortcut_controller_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
- switch (prop_id)
- {
- case PROP_MNEMONICS_MODIFIERS:
- gtk_shortcut_controller_set_mnemonics_modifiers (self, g_value_get_flags (value));
- break;
-
- case PROP_MODEL:
- {
- GListModel *model = g_value_get_object (value);
- if (model && g_list_model_get_item_type (model) != GTK_TYPE_SHORTCUT)
- {
- g_warning ("Setting a model with type '%s' on a shortcut controller that requires 'GtkShortcut'",
- g_type_name (g_list_model_get_item_type (model)));
- model = NULL;
- }
- if (model == NULL)
- {
- self->shortcuts = G_LIST_MODEL (g_list_store_new (GTK_TYPE_SHORTCUT));
- self->custom_shortcuts = TRUE;
- }
- else
- {
- self->shortcuts = g_object_ref (model);
- self->custom_shortcuts = FALSE;
- }
- g_signal_connect_swapped (self->shortcuts, "items-changed", G_CALLBACK (g_list_model_items_changed), self);
- }
- break;
-
- case PROP_SCOPE:
- gtk_shortcut_controller_set_scope (self, g_value_get_enum (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-gtk_shortcut_controller_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
- switch (prop_id)
- {
- case PROP_MNEMONICS_MODIFIERS:
- g_value_set_flags (value, self->mnemonics_modifiers);
- break;
-
- case PROP_SCOPE:
- g_value_set_enum (value, self->scope);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-gtk_shortcut_controller_dispose (GObject *object)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
- if (self->custom_shortcuts)
- g_list_store_remove_all (G_LIST_STORE (self->shortcuts));
-
- G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->dispose (object);
-}
-
-static void
-gtk_shortcut_controller_finalize (GObject *object)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (object);
-
- g_signal_handlers_disconnect_by_func (self->shortcuts, g_list_model_items_changed, self);
- g_clear_object (&self->shortcuts);
-
- G_OBJECT_CLASS (gtk_shortcut_controller_parent_class)->finalize (object);
-}
-
-static gboolean
-gtk_shortcut_controller_trigger_shortcut (GtkShortcutController *self,
- GtkShortcut *shortcut,
- guint position,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- GtkWidget *widget;
-
- if (!gtk_shortcut_trigger_trigger (gtk_shortcut_get_trigger (shortcut), event, enable_mnemonics))
- return FALSE;
-
- widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
- if (!self->custom_shortcuts &&
- GTK_IS_CONCAT_MODEL (self->shortcuts))
- {
- GListModel *model = gtk_concat_model_get_model_for_item (GTK_CONCAT_MODEL (self->shortcuts), position);
- if (GTK_IS_SHORTCUT_CONTROLLER (model))
- widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (model));
- }
-
- return gtk_shortcut_action_activate (gtk_shortcut_get_action (shortcut),
- GTK_SHORTCUT_ACTION_EXCLUSIVE, /* FIXME */
- widget,
- gtk_shortcut_get_arguments (shortcut));
-}
-
-static gboolean
-gtk_shortcut_controller_run_controllers (GtkEventController *controller,
- GdkEvent *event,
- double x,
- double y,
- gboolean enable_mnemonics)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
- guint i;
-
- for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
- {
- if (gtk_shortcut_controller_trigger_shortcut (self,
- g_list_model_get_item (self->shortcuts, i),
- i,
- event,
- enable_mnemonics))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-gtk_shortcut_controller_handle_event (GtkEventController *controller,
- GdkEvent *event,
- double x,
- double y)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
- gboolean enable_mnemonics;
-
- if (self->scope != GTK_SHORTCUT_SCOPE_LOCAL)
- return FALSE;
-
- if (gdk_event_get_event_type (event) == GDK_KEY_PRESS)
- {
- GdkModifierType modifiers;
- modifiers = gdk_event_get_modifier_state (event);
- enable_mnemonics = (modifiers & gtk_accelerator_get_default_mod_mask ()) == self->mnemonics_modifiers;
- }
- else
- {
- enable_mnemonics = FALSE;
- }
-
- return gtk_shortcut_controller_run_controllers (controller, event, x, y, enable_mnemonics);
-}
-
-static void
-gtk_shortcut_controller_set_widget (GtkEventController *controller,
- GtkWidget *widget)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
-
- GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->set_widget (controller, widget);
-
- if (_gtk_widget_get_root (widget))
- gtk_shortcut_controller_root (self);
-}
-
-static void
-gtk_shortcut_controller_unset_widget (GtkEventController *controller)
-{
- GtkShortcutController *self = GTK_SHORTCUT_CONTROLLER (controller);
- GtkWidget *widget = gtk_event_controller_get_widget (controller);
-
- if (_gtk_widget_get_root (widget))
- gtk_shortcut_controller_unroot (self);
-
- GTK_EVENT_CONTROLLER_CLASS (gtk_shortcut_controller_parent_class)->unset_widget (controller);
-}
-
-static void
-gtk_shortcut_controller_class_init (GtkShortcutControllerClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- GtkEventControllerClass *controller_class = GTK_EVENT_CONTROLLER_CLASS (klass);
-
- object_class->dispose = gtk_shortcut_controller_dispose;
- object_class->finalize = gtk_shortcut_controller_finalize;
- object_class->set_property = gtk_shortcut_controller_set_property;
- object_class->get_property = gtk_shortcut_controller_get_property;
-
- controller_class->handle_event = gtk_shortcut_controller_handle_event;
- controller_class->set_widget = gtk_shortcut_controller_set_widget;
- controller_class->unset_widget = gtk_shortcut_controller_unset_widget;
-
- /**
- * GtkShortcutController:mnemonic-modifiers:
- *
- * The modifiers that need to be pressed to allow mnemonics activation.
- */
- properties[PROP_MNEMONICS_MODIFIERS] =
- g_param_spec_flags ("mnemonic-modifiers",
- P_("Mnemonic modifers"),
- P_("The modifiers to be pressed to allow mnemonics activation"),
- GDK_TYPE_MODIFIER_TYPE,
- GDK_MOD1_MASK,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- /**
- * GtkShortcutController:model:
- *
- * A list model to take shortcuts from
- */
- properties[PROP_MODEL] =
- g_param_spec_object ("model",
- P_("Model"),
- P_("A list model to take shortcuts from"),
- G_TYPE_LIST_MODEL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- /**
- * GtkShortcutController:scope:
- *
- * What scope the shortcuts will be handled in.
- */
- properties[PROP_SCOPE] =
- g_param_spec_enum ("scope",
- P_("Scope"),
- P_("What scope the shortcuts will be handled in"),
- GTK_TYPE_SHORTCUT_SCOPE,
- GTK_SHORTCUT_SCOPE_LOCAL,
- G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, N_PROPS, properties);
-}
-
-static void
-gtk_shortcut_controller_init (GtkShortcutController *self)
-{
- self->mnemonics_modifiers = GDK_MOD1_MASK;
-}
-
-void
-gtk_shortcut_controller_root (GtkShortcutController *self)
-{
- GtkShortcutManager *manager;
-
- switch (self->scope)
- {
- case GTK_SHORTCUT_SCOPE_LOCAL:
- return;
-
- case GTK_SHORTCUT_SCOPE_MANAGED:
- {
- GtkWidget *widget;
-
- for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
- !GTK_IS_SHORTCUT_MANAGER (widget);
- widget = _gtk_widget_get_parent (widget))
- ;
-
- if (!GTK_IS_SHORTCUT_MANAGER (widget))
- return;
-
- manager = GTK_SHORTCUT_MANAGER (widget);
- }
- break;
-
- case GTK_SHORTCUT_SCOPE_GLOBAL:
- {
- GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
-
- if (!GTK_IS_SHORTCUT_MANAGER (root))
- return;
-
- manager = GTK_SHORTCUT_MANAGER (root);
- }
- break;
-
- default:
- g_assert_not_reached ();
- return;
- }
-
- GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->add_controller (manager, self);
-}
-
-void
-gtk_shortcut_controller_unroot (GtkShortcutController *self)
-{
- GtkShortcutManager *manager;
-
- switch (self->scope)
- {
- case GTK_SHORTCUT_SCOPE_LOCAL:
- return;
-
- case GTK_SHORTCUT_SCOPE_MANAGED:
- {
- GtkWidget *widget;
-
- for (widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self));
- !GTK_IS_SHORTCUT_MANAGER (widget);
- widget = _gtk_widget_get_parent (widget))
- ;
-
- if (!GTK_IS_SHORTCUT_MANAGER (widget))
- return;
-
- manager = GTK_SHORTCUT_MANAGER (widget);
- }
- break;
-
- case GTK_SHORTCUT_SCOPE_GLOBAL:
- {
- GtkRoot *root = gtk_widget_get_root (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (self)));
-
- if (!GTK_IS_SHORTCUT_MANAGER (root))
- return;
-
- manager = GTK_SHORTCUT_MANAGER (root);
- }
- break;
-
- default:
- g_assert_not_reached ();
- return;
- }
-
- GTK_SHORTCUT_MANAGER_GET_IFACE (manager)->remove_controller (manager, self);
-}
-
-GtkEventController *
-gtk_shortcut_controller_new (void)
-{
- return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
- NULL);
-}
-
-GtkEventController *
-gtk_shortcut_controller_new_for_model (GListModel *model)
-{
- g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
- g_return_val_if_fail (g_list_model_get_item_type (model) == GTK_TYPE_SHORTCUT, NULL);
-
- return g_object_new (GTK_TYPE_SHORTCUT_CONTROLLER,
- "model", model,
- NULL);
-}
-
-/**
- * gtk_shortcut_controller_add_shortcut:
- * @self: the controller
- * @shortcut: a #GtkShortcut
- *
- * Adds @shortcut to the list of shortcuts handled by @self.
- *
- * If this controller uses an external shortcut list, this function does
- * nothing.
- *
- * The shortcut is added to the list so that it is triggered before
- * all existing shortcuts.
- *
- * FIXME: What's supposed to happen if a shortcut gets added twice?
- **/
-void
-gtk_shortcut_controller_add_shortcut (GtkShortcutController *self,
- GtkShortcut *shortcut)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
- g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
-
- if (!self->custom_shortcuts)
- return;
-
- g_list_store_append (G_LIST_STORE (self->shortcuts), shortcut);
-}
-
-/**
- * gtk_shortcut_controller_remove_shortcut:
- * @self: the controller
- * @shortcut: a #GtkShortcut
- *
- * Removes @shortcut from the list of shortcuts handled by @self.
- *
- * If @shortcut had not been added to @controller or this controller
- * uses an external shortcut list, this function does nothing.
- **/
-void
-gtk_shortcut_controller_remove_shortcut (GtkShortcutController *self,
- GtkShortcut *shortcut)
-{
- guint i;
-
- g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
- g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
-
- if (!self->custom_shortcuts)
- return;
-
- for (i = 0; i < g_list_model_get_n_items (self->shortcuts); i++)
- {
- GtkShortcut *item = g_list_model_get_item (self->shortcuts, i);
-
- if (item == shortcut)
- {
- g_object_unref (item);
- g_list_store_remove (G_LIST_STORE (self->shortcuts), i);
- return;
- }
-
- g_object_unref (item);
- }
-}
-
-/**
- * gtk_shortcut_controller_set_scope:
- * @self: a #GtkShortcutController
- * @scope: the new scope to use
- *
- * Sets the controller to have the given @scope.
- *
- * The scope allows shortcuts to be activated outside of the normal
- * event propagation. In particular, it allows installing global
- * keyboard shortcuts that can be activated even when a widget does
- * not have focus.
- **/
-void
-gtk_shortcut_controller_set_scope (GtkShortcutController *self,
- GtkShortcutScope scope)
-{
- gboolean rooted;
-
- g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-
- if (self->scope == scope)
- return;
-
- rooted = gtk_shortcut_controller_is_rooted (self);
-
- if (rooted)
- gtk_shortcut_controller_unroot (self);
-
- self->scope = scope;
-
- if (rooted)
- gtk_shortcut_controller_root (self);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SCOPE]);
-}
-
-/**
- * gtk_shortcut_controller_get_scope:
- * @self: a #GtkShortcutController
- *
- * Gets the scope for when this controller activates its shortcuts. See
- * gtk_shortcut_controller_set_scope() for details.
- *
- * Returns: the controller's scope
- **/
-GtkShortcutScope
-gtk_shortcut_controller_get_scope (GtkShortcutController *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
-
- return self->scope;
-}
-
-/**
- * gtk_shortcut_controller_set_mnemonics_modifiers:
- * @self: a #GtkShortcutController
- * @modifiers: the new mnemonics_modifiers to use
- *
- * Sets the controller to have the given @mnemonics_modifiers.
- *
- * The mnemonics modifiers determines which modifiers need to be pressed to allow
- * activation of shortcuts with mnemonics triggers.
- *
- * This value is only relevant for local shortcut controllers. Global and managed
- * shortcut controllers will have their shortcuts activated from other places which
- * have their own modifiers for activating mnemonics.
- **/
-void
-gtk_shortcut_controller_set_mnemonics_modifiers (GtkShortcutController *self,
- GdkModifierType modifiers)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self));
-
- if (self->mnemonics_modifiers == modifiers)
- return;
-
- self->mnemonics_modifiers = modifiers;
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MNEMONICS_MODIFIERS]);
-}
-
-/**
- * gtk_shortcut_controller_get_mnemonics_modifiers:
- * @self: a #GtkShortcutController
- *
- * Gets the mnemonics modifiers for when this controller activates its shortcuts. See
- * gtk_shortcut_controller_set_mnemonics_modifiers() for details.
- *
- * Returns: the controller's mnemonics modifiers
- **/
-GdkModifierType
-gtk_shortcut_controller_get_mnemonics_modifiers (GtkShortcutController *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_CONTROLLER (self), GTK_SHORTCUT_SCOPE_LOCAL);
-
- return self->mnemonics_modifiers;
-}
-
diff --git a/gtk/gtkshortcutcontroller.h b/gtk/gtkshortcutcontroller.h
deleted file mode 100644
index aeb50e7f91..0000000000
--- a/gtk/gtkshortcutcontroller.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-
-#ifndef __GTK_SHORTCUT_CONTROLLER_H__
-#define __GTK_SHORTCUT_CONTROLLER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtkeventcontroller.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_CONTROLLER (gtk_shortcut_controller_get_type ())
-#define GTK_SHORTCUT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutController))
-#define GTK_SHORTCUT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutControllerClass))
-#define GTK_IS_SHORTCUT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_SHORTCUT_CONTROLLER))
-#define GTK_IS_SHORTCUT_CONTROLLER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_SHORTCUT_CONTROLLER))
-#define GTK_SHORTCUT_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_SHORTCUT_CONTROLLER, GtkShortcutControllerClass))
-
-typedef struct _GtkShortcutController GtkShortcutController;
-typedef struct _GtkShortcutControllerClass GtkShortcutControllerClass;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_shortcut_controller_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkEventController * gtk_shortcut_controller_new (void);
-GDK_AVAILABLE_IN_ALL
-GtkEventController * gtk_shortcut_controller_new_for_model (GListModel *list);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_controller_set_mnemonics_modifiers (GtkShortcutController *self,
- GdkModifierType modifiers);
-GDK_AVAILABLE_IN_ALL
-GdkModifierType gtk_shortcut_controller_get_mnemonics_modifiers (GtkShortcutController *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_controller_set_scope (GtkShortcutController *self,
- GtkShortcutScope scope);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutScope gtk_shortcut_controller_get_scope (GtkShortcutController *self);
-
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_controller_add_shortcut (GtkShortcutController *self,
- GtkShortcut *shortcut);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_controller_remove_shortcut (GtkShortcutController *self,
- GtkShortcut *shortcut);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_CONTROLLER_H__ */
diff --git a/gtk/gtkshortcutcontrollerprivate.h b/gtk/gtkshortcutcontrollerprivate.h
deleted file mode 100644
index db1b52cecc..0000000000
--- a/gtk/gtkshortcutcontrollerprivate.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_CONTROLLER_PRIVATE_H__
-#define __GTK_SHORTCUT_CONTROLLER_PRIVATE_H__
-
-#include "gtkshortcutcontroller.h"
-
-void gtk_shortcut_controller_root (GtkShortcutController *controller);
-void gtk_shortcut_controller_unroot (GtkShortcutController *controller);
-
-#endif /* __GTK_SHORTCUT_CONTROLLER_H__ */
diff --git a/gtk/gtkshortcutlabel.c b/gtk/gtkshortcutlabel.c
index 90471af3ee..704324fa8c 100644
--- a/gtk/gtkshortcutlabel.c
+++ b/gtk/gtkshortcutlabel.c
@@ -303,7 +303,8 @@ parse_combination (GtkShortcutLabel *self,
accels = g_strsplit (str, "&", 0);
for (k = 0; accels[k]; k++)
{
- if (!gtk_accelerator_parse (accels[k], &key, &modifier))
+ gtk_accelerator_parse (accels[k], &key, &modifier);
+ if (key == 0 && modifier == 0)
{
retval = FALSE;
break;
diff --git a/gtk/gtkshortcutmanager.c b/gtk/gtkshortcutmanager.c
deleted file mode 100644
index 64fdd7ba8e..0000000000
--- a/gtk/gtkshortcutmanager.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#include "config.h"
-
-#include "gtkshortcutmanager.h"
-#include "gtkshortcutmanagerprivate.h"
-#include "gtkconcatmodelprivate.h"
-
-/**
- * SECTION:gtkshortcutmanager
- * @title: GtkShortcutManager
- * @short_description: Interface for managing shortcuts
- *
- * The GtkShortcutManager interface is used to implement
- * shortcut scopes.
- */
-
-G_DEFINE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, G_TYPE_OBJECT)
-
-void
-gtk_shortcut_manager_create_controllers (GtkWidget *widget)
-{
- GtkConcatModel *model;
- GtkEventController *controller;
-
- model = gtk_concat_model_new (GTK_TYPE_SHORTCUT);
- g_object_set_data_full (G_OBJECT (widget), "gtk-shortcut-manager-bubble", model, g_object_unref);
- controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (model));
- gtk_event_controller_set_name (controller, "gtk-shortcut-manager-bubble");
- gtk_widget_add_controller (widget, controller);
-
- model = gtk_concat_model_new (GTK_TYPE_SHORTCUT);
- g_object_set_data_full (G_OBJECT (widget), "gtk-shortcut-manager-capture", model, g_object_unref);
- controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (model));
- gtk_event_controller_set_name (controller, "gtk-shortcut-manager-capture");
- gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
- gtk_widget_add_controller (widget, controller);
-}
-
-static GtkConcatModel *
-gtk_shortcut_manager_get_model (GtkShortcutManager *self,
- GtkPropagationPhase phase)
-{
- switch (phase)
- {
- case GTK_PHASE_CAPTURE:
- return g_object_get_data (G_OBJECT (self), "gtk-shortcut-manager-capture");
- case GTK_PHASE_BUBBLE:
- return g_object_get_data (G_OBJECT (self), "gtk-shortcut-manager-bubble");
- case GTK_PHASE_NONE:
- case GTK_PHASE_TARGET:
- return NULL;
- default:
- g_assert_not_reached ();
- return NULL;
- }
-}
-
-static void
-gtk_shortcut_manager_default_add_controller (GtkShortcutManager *self,
- GtkShortcutController *controller)
-{
- GtkConcatModel *model;
-
- model = gtk_shortcut_manager_get_model (self,
- gtk_event_controller_get_propagation_phase (GTK_EVENT_CONTROLLER (controller)));
- if (model)
- gtk_concat_model_append (model, G_LIST_MODEL (controller));
-}
-
-static void
-gtk_shortcut_manager_default_remove_controller (GtkShortcutManager *self,
- GtkShortcutController *controller)
-{
- GtkConcatModel *model;
-
- model = gtk_shortcut_manager_get_model (self,
- gtk_event_controller_get_propagation_phase (GTK_EVENT_CONTROLLER (controller)));
- if (model)
- gtk_concat_model_remove (model, G_LIST_MODEL (controller));
-}
-
-static void
-gtk_shortcut_manager_default_init (GtkShortcutManagerInterface *iface)
-{
- iface->add_controller = gtk_shortcut_manager_default_add_controller;
- iface->remove_controller = gtk_shortcut_manager_default_remove_controller;
-}
-
diff --git a/gtk/gtkshortcutmanager.h b/gtk/gtkshortcutmanager.h
deleted file mode 100644
index 0d4ece9745..0000000000
--- a/gtk/gtkshortcutmanager.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_MANAGER_H__
-#define __GTK_SHORTCUT_MANAGER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtkshortcutcontroller.h>
-#include <gtk/gtkwidget.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_MANAGER (gtk_shortcut_manager_get_type ())
-
-GDK_AVAILABLE_IN_ALL
-G_DECLARE_INTERFACE (GtkShortcutManager, gtk_shortcut_manager, GTK, SHORTCUT_MANAGER, GtkWidget)
-
-/**
- * GtkShortcutManager:
- *
- * This object is used to implement support for #GtkShortcutScopes. Every
- * widget that implements #GtkShortcutManager will be used as a
- * %GTK_SHORTCUT_SCOPE_MANAGED.
- */
-
-/**
- * GtkShortcutManagerInterface:
- * @add_controller: Add a #GtkShortcutController to be managed.
- * @remove_controller: Remove a #GtkShortcutController that had previously
- * been added.
- *
- * The list of functions that can be implemented for the #GtkShortcutManager interface.
- *
- * Note that no function is mandatory to implement, the default implementation will work
- * fine.
- */
-struct _GtkShortcutManagerInterface
-{
- /*< private >*/
- GTypeInterface g_iface;
-
- /*< public >*/
- void (* add_controller) (GtkShortcutManager *self,
- GtkShortcutController *controller);
- void (* remove_controller) (GtkShortcutManager *self,
- GtkShortcutController *controller);
-};
-
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_MANAGER_H__ */
diff --git a/gtk/gtkshortcutmanagerprivate.h b/gtk/gtkshortcutmanagerprivate.h
deleted file mode 100644
index 72424dba23..0000000000
--- a/gtk/gtkshortcutmanagerprivate.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __GTK_SHORTCUT_MANAGER_PRIVATE_H__
-#define __GTK_SHORTCUT_MANAGER__PRIVATE_H__
-
-#include "gtkshortcutmanager.h"
-
-G_BEGIN_DECLS
-
-void gtk_shortcut_manager_create_controllers (GtkWidget *widget);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_MANAGER_PRIVATE_H__ */
diff --git a/gtk/gtkshortcutssection.c b/gtk/gtkshortcutssection.c
index 337ece2539..6a95e348a1 100644
--- a/gtk/gtkshortcutssection.c
+++ b/gtk/gtkshortcutssection.c
@@ -30,6 +30,7 @@
#include "gtkorientable.h"
#include "gtksizegroup.h"
#include "gtkwidget.h"
+#include "gtkbindings.h"
#include "gtkprivate.h"
#include "gtkmarshalers.h"
#include "gtkgesturepan.h"
@@ -306,6 +307,7 @@ gtk_shortcuts_section_class_init (GtkShortcutsSectionClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set;
object_class->finalize = gtk_shortcuts_section_finalize;
object_class->get_property = gtk_shortcuts_section_get_property;
@@ -386,23 +388,23 @@ gtk_shortcuts_section_class_init (GtkShortcutsSectionClass *klass)
G_TYPE_BOOLEAN, 1,
G_TYPE_INT);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Up, 0,
- "change-current-page",
- "(i)", -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Down, 0,
- "change-current-page",
- "(i)", 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Up, GDK_CONTROL_MASK,
- "change-current-page",
- "(i)", -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Page_Down, GDK_CONTROL_MASK,
- "change-current-page",
- "(i)", 1);
-
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Up, 0,
+ "change-current-page", 1,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Down, 0,
+ "change-current-page", 1,
+ G_TYPE_INT, 1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, -1);
+ gtk_binding_entry_add_signal (binding_set,
+ GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+ "change-current-page", 1,
+ G_TYPE_INT, 1);
gtk_widget_class_set_css_name (widget_class, I_("shortcuts-section"));
}
diff --git a/gtk/gtkshortcutswindow.c b/gtk/gtkshortcutswindow.c
index a2d580f0eb..292b1171be 100644
--- a/gtk/gtkshortcutswindow.c
+++ b/gtk/gtkshortcutswindow.c
@@ -20,6 +20,7 @@
#include "gtkshortcutswindowprivate.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkgrid.h"
#include "gtkheaderbar.h"
@@ -773,6 +774,7 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set = gtk_binding_set_by_class (klass);
object_class->constructed = gtk_shortcuts_window_constructed;
object_class->finalize = gtk_shortcuts_window_finalize;
@@ -854,14 +856,8 @@ gtk_shortcuts_window_class_init (GtkShortcutsWindowClass *klass)
G_TYPE_NONE,
0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Escape, 0,
- "close",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_f, GDK_CONTROL_MASK,
- "search",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Escape, 0, "close", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, "search", 0);
g_type_ensure (GTK_TYPE_SHORTCUTS_GROUP);
g_type_ensure (GTK_TYPE_SHORTCUTS_SHORTCUT);
diff --git a/gtk/gtkshortcuttrigger.c b/gtk/gtkshortcuttrigger.c
deleted file mode 100644
index dce75a1191..0000000000
--- a/gtk/gtkshortcuttrigger.c
+++ /dev/null
@@ -1,976 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-/**
- * SECTION:gtkshortcuttrigger
- * @Title: GtkShortcutTrigger
- * @Short_description: Triggers to track if shortcuts should be activated
- * @See_also: #GtkShortcut
- *
- * #GtkShortcutTrigger is the object used to track if a #GtkShortcut should be
- * activated. For this purpose, gtk_shortcut_trigger_trigger() can be called
- * on a #GdkEvent.
- *
- * #GtkShortcutTriggers contain functions that allow easy presentation to end
- * users as well as being printed for debugging.
- *
- * All #GtkShortcutTriggers are immutable, you can only specify their properties
- * during construction. If you want to change a trigger, you have to replace it
- * with a new one.
- */
-
-#include "config.h"
-
-#include "gtkshortcuttrigger.h"
-
-#include "gtkaccelgroupprivate.h"
-
-typedef struct _GtkShortcutTriggerClass GtkShortcutTriggerClass;
-
-#define GTK_IS_SHORTCUT_TRIGGER_TYPE(trigger,type) (GTK_IS_SHORTCUT_TRIGGER (trigger) && (trigger)->trigger_class->trigger_type == (type))
-
-struct _GtkShortcutTrigger
-{
- const GtkShortcutTriggerClass *trigger_class;
-
- gatomicrefcount ref_count;
-};
-
-struct _GtkShortcutTriggerClass
-{
- GtkShortcutTriggerType trigger_type;
- gsize struct_size;
- const char *type_name;
-
- void (* finalize) (GtkShortcutTrigger *trigger);
- gboolean (* trigger) (GtkShortcutTrigger *trigger,
- GdkEvent *event,
- gboolean enable_mnemonics);
- guint (* hash) (GtkShortcutTrigger *trigger);
- int (* compare) (GtkShortcutTrigger *trigger1,
- GtkShortcutTrigger *trigger2);
- void (* print) (GtkShortcutTrigger *trigger,
- GString *string);
- gboolean (* print_label) (GtkShortcutTrigger *trigger,
- GdkDisplay *display,
- GString *string);
-};
-
-G_DEFINE_BOXED_TYPE (GtkShortcutTrigger, gtk_shortcut_trigger,
- gtk_shortcut_trigger_ref,
- gtk_shortcut_trigger_unref)
-
-static void
-gtk_shortcut_trigger_finalize (GtkShortcutTrigger *self)
-{
- self->trigger_class->finalize (self);
-
- g_free (self);
-}
-
-/*< private >
- * gtk_shortcut_trigger_new:
- * @trigger_class: class structure for this trigger
- *
- * Returns: (transfer full): the newly created #GtkShortcutTrigger
- */
-static GtkShortcutTrigger *
-gtk_shortcut_trigger_new (const GtkShortcutTriggerClass *trigger_class)
-{
- GtkShortcutTrigger *self;
-
- g_return_val_if_fail (trigger_class != NULL, NULL);
-
- self = g_malloc0 (trigger_class->struct_size);
- g_atomic_ref_count_init (&self->ref_count);
-
- self->trigger_class = trigger_class;
-
- return self;
-}
-
-/**
- * gtk_shortcut_trigger_ref:
- * @self: a #GtkShortcutTrigger
- *
- * Acquires a reference on the given #GtkShortcutTrigger.
- *
- * Returns: (transfer full): the #GtkShortcutTrigger with
- * an additional reference
- */
-GtkShortcutTrigger *
-gtk_shortcut_trigger_ref (GtkShortcutTrigger *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), NULL);
-
- g_atomic_ref_count_inc (&self->ref_count);
-
- return self;
-}
-
-/**
- * gtk_shortcut_trigger_unref:
- * @self: (transfer full): a #GtkShortcutTrigger
- *
- * Releases a reference on the given #GtkShortcutTrigger.
- *
- * If the reference was the last, the resources associated
- * to the trigger are freed.
- */
-void
-gtk_shortcut_trigger_unref (GtkShortcutTrigger *self)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_TRIGGER (self));
-
- if (g_atomic_ref_count_dec (&self->ref_count))
- gtk_shortcut_trigger_finalize (self);
-}
-
-/**
- * gtk_shortcut_trigger_get_trigger_type:
- * @self: a #GtkShortcutTrigger
- *
- * Returns the type of the @trigger.
- *
- * Returns: the type of the #GtkShortcutTrigger
- */
-GtkShortcutTriggerType
-gtk_shortcut_trigger_get_trigger_type (GtkShortcutTrigger *self)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), GTK_SHORTCUT_TRIGGER_NEVER);
-
- return self->trigger_class->trigger_type;
-}
-
-/**
- * gtk_shortcut_trigger_trigger:
- * @self: a #GtkShortcutTrigger
- * @event: the event to check
- * @enable_mnemonics: %TRUE if mnemonics should trigger. Usually the
- * value of this property is determined by checking that the passed
- * in @event is a Key event and has the right modifiers set.
- *
- * Checks if the given @event triggers @self. If so,
- * returns %TRUE.
- *
- * Returns: %TRUE if this event triggered the trigger
- **/
-gboolean
-gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), FALSE);
-
- return self->trigger_class->trigger (self, event, enable_mnemonics);
-}
-
-/**
- * gtk_shortcut_trigger_parse_string:
- * @string: the string to parse
- *
- * Tries to parse the given string into a trigger. On success,
- * the parsed trigger is returned. When parsing failed, %NULL is
- * returned.
- *
- * FIXME: Document the supported format here once we've figured
- * it out.
- * For now, this function only supports gtk_accelerator_parse() and
- * can only return a trigger of type %GTK_SHORTCUT_TRIGGER_KEYVAL.
- *
- * Returns: a new #GtkShortcutTrigger or %NULL on error
- **/
-GtkShortcutTrigger *
-gtk_shortcut_trigger_parse_string (const char *string)
-{
- GdkModifierType modifiers;
- guint keyval;
-
- g_return_val_if_fail (string != NULL, NULL);
-
- if (gtk_accelerator_parse (string, &keyval, &modifiers))
- return gtk_keyval_trigger_new (keyval, modifiers);
-
- return NULL;
-}
-
-/**
- * gtk_shortcut_trigger_to_string:
- * @self: a #GtkShortcutTrigger
- *
- * Prints the given trigger into a human-readable string.
- * This is a small wrapper around gdk_content_formats_print()
- * to help when debugging.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_trigger_to_string (GtkShortcutTrigger *self)
-{
- GString *string;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- string = g_string_new (NULL);
- gtk_shortcut_trigger_print (self, string);
-
- return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_trigger_print:
- * @self: a #GtkShortcutTrigger
- * @string: a #GString to print into
- *
- * Prints the given trigger into a string for the developer.
- * This is meant for debugging and logging.
- *
- * The form of the representation may change at any time
- * and is not guaranteed to stay identical.
- **/
-void
-gtk_shortcut_trigger_print (GtkShortcutTrigger *self,
- GString *string)
-{
- g_return_if_fail (GTK_IS_SHORTCUT_TRIGGER (self));
- g_return_if_fail (string != NULL);
-
- return self->trigger_class->print (self, string);
-}
-
-/**
- * gtk_shortcut_trigger_to_label:
- * @self: a #GtkShortcutTrigger
- * @display: #GdkDisplay to print for
- *
- * Gets textual representation for the given trigger. This
- * function is returning a translated string for presentation
- * to end users for example in menu items or in help texts.
- *
- * The @display in use may influence the resulting string in
- * various forms, such as resolving hardware keycodes or by
- * causing display-specific modifier names.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- *
- * Returns: (transfer full): a new string
- **/
-char *
-gtk_shortcut_trigger_to_label (GtkShortcutTrigger *self,
- GdkDisplay *display)
-{
- GString *string;
-
- g_return_val_if_fail (self != NULL, NULL);
-
- string = g_string_new (NULL);
- gtk_shortcut_trigger_print_label (self, display, string);
-
- return g_string_free (string, FALSE);
-}
-
-/**
- * gtk_shortcut_trigger_print_label:
- * @self: a #GtkShortcutTrigger
- * @display: #GdkDisplay to print for
- * @string: a #GString to print into
- *
- * Prints the given trigger into a string. This function is
- * returning a translated string for presentation to end users
- * for example in menu items or in help texts.
- *
- * The @display in use may influence the resulting string in
- * various forms, such as resolving hardware keycodes or by
- * causing display-specific modifier names.
- *
- * The form of the representation may change at any time and is
- * not guaranteed to stay identical.
- *
- * Returns: %TRUE if something was printed or %FALSE if the
- * trigger did not have a textual representation suitable
- * for end users.
- **/
-gboolean
-gtk_shortcut_trigger_print_label (GtkShortcutTrigger *self,
- GdkDisplay *display,
- GString *string)
-{
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (self), FALSE);
- g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
- g_return_val_if_fail (string != NULL, FALSE);
-
- return self->trigger_class->print_label (self, display, string);
-}
-
-/**
- * gtk_shortcut_trigger_hash:
- * @trigger: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- * Generates a hash value for a #GtkShortcutTrigger.
- *
- * The output of this function is guaranteed to be the same for a given
- * value only per-process. It may change between different processor
- * architectures or even different versions of GTK. Do not use this
- * function as a basis for building protocols or file formats.
- *
- * The types of @trigger is #gconstpointer only to allow use of this
- * function with #GHashTable. They must each be a #GtkShortcutTrigger.
- *
- * Returns: a hash value corresponding to @trigger
- **/
-guint
-gtk_shortcut_trigger_hash (gconstpointer trigger)
-{
- GtkShortcutTrigger *t = (GtkShortcutTrigger *) trigger;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger), 0);
-
- return t->trigger_class->hash (t);
-}
-
-/**
- * gtk_shortcut_trigger_equal:
- * @trigger1: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- * @trigger2: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- * Checks if @trigger1 and @trigger2 trigger under the same conditions.
- *
- * The types of @one and @two are #gconstpointer only to allow use of this
- * function with #GHashTable. They must each be a #GtkShortcutTrigger.
- *
- * Returns: %TRUE if @trigger1 and @trigger2 are equal
- **/
-gboolean
-gtk_shortcut_trigger_equal (gconstpointer trigger1,
- gconstpointer trigger2)
-{
- return gtk_shortcut_trigger_compare (trigger1, trigger2) == 0;
-}
-
-/**
- * gtk_shortcut_trigger_compare:
- * @trigger1: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- * @trigger2: (type GtkShortcutTrigger): a #GtkShortcutTrigger
- *
- *
- * The types of @one and @two are #gconstpointer only to allow use of this
- * function as a #GCompareFunc. They must each be a #GtkShortcutTrigger.
- *
- * Returns: An integer less than, equal to, or greater than zero if
- * @trigger1 is found, respectively, to be less than, to match,
- * or be greater than @trigger2.
- **/
-gint
-gtk_shortcut_trigger_compare (gconstpointer trigger1,
- gconstpointer trigger2)
-{
- GtkShortcutTrigger *t1 = (GtkShortcutTrigger *) trigger1;
- GtkShortcutTrigger *t2 = (GtkShortcutTrigger *) trigger2;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger1), -1);
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (trigger2), 1);
-
- if (t1->trigger_class != t2->trigger_class)
- return t1->trigger_class->trigger_type - t2->trigger_class->trigger_type;
-
- return t1->trigger_class->compare (t1, t2);
-}
-
-/*** GTK_SHORTCUT_TRIGGER_NEVER ***/
-
-typedef struct _GtkNeverTrigger GtkNeverTrigger;
-
-struct _GtkNeverTrigger
-{
- GtkShortcutTrigger trigger;
-
- guint never;
- GdkModifierType modifiers;
-};
-
-static void
-gtk_never_trigger_finalize (GtkShortcutTrigger *trigger)
-{
- g_assert_not_reached ();
-}
-
-static gboolean
-gtk_never_trigger_trigger (GtkShortcutTrigger *trigger,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- return FALSE;
-}
-
-static guint
-gtk_never_trigger_hash (GtkShortcutTrigger *trigger)
-{
- return GTK_SHORTCUT_TRIGGER_NEVER;
-}
-
-static int
-gtk_never_trigger_compare (GtkShortcutTrigger *trigger1,
- GtkShortcutTrigger *trigger2)
-{
- return 0;
-}
-
-static void
-gtk_never_trigger_print (GtkShortcutTrigger *trigger,
- GString *string)
-
-{
- g_string_append (string, "<never>");
-}
-
-static gboolean
-gtk_never_trigger_print_label (GtkShortcutTrigger *trigger,
- GdkDisplay *display,
- GString *string)
-{
- return FALSE;
-}
-
-static const GtkShortcutTriggerClass GTK_NEVER_TRIGGER_CLASS = {
- GTK_SHORTCUT_TRIGGER_NEVER,
- sizeof (GtkNeverTrigger),
- "GtkNeverTrigger",
- gtk_never_trigger_finalize,
- gtk_never_trigger_trigger,
- gtk_never_trigger_hash,
- gtk_never_trigger_compare,
- gtk_never_trigger_print,
- gtk_never_trigger_print_label
-};
-
-static GtkNeverTrigger never = { { &GTK_NEVER_TRIGGER_CLASS, 1 } };
-
-/**
- * gtk_never_trigger_get:
- *
- * Gets the never trigger. This is a singleton for a trigger
- * that never triggers. Use this trigger instead of %NULL
- * because it implements all virtual functions.
- *
- * Returns: (transfer none): The never trigger
- */
-GtkShortcutTrigger *
-gtk_never_trigger_get (void)
-{
- return &never.trigger;
-}
-
-/*** GTK_KEYVAL_TRIGGER ***/
-
-typedef struct _GtkKeyvalTrigger GtkKeyvalTrigger;
-
-struct _GtkKeyvalTrigger
-{
- GtkShortcutTrigger trigger;
-
- guint keyval;
- GdkModifierType modifiers;
-};
-
-static void
-gtk_keyval_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-}
-
-static gboolean
-gtk_keyval_trigger_trigger (GtkShortcutTrigger *trigger,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
- GdkModifierType modifiers;
- guint keyval;
-
- if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
- return FALSE;
-
- /* XXX: This needs to deal with groups */
- modifiers = gdk_event_get_modifier_state (event);
- keyval = gdk_key_event_get_keyval (event);
-
- if (keyval == GDK_KEY_ISO_Left_Tab)
- keyval = GDK_KEY_Tab;
- else
- keyval = gdk_keyval_to_lower (keyval);
-
- return keyval == self->keyval && modifiers == self->modifiers;
-}
-
-static guint
-gtk_keyval_trigger_hash (GtkShortcutTrigger *trigger)
-{
- GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-
- return (self->modifiers << 24)
- | (self->modifiers >> 8)
- | (self->keyval << 16)
- | GTK_SHORTCUT_TRIGGER_KEYVAL;
-}
-
-static int
-gtk_keyval_trigger_compare (GtkShortcutTrigger *trigger1,
- GtkShortcutTrigger *trigger2)
-{
- GtkKeyvalTrigger *self1 = (GtkKeyvalTrigger *) trigger1;
- GtkKeyvalTrigger *self2 = (GtkKeyvalTrigger *) trigger2;
-
- if (self1->modifiers != self2->modifiers)
- return self2->modifiers - self1->modifiers;
-
- return self1->keyval - self2->keyval;
-}
-
-static void
-gtk_keyval_trigger_print (GtkShortcutTrigger *trigger,
- GString *string)
-
-{
- GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
- char *accelerator_name;
-
- accelerator_name = gtk_accelerator_name (self->keyval, self->modifiers);
- g_string_append (string, accelerator_name);
- g_free (accelerator_name);
-}
-
-static gboolean
-gtk_keyval_trigger_print_label (GtkShortcutTrigger *trigger,
- GdkDisplay *display,
- GString *string)
-{
- GtkKeyvalTrigger *self = (GtkKeyvalTrigger *) trigger;
-
- gtk_accelerator_print_label (string, self->keyval, self->modifiers);
-
- return TRUE;
-}
-
-static const GtkShortcutTriggerClass GTK_KEYVAL_TRIGGER_CLASS = {
- GTK_SHORTCUT_TRIGGER_KEYVAL,
- sizeof (GtkKeyvalTrigger),
- "GtkKeyvalTrigger",
- gtk_keyval_trigger_finalize,
- gtk_keyval_trigger_trigger,
- gtk_keyval_trigger_hash,
- gtk_keyval_trigger_compare,
- gtk_keyval_trigger_print,
- gtk_keyval_trigger_print_label
-};
-
-/**
- * gtk_keyval_trigger_new:
- * @keyval: The keyval to trigger for
- * @modifiers: the modifiers that need to be present
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever
- * the key with the given @keyval and @modifiers is pressed.
- *
- * Returns: A new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_keyval_trigger_new (guint keyval,
- GdkModifierType modifiers)
-{
- GtkKeyvalTrigger *self;
-
- self = (GtkKeyvalTrigger *) gtk_shortcut_trigger_new (&GTK_KEYVAL_TRIGGER_CLASS);
-
- /* We store keyvals as lower key */
- if (keyval == GDK_KEY_ISO_Left_Tab)
- self->keyval = GDK_KEY_Tab;
- else
- self->keyval = gdk_keyval_to_lower (keyval);
- self->modifiers = modifiers;
-
- return &self->trigger;
-}
-
-/**
- * gtk_keyval_trigger_get_modifiers:
- * @self: a keyval #GtkShortcutTrigger
- *
- * Gets the modifiers that must be present to succeed
- * triggering @self.
- *
- * Returns: the modifiers
- **/
-GdkModifierType
-gtk_keyval_trigger_get_modifiers (GtkShortcutTrigger *self)
-{
- GtkKeyvalTrigger *trigger = (GtkKeyvalTrigger *) self;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_KEYVAL), 0);
-
- return trigger->modifiers;
-}
-
-/**
- * gtk_keyval_trigger_get_keyval:
- * @self: a keyval #GtkShortcutTrigger
- *
- * Gets the keyval that must be pressed to succeed
- * triggering @self.
- *
- * Returns: the keyval
- **/
-guint
-gtk_keyval_trigger_get_keyval (GtkShortcutTrigger *self)
-{
- GtkKeyvalTrigger *trigger = (GtkKeyvalTrigger *) self;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_KEYVAL), 0);
-
- return trigger->keyval;
-}
-
-/*** GTK_MNEMONIC_TRIGGER ***/
-
-typedef struct _GtkMnemonicTrigger GtkMnemonicTrigger;
-
-struct _GtkMnemonicTrigger
-{
- GtkShortcutTrigger trigger;
-
- guint keyval;
-};
-
-static void
-gtk_mnemonic_trigger_finalize (GtkShortcutTrigger *trigger)
-{
-}
-
-static gboolean
-gtk_mnemonic_trigger_trigger (GtkShortcutTrigger *trigger,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
- guint keyval;
-
- if (!enable_mnemonics)
- return FALSE;
-
- if (gdk_event_get_event_type (event) != GDK_KEY_PRESS)
- return FALSE;
-
- /* XXX: This needs to deal with groups */
- keyval = gdk_key_event_get_keyval (event);
-
- if (keyval == GDK_KEY_ISO_Left_Tab)
- keyval = GDK_KEY_Tab;
- else
- keyval = gdk_keyval_to_lower (keyval);
-
- return keyval == self->keyval;
-}
-
-static guint
-gtk_mnemonic_trigger_hash (GtkShortcutTrigger *trigger)
-{
- GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-
- return (self->keyval << 8)
- | GTK_SHORTCUT_TRIGGER_MNEMONIC;
-}
-
-static int
-gtk_mnemonic_trigger_compare (GtkShortcutTrigger *trigger1,
- GtkShortcutTrigger *trigger2)
-{
- GtkMnemonicTrigger *self1 = (GtkMnemonicTrigger *) trigger1;
- GtkMnemonicTrigger *self2 = (GtkMnemonicTrigger *) trigger2;
-
- return self1->keyval - self2->keyval;
-}
-
-static void
-gtk_mnemonic_trigger_print (GtkShortcutTrigger *trigger,
- GString *string)
-{
- GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
- const char *keyval_str;
-
- keyval_str = gdk_keyval_name (self->keyval);
- if (keyval_str == NULL)
- keyval_str = "???";
-
- g_string_append (string, "<Mnemonic>");
- g_string_append (string, keyval_str);
-}
-
-static gboolean
-gtk_mnemonic_trigger_print_label (GtkShortcutTrigger *trigger,
- GdkDisplay *display,
- GString *string)
-{
- GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
- const char *keyval_str;
-
- keyval_str = gdk_keyval_name (self->keyval);
- if (keyval_str == NULL)
- return FALSE;
-
- g_string_append (string, keyval_str);
-
- return TRUE;
-}
-
-static const GtkShortcutTriggerClass GTK_MNEMONIC_TRIGGER_CLASS = {
- GTK_SHORTCUT_TRIGGER_MNEMONIC,
- sizeof (GtkMnemonicTrigger),
- "GtkMnemonicTrigger",
- gtk_mnemonic_trigger_finalize,
- gtk_mnemonic_trigger_trigger,
- gtk_mnemonic_trigger_hash,
- gtk_mnemonic_trigger_compare,
- gtk_mnemonic_trigger_print,
- gtk_mnemonic_trigger_print_label
-};
-
-/**
- * gtk_mnemonic_trigger_new:
- * @keyval: The keyval to trigger for
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever the key with
- * the given @keyval is pressed and mnemonics have been activated.
- *
- * Mnemonics are activated by calling code when a key event with the right
- * modifiers is detected.
- *
- * Returns: A new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_mnemonic_trigger_new (guint keyval)
-{
- GtkMnemonicTrigger *self;
-
- self = (GtkMnemonicTrigger *) gtk_shortcut_trigger_new (&GTK_MNEMONIC_TRIGGER_CLASS);
-
- /* We store keyvals as lower key */
- if (keyval == GDK_KEY_ISO_Left_Tab)
- self->keyval = GDK_KEY_Tab;
- else
- self->keyval = gdk_keyval_to_lower (keyval);
-
- return &self->trigger;
-}
-
-/**
- * gtk_mnemonic_trigger_get_keyval:
- * @trigger: a mnemonic #GtkShortcutTrigger
- *
- * Gets the keyval that must be pressed to succeed triggering @self.
- *
- * Returns: the keyval
- **/
-guint
-gtk_mnemonic_trigger_get_keyval (GtkShortcutTrigger *trigger)
-{
- GtkMnemonicTrigger *self = (GtkMnemonicTrigger *) trigger;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (trigger, GTK_SHORTCUT_TRIGGER_MNEMONIC), 0);
-
- return self->keyval;
-}
-
-/*** GTK_ALTERNATIVE_TRIGGER ***/
-
-typedef struct _GtkAlternativeTrigger GtkAlternativeTrigger;
-
-struct _GtkAlternativeTrigger
-{
- GtkShortcutTrigger trigger;
-
- GtkShortcutTrigger *first;
- GtkShortcutTrigger *second;
-};
-
-static void
-gtk_alternative_trigger_finalize (GtkShortcutTrigger *trigger)
-{
- GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
- gtk_shortcut_trigger_unref (self->first);
- gtk_shortcut_trigger_unref (self->second);
-}
-
-static gboolean
-gtk_alternative_trigger_trigger (GtkShortcutTrigger *trigger,
- GdkEvent *event,
- gboolean enable_mnemonics)
-{
- GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
- if (gtk_shortcut_trigger_trigger (self->first, event, enable_mnemonics))
- return TRUE;
-
- if (gtk_shortcut_trigger_trigger (self->second, event, enable_mnemonics))
- return TRUE;
-
- return FALSE;
-}
-
-static guint
-gtk_alternative_trigger_hash (GtkShortcutTrigger *trigger)
-{
- GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
- guint result;
-
- result = gtk_shortcut_trigger_hash (self->first);
- result <<= 5;
-
- result |= gtk_shortcut_trigger_hash (self->second);
- result <<= 5;
-
- return result | GTK_SHORTCUT_TRIGGER_ALTERNATIVE;
-}
-
-static int
-gtk_alternative_trigger_compare (GtkShortcutTrigger *trigger1,
- GtkShortcutTrigger *trigger2)
-{
- GtkAlternativeTrigger *self1 = (GtkAlternativeTrigger *) trigger1;
- GtkAlternativeTrigger *self2 = (GtkAlternativeTrigger *) trigger2;
- int cmp;
-
- cmp = gtk_shortcut_trigger_compare (self1->first, self2->first);
- if (cmp != 0)
- return cmp;
-
- return gtk_shortcut_trigger_compare (self1->second, self2->second);
-}
-
-static void
-gtk_alternative_trigger_print (GtkShortcutTrigger *trigger,
- GString *string)
-{
- GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
- gtk_shortcut_trigger_print (self->first, string);
- g_string_append (string, ", ");
- gtk_shortcut_trigger_print (self->second, string);
-}
-
-static gboolean
-gtk_alternative_trigger_print_label (GtkShortcutTrigger *trigger,
- GdkDisplay *display,
- GString *string)
-{
- GtkAlternativeTrigger *self = (GtkAlternativeTrigger *) trigger;
-
- if (gtk_shortcut_trigger_print_label (self->first, display, string))
- {
- g_string_append (string, ", ");
- if (!gtk_shortcut_trigger_print_label (self->second, display, string))
- g_string_truncate (string, string->len - 2);
- return TRUE;
- }
- else
- {
- return gtk_shortcut_trigger_print_label (self->second, display, string);
- }
-}
-
-static const GtkShortcutTriggerClass GTK_ALTERNATIVE_TRIGGER_CLASS = {
- GTK_SHORTCUT_TRIGGER_ALTERNATIVE,
- sizeof (GtkAlternativeTrigger),
- "GtkAlternativeTrigger",
- gtk_alternative_trigger_finalize,
- gtk_alternative_trigger_trigger,
- gtk_alternative_trigger_hash,
- gtk_alternative_trigger_compare,
- gtk_alternative_trigger_print,
- gtk_alternative_trigger_print_label
-};
-
-/**
- * gtk_alternative_trigger_new:
- * @first: (transfer full): The first trigger that may trigger
- * @second: (transfer full): The second trigger that may trigger
- *
- * Creates a #GtkShortcutTrigger that will trigger whenever
- * either of the two given triggers gets triggered.
- *
- * Note that nesting is allowed, so if you want more than two
- * alternative, create a new alternative trigger for each option.
- *
- * Returns: a new #GtkShortcutTrigger
- */
-GtkShortcutTrigger *
-gtk_alternative_trigger_new (GtkShortcutTrigger *first,
- GtkShortcutTrigger *second)
-{
- GtkAlternativeTrigger *self;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (first), NULL);
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER (second), NULL);
-
- self = (GtkAlternativeTrigger *) gtk_shortcut_trigger_new (&GTK_ALTERNATIVE_TRIGGER_CLASS);
-
- self->first = first;
- self->second = second;
-
- return &self->trigger;
-}
-
-/**
- * gtk_alternative_trigger_get_first:
- * @self: an alternative #GtkShortcutTrigger
- *
- * Gets the first of the two alternative triggers that may
- * trigger @self. gtk_alternative_trigger_get_second() will
- * return the other one.
- *
- * Returns: (transfer none): the first alternative trigger
- **/
-GtkShortcutTrigger *
-gtk_alternative_trigger_get_first (GtkShortcutTrigger *self)
-{
- GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
-
- return trigger->first;
-}
-
-/**
- * gtk_alternative_trigger_get_second:
- * @self: an alternative #GtkShortcutTrigger
- *
- * Gets the second of the two alternative triggers that may
- * trigger @self. gtk_alternative_trigger_get_first() will
- * return the other one.
- *
- * Returns: (transfer none): the second alternative trigger
- **/
-GtkShortcutTrigger *
-gtk_alternative_trigger_get_second (GtkShortcutTrigger *self)
-{
- GtkAlternativeTrigger *trigger = (GtkAlternativeTrigger *) self;
-
- g_return_val_if_fail (GTK_IS_SHORTCUT_TRIGGER_TYPE (self, GTK_SHORTCUT_TRIGGER_ALTERNATIVE), 0);
-
- return trigger->second;
-}
diff --git a/gtk/gtkshortcuttrigger.h b/gtk/gtkshortcuttrigger.h
deleted file mode 100644
index b0ab8af862..0000000000
--- a/gtk/gtkshortcuttrigger.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright © 2018 Benjamin Otte
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors: Benjamin Otte <otte@gnome.org>
- */
-
-#ifndef __GTK_SHORTCUT_TRIGGER_H__
-#define __GTK_SHORTCUT_TRIGGER_H__
-
-#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
-#error "Only <gtk/gtk.h> can be included directly."
-#endif
-
-#include <gtk/gtktypes.h>
-
-G_BEGIN_DECLS
-
-#define GTK_TYPE_SHORTCUT_TRIGGER (gtk_shortcut_trigger_get_type ())
-
-#define GTK_IS_SHORTCUT_TRIGGER(obj) ((obj) != NULL)
-
-/**
- * GtkShortcutTriggerType:
- * @GTK_SHORTCUT_TRIGGER_NEVER: Never ever trigger
- * @GTK_SHORTCUT_TRIGGER_KEYVAL: Trigger if a key event with matching
- * modifiers and keyval is received.
- * @GTK_SHORTCUT_TRIGGER_MNEMONIC: Trigger if a key event with matching
- * keyval is received and mnemonics are enabled for this event.
- * @GTK_SHORTCUT_TRIGGER_ALTERNAITVE: Trigger if either if two
- * alternatives triggers
- *
- * The type of a trigger determines what the trigger triggers on.
- **/
-typedef enum {
- GTK_SHORTCUT_TRIGGER_NEVER,
- GTK_SHORTCUT_TRIGGER_KEYVAL,
- GTK_SHORTCUT_TRIGGER_MNEMONIC,
- GTK_SHORTCUT_TRIGGER_ALTERNATIVE
-} GtkShortcutTriggerType;
-
-GDK_AVAILABLE_IN_ALL
-GType gtk_shortcut_trigger_get_type (void) G_GNUC_CONST;
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_shortcut_trigger_ref (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_trigger_unref (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTriggerType gtk_shortcut_trigger_get_trigger_type (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_shortcut_trigger_parse_string (const char *string);
-
-GDK_AVAILABLE_IN_ALL
-char * gtk_shortcut_trigger_to_string (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-void gtk_shortcut_trigger_print (GtkShortcutTrigger *self,
- GString *string);
-GDK_AVAILABLE_IN_ALL
-char * gtk_shortcut_trigger_to_label (GtkShortcutTrigger *self,
- GdkDisplay *display);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_shortcut_trigger_print_label (GtkShortcutTrigger *self,
- GdkDisplay *display,
- GString *string);
-
-GDK_AVAILABLE_IN_ALL
-guint gtk_shortcut_trigger_hash (gconstpointer trigger);
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_shortcut_trigger_equal (gconstpointer trigger1,
- gconstpointer trigger2);
-GDK_AVAILABLE_IN_ALL
-gint gtk_shortcut_trigger_compare (gconstpointer trigger1,
- gconstpointer trigger2);
-
-GDK_AVAILABLE_IN_ALL
-gboolean gtk_shortcut_trigger_trigger (GtkShortcutTrigger *self,
- GdkEvent *event,
- gboolean enable_mnemonics);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_never_trigger_get (void);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_keyval_trigger_new (guint keyval,
- GdkModifierType modifiers);
-GDK_AVAILABLE_IN_ALL
-GdkModifierType gtk_keyval_trigger_get_modifiers (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-guint gtk_keyval_trigger_get_keyval (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_mnemonic_trigger_new (guint keyval);
-GDK_AVAILABLE_IN_ALL
-guint gtk_mnemonic_trigger_get_keyval (GtkShortcutTrigger *self);
-
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_alternative_trigger_new (GtkShortcutTrigger *one,
- GtkShortcutTrigger *two);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_alternative_trigger_get_first (GtkShortcutTrigger *self);
-GDK_AVAILABLE_IN_ALL
-GtkShortcutTrigger * gtk_alternative_trigger_get_second (GtkShortcutTrigger *self);
-
-G_END_DECLS
-
-#endif /* __GTK_SHORTCUT_TRIGGER_H__ */
diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c
index 0176797f1e..548bac5f16 100644
--- a/gtk/gtkspinbutton.c
+++ b/gtk/gtkspinbutton.c
@@ -30,6 +30,7 @@
#include "gtkspinbutton.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbutton.h"
#include "gtkcssstylepropertyprivate.h"
@@ -316,10 +317,10 @@ G_DEFINE_TYPE_WITH_CODE (GtkSpinButton, gtk_spin_button, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_CELL_EDITABLE,
gtk_spin_button_cell_editable_init))
-#define add_spin_binding(widget_class, keyval, mask, scroll) \
- gtk_widget_class_add_binding_signal (widget_class, keyval, mask, \
- "change-value", \
- "(i)", scroll)
+#define add_spin_binding(binding_set, keyval, mask, scroll) \
+ gtk_binding_entry_add_signal (binding_set, keyval, mask, \
+ "change-value", 1, \
+ GTK_TYPE_SCROLL_TYPE, scroll)
static gboolean
@@ -346,6 +347,7 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkBindingSet *binding_set;
gobject_class->finalize = gtk_spin_button_finalize;
gobject_class->set_property = gtk_spin_button_set_property;
@@ -543,16 +545,18 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
G_TYPE_NONE, 1,
GTK_TYPE_SCROLL_TYPE);
- add_spin_binding (widget_class, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
- add_spin_binding (widget_class, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
- add_spin_binding (widget_class, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
- add_spin_binding (widget_class, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
- add_spin_binding (widget_class, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
- add_spin_binding (widget_class, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_DOWN);
- add_spin_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END);
- add_spin_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START);
- add_spin_binding (widget_class, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_END);
- add_spin_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_START);
+ binding_set = gtk_binding_set_by_class (class);
+
+ add_spin_binding (binding_set, GDK_KEY_Up, 0, GTK_SCROLL_STEP_UP);
+ add_spin_binding (binding_set, GDK_KEY_KP_Up, 0, GTK_SCROLL_STEP_UP);
+ add_spin_binding (binding_set, GDK_KEY_Down, 0, GTK_SCROLL_STEP_DOWN);
+ add_spin_binding (binding_set, GDK_KEY_KP_Down, 0, GTK_SCROLL_STEP_DOWN);
+ add_spin_binding (binding_set, GDK_KEY_Page_Up, 0, GTK_SCROLL_PAGE_UP);
+ add_spin_binding (binding_set, GDK_KEY_Page_Down, 0, GTK_SCROLL_PAGE_DOWN);
+ add_spin_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK, GTK_SCROLL_END);
+ add_spin_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK, GTK_SCROLL_START);
+ add_spin_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK, GTK_SCROLL_END);
+ add_spin_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK, GTK_SCROLL_START);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SPIN_BUTTON_ACCESSIBLE);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index 70a5d5276c..b052cebb62 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -25,6 +25,7 @@
#include "gtkactionable.h"
#include "gtkadjustment.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbutton.h"
#include "gtkcssnodeprivate.h"
@@ -381,9 +382,7 @@ static void gtk_text_set_alignment (GtkText *self,
/* Default signal handlers
*/
static GMenuModel *gtk_text_get_menu_model (GtkText *self);
-static void gtk_text_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters);
+static gboolean gtk_text_popup_menu (GtkWidget *widget);
static void gtk_text_move_cursor (GtkText *self,
GtkMovementStep step,
int count,
@@ -680,7 +679,7 @@ G_DEFINE_TYPE_WITH_CODE (GtkText, gtk_text, GTK_TYPE_WIDGET,
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, gtk_text_editable_init))
static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
GtkMovementStep step,
@@ -688,22 +687,28 @@ add_move_binding (GtkWidgetClass *widget_class,
{
g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(iib)", step, count, FALSE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, FALSE);
+
/* Selection-extending version */
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | GDK_SHIFT_MASK,
- "move-cursor",
- "(iib)", step, count, TRUE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, TRUE);
}
static void
gtk_text_class_init (GtkTextClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GtkWidgetClass *widget_class;
+ GtkBindingSet *binding_set;
+
+ widget_class = (GtkWidgetClass*) class;
gobject_class->dispose = gtk_text_dispose;
gobject_class->finalize = gtk_text_finalize;
@@ -723,6 +728,7 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->state_flags_changed = gtk_text_state_flags_changed;
widget_class->root = gtk_text_root;
widget_class->mnemonic_activate = gtk_text_mnemonic_activate;
+ widget_class->popup_menu = gtk_text_popup_menu;
class->move_cursor = gtk_text_move_cursor;
class->insert_at_cursor = gtk_text_insert_at_cursor;
@@ -1190,217 +1196,187 @@ gtk_text_class_init (GtkTextClass *class)
gtk_widget_class_install_action (widget_class, "text.undo", NULL, gtk_text_real_undo);
gtk_widget_class_install_action (widget_class, "text.redo", NULL, gtk_text_real_redo);
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_text_popup_menu);
/*
* Key bindings
*/
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
+ binding_set = gtk_binding_set_by_class (class);
/* Moving the insertion point */
- add_move_binding (widget_class, GDK_KEY_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, 0,
+ add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
/* Select all
*/
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- (GtkShortcutFunc) gtk_text_select_all,
- NULL);
-
- gtk_widget_class_add_binding (widget_class,
- GDK_KEY_slash, GDK_CONTROL_MASK,
- (GtkShortcutFunc) gtk_text_select_all,
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+ G_TYPE_INT, -1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+ G_TYPE_INT, 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+ G_TYPE_INT, -1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_BUFFER_ENDS,
+ G_TYPE_INT, 1,
+ G_TYPE_BOOLEAN, TRUE);
/* Unselect all
*/
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_backslash, GDK_CONTROL_MASK,
- "move-cursor",
- "(iib)", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "move-cursor",
- "(iib)", GTK_MOVEMENT_VISUAL_POSITIONS, 0, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 0,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "move-cursor", 3,
+ GTK_TYPE_MOVEMENT_STEP, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 0,
+ G_TYPE_BOOLEAN, FALSE);
/* Activate
*/
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
- "activate",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
- "activate",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
- "activate",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate", 0);
/* Deleting text */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, 0,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_CHARS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, 0,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_CHARS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_CHARS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_CHARS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, 0,
- "backspace",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
+ "backspace", 0);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_u, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_PARAGRAPH_ENDS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_u, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+ G_TYPE_INT, -1);
/* Make this do the same as Backspace, to help with mis-typing */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, GDK_SHIFT_MASK,
- "backspace",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
+ "backspace", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, -1);
/* Cut/copy/paste */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_x, GDK_CONTROL_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_c, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_v, GDK_CONTROL_MASK,
- "paste-clipboard",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, GDK_SHIFT_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, GDK_SHIFT_MASK,
- "paste-clipboard",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
- "paste-clipboard",
- NULL);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
+ "paste-clipboard", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
+ "paste-clipboard", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
+ "paste-clipboard", 0);
/* Overwrite */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, 0,
- "toggle-overwrite",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, 0,
- "toggle-overwrite",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
+ "toggle-overwrite", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
+ "toggle-overwrite", 0);
/* Emoji */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_period, GDK_CONTROL_MASK,
- "insert-emoji",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_semicolon, GDK_CONTROL_MASK,
- "insert-emoji",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_period, GDK_CONTROL_MASK,
+ "insert-emoji", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_semicolon, GDK_CONTROL_MASK,
+ "insert-emoji", 0);
/* Undo/Redo */
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_z, GDK_CONTROL_MASK,
- "text.undo", NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_y, GDK_CONTROL_MASK,
- "text.redo", NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "text.redo", NULL);
-
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK,
+ "text.undo", NULL);
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_y, GDK_CONTROL_MASK,
+ "text.redo", NULL);
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "text.redo", NULL);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("text"));
@@ -5936,12 +5912,11 @@ gtk_text_mnemonic_activate (GtkWidget *widget,
return GDK_EVENT_STOP;
}
-static void
-gtk_text_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+static gboolean
+gtk_text_popup_menu (GtkWidget *widget)
{
gtk_text_do_popup (GTK_TEXT (widget), -1, -1);
+ return TRUE;
}
static void
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 60842f76f5..62687d0f29 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -30,6 +30,7 @@
#include <string.h>
#include "gtkadjustmentprivate.h"
+#include "gtkbindings.h"
#include "gtkcsscolorvalueprivate.h"
#include "gtkdebug.h"
#include "gtkdropcontrollermotion.h"
@@ -434,9 +435,7 @@ static gboolean gtk_text_view_drag_drop (GtkDropTarget *dest,
double y,
GtkTextView *text_view);
-static void gtk_text_view_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters);
+static gboolean gtk_text_view_popup_menu (GtkWidget *widget);
static void gtk_text_view_move_cursor (GtkTextView *text_view,
GtkMovementStep step,
gint count,
@@ -775,7 +774,7 @@ gtk_text_view_drop_scroll_leave (GtkDropControllerMotion *motion,
}
static void
-add_move_binding (GtkWidgetClass *widget_class,
+add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
GtkMovementStep step,
@@ -783,16 +782,18 @@ add_move_binding (GtkWidgetClass *widget_class,
{
g_assert ((modmask & GDK_SHIFT_MASK) == 0);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(iib)", step, count, FALSE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, FALSE);
/* Selection-extending version */
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask | GDK_SHIFT_MASK,
- "move-cursor",
- "(iib)", step, count, TRUE);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
+ "move-cursor", 3,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count,
+ G_TYPE_BOOLEAN, TRUE);
}
static void
@@ -801,6 +802,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkBindingSet *binding_set;
/* Default handlers and virtual methods
*/
@@ -820,6 +822,8 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
widget_class->snapshot = gtk_text_view_snapshot;
widget_class->focus = gtk_text_view_focus;
+ widget_class->popup_menu = gtk_text_view_popup_menu;
+
container_class->add = gtk_text_view_add;
container_class->remove = gtk_text_view_remove;
container_class->forall = gtk_text_view_forall;
@@ -1462,288 +1466,237 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
gtk_widget_class_install_action (widget_class, "text.undo", NULL, gtk_text_view_real_undo);
gtk_widget_class_install_action (widget_class, "text.redo", NULL, gtk_text_view_real_redo);
- gtk_widget_class_install_action (widget_class, "menu.popup", NULL, gtk_text_view_popup_menu);
/*
* Key bindings
*/
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_F10, GDK_SHIFT_MASK,
- "menu.popup",
- NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_Menu, 0,
- "menu.popup",
- NULL);
-
+ binding_set = gtk_binding_set_by_class (klass);
+
/* Moving the insertion point */
- add_move_binding (widget_class, GDK_KEY_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, 0,
GTK_MOVEMENT_VISUAL_POSITIONS, -1);
- add_move_binding (widget_class, GDK_KEY_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, 1);
- add_move_binding (widget_class, GDK_KEY_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
GTK_MOVEMENT_WORDS, -1);
- add_move_binding (widget_class, GDK_KEY_Up, 0,
+ add_move_binding (binding_set, GDK_KEY_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Up, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Up, 0,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- add_move_binding (widget_class, GDK_KEY_Down, 0,
+ add_move_binding (binding_set, GDK_KEY_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Down, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Down, 0,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- add_move_binding (widget_class, GDK_KEY_Up, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Up, GDK_CONTROL_MASK,
GTK_MOVEMENT_PARAGRAPHS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Up, GDK_CONTROL_MASK,
GTK_MOVEMENT_PARAGRAPHS, -1);
- add_move_binding (widget_class, GDK_KEY_Down, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Down, GDK_CONTROL_MASK,
GTK_MOVEMENT_PARAGRAPHS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Down, GDK_CONTROL_MASK,
GTK_MOVEMENT_PARAGRAPHS, 1);
- add_move_binding (widget_class, GDK_KEY_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, 0,
+ add_move_binding (binding_set, GDK_KEY_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_End, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_End, 0,
GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Home, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- add_move_binding (widget_class, GDK_KEY_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_KP_End, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_End, GDK_CONTROL_MASK,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- add_move_binding (widget_class, GDK_KEY_Page_Up, 0,
+ add_move_binding (binding_set, GDK_KEY_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0,
GTK_MOVEMENT_PAGES, -1);
- add_move_binding (widget_class, GDK_KEY_Page_Down, 0,
+ add_move_binding (binding_set, GDK_KEY_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0,
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0,
GTK_MOVEMENT_PAGES, 1);
- add_move_binding (widget_class, GDK_KEY_Page_Up, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Page_Up, GDK_CONTROL_MASK,
GTK_MOVEMENT_HORIZONTAL_PAGES, -1);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Up, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Up, GDK_CONTROL_MASK,
GTK_MOVEMENT_HORIZONTAL_PAGES, -1);
- add_move_binding (widget_class, GDK_KEY_Page_Down, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_Page_Down, GDK_CONTROL_MASK,
GTK_MOVEMENT_HORIZONTAL_PAGES, 1);
- add_move_binding (widget_class, GDK_KEY_KP_Page_Down, GDK_CONTROL_MASK,
+ add_move_binding (binding_set, GDK_KEY_KP_Page_Down, GDK_CONTROL_MASK,
GTK_MOVEMENT_HORIZONTAL_PAGES, 1);
/* Select all */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_CONTROL_MASK,
- "select-all",
- "(b)", TRUE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_slash, GDK_CONTROL_MASK,
- "select-all",
- "(b)", TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK,
+ "select-all", 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK,
+ "select-all", 1,
+ G_TYPE_BOOLEAN, TRUE);
/* Unselect all */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_backslash, GDK_CONTROL_MASK,
- "select-all",
- "(b)", FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK,
+ "select-all", 1,
+ G_TYPE_BOOLEAN, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "select-all",
- "(b)", FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "select-all", 1,
+ G_TYPE_BOOLEAN, FALSE);
/* Deleting text */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, 0,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_CHARS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, 0,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_CHARS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, 0,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_CHARS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, 0,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_CHARS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, 0,
- "backspace",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0,
+ "backspace", 0);
/* Make this do the same as Backspace, to help with mis-typing */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, GDK_SHIFT_MASK,
- "backspace",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK,
+ "backspace", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_WORD_ENDS, -1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_PARAGRAPH_ENDS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_PARAGRAPH_ENDS, 1);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_BackSpace, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "delete-from-cursor",
- "(ii)", GTK_DELETE_PARAGRAPH_ENDS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ G_TYPE_INT, -1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+ G_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "delete-from-cursor", 2,
+ G_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
+ G_TYPE_INT, -1);
/* Cut/copy/paste */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_x, GDK_CONTROL_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_c, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_v, GDK_CONTROL_MASK,
- "paste-clipboard",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
- "paste-clipboard",
- NULL);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Delete, GDK_SHIFT_MASK,
- "cut-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, GDK_CONTROL_MASK,
- "copy-clipboard",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, GDK_SHIFT_MASK,
- "paste-clipboard",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_x, GDK_CONTROL_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_c, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_v, GDK_CONTROL_MASK,
+ "paste-clipboard", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Delete, GDK_SHIFT_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, GDK_SHIFT_MASK,
+ "paste-clipboard", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Delete, GDK_SHIFT_MASK,
+ "cut-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_CONTROL_MASK,
+ "copy-clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, GDK_SHIFT_MASK,
+ "paste-clipboard", 0);
/* Undo/Redo */
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_z, GDK_CONTROL_MASK,
- "text.undo", NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_y, GDK_CONTROL_MASK,
- "text.redo", NULL);
- gtk_widget_class_add_binding_action (widget_class,
- GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "text.redo", NULL);
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK,
+ "text.undo", NULL);
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_y, GDK_CONTROL_MASK,
+ "text.redo", NULL);
+ gtk_binding_entry_add_action (binding_set, GDK_KEY_z, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "text.redo", NULL);
/* Overwrite */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Insert, 0,
- "toggle-overwrite",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Insert, 0,
- "toggle-overwrite",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Insert, 0,
+ "toggle-overwrite", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Insert, 0,
+ "toggle-overwrite", 0);
/* Emoji */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_period, GDK_CONTROL_MASK,
- "insert-emoji",
- NULL);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_semicolon, GDK_CONTROL_MASK,
- "insert-emoji",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_period, GDK_CONTROL_MASK,
+ "insert-emoji", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_semicolon, GDK_CONTROL_MASK,
+ "insert-emoji", 0);
/* Caret mode */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_F7, 0,
- "toggle-cursor-visible",
- NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_F7, 0,
+ "toggle-cursor-visible", 0);
/* Control-tab focus motion */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Tab, GDK_CONTROL_MASK,
- "move-focus",
- "(i)", GTK_DIR_TAB_FORWARD);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Tab, GDK_CONTROL_MASK,
- "move-focus",
- "(i)", GTK_DIR_TAB_FORWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "move-focus",
- "(i)", GTK_DIR_TAB_BACKWARD);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "move-focus",
- "(i)", GTK_DIR_TAB_BACKWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_VIEW_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("textview"));
@@ -4475,9 +4428,6 @@ gtk_text_view_size_allocate (GtkWidget *widget,
if (priv->popup_menu)
gtk_native_check_resize (GTK_NATIVE (priv->popup_menu));
-
- if (priv->selection_bubble)
- gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble));
}
static void
@@ -8705,12 +8655,11 @@ gtk_text_view_do_popup (GtkTextView *text_view,
gdk_event_unref (trigger_event);
}
-static void
-gtk_text_view_popup_menu (GtkWidget *widget,
- const char *action_name,
- GVariant *parameters)
+static gboolean
+gtk_text_view_popup_menu (GtkWidget *widget)
{
gtk_text_view_do_popup (GTK_TEXT_VIEW (widget), NULL);
+ return TRUE;
}
static void
diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c
index 51fa6d5229..a30d0c0973 100644
--- a/gtk/gtktreeview.c
+++ b/gtk/gtktreeview.c
@@ -22,6 +22,7 @@
#include "gtkadjustmentprivate.h"
#include "gtkbox.h"
+#include "gtkbindings.h"
#include "gtkbuildable.h"
#include "gtkbutton.h"
#include "gtkcelllayout.h"
@@ -53,7 +54,6 @@
#include "gtkrendericonprivate.h"
#include "gtkscrollable.h"
#include "gtksettingsprivate.h"
-#include "gtkshortcutcontroller.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
#include "gtktooltip.h"
@@ -657,11 +657,6 @@ static void gtk_tree_view_size_allocate (GtkWidget *widget,
static void gtk_tree_view_snapshot (GtkWidget *widget,
GtkSnapshot *snapshot);
-static gboolean gtk_tree_view_forward_controller_key_pressed (GtkEventControllerKey *key,
- guint keyval,
- guint keycode,
- GdkModifierType state,
- GtkTreeView *tree_view);
static gboolean gtk_tree_view_key_controller_key_pressed (GtkEventControllerKey *key,
guint keyval,
guint keycode,
@@ -770,7 +765,7 @@ static void invalidate_empty_focus (GtkTreeView *tree_view);
static gboolean gtk_tree_view_is_expander_column (GtkTreeView *tree_view,
GtkTreeViewColumn *column);
static inline gboolean gtk_tree_view_draw_expanders (GtkTreeView *tree_view);
-static void gtk_tree_view_add_move_binding (GtkWidgetClass *widget_class,
+static void gtk_tree_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
gboolean add_shifted_binding,
@@ -1004,9 +999,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkTreeView, gtk_tree_view, GTK_TYPE_CONTAINER,
static void
gtk_tree_view_class_init (GtkTreeViewClass *class)
{
- GObjectClass *o_class = G_OBJECT_CLASS (class);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
+ GObjectClass *o_class;
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
+
+ binding_set = gtk_binding_set_by_class (class);
+
+ o_class = (GObjectClass *) class;
+ widget_class = (GtkWidgetClass *) class;
+ container_class = (GtkContainerClass *) class;
/* GObject signals */
o_class->set_property = gtk_tree_view_set_property;
@@ -1501,198 +1503,217 @@ gtk_tree_view_class_init (GtkTreeViewClass *class)
_gtk_marshal_BOOLEAN__VOIDv);
/* Key bindings */
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Up, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Up, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Up, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Up, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Down, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Down, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Down, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Down, 0, TRUE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_p, GDK_CONTROL_MASK, FALSE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_p, GDK_CONTROL_MASK, FALSE,
GTK_MOVEMENT_DISPLAY_LINES, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_n, GDK_CONTROL_MASK, FALSE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_n, GDK_CONTROL_MASK, FALSE,
GTK_MOVEMENT_DISPLAY_LINES, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Home, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Home, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Home, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Home, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_End, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_End, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_End, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_End, 0, TRUE,
GTK_MOVEMENT_BUFFER_ENDS, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Page_Up, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Up, 0, TRUE,
GTK_MOVEMENT_PAGES, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Up, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Up, 0, TRUE,
GTK_MOVEMENT_PAGES, -1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_Page_Down, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_Page_Down, 0, TRUE,
GTK_MOVEMENT_PAGES, 1);
- gtk_tree_view_add_move_binding (widget_class, GDK_KEY_KP_Page_Down, 0, TRUE,
+ gtk_tree_view_add_move_binding (binding_set, GDK_KEY_KP_Page_Down, 0, TRUE,
GTK_MOVEMENT_PAGES, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Right, 0,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, 0, "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Left, 0,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, 0, "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Right, 0,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, 0, "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Left, 0,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, 0, "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Right, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Left, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, -1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Right, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, 1);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Left, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", GTK_MOVEMENT_VISUAL_POSITIONS, -1);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, GTK_MOVEMENT_VISUAL_POSITIONS,
+ G_TYPE_INT, -1);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-row", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_CONTROL_MASK, "toggle-cursor-row", 0);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_slash, GDK_CONTROL_MASK, "select-all", NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_a, GDK_CONTROL_MASK, "select-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, GDK_CONTROL_MASK, "select-all", 0);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_backslash, GDK_CONTROL_MASK, "unselect-all", NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_A, GDK_CONTROL_MASK | GDK_SHIFT_MASK, "unselect-all", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_backslash, GDK_CONTROL_MASK, "unselect-all", 0);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, GDK_SHIFT_MASK, "select-cursor-row", "(b)", TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", "(b)", TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, GDK_SHIFT_MASK, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, GDK_SHIFT_MASK, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0, "select-cursor-row", "(b)", TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0, "select-cursor-row", "(b)", TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0, "select-cursor-row", "(b)", TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0, "select-cursor-row", "(b)", TRUE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0, "select-cursor-row", "(b)", TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0, "select-cursor-row", 1,
+ G_TYPE_BOOLEAN, TRUE);
/* expand and collapse rows */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_plus, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, FALSE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_asterisk, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Multiply, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, TRUE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_slash, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Divide, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, 0, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_asterisk, 0,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Multiply, 0,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_slash, 0,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Divide, 0,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE);
/* Not doable on US keyboards */
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_plus, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Add, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Add, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Add, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Right, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Right, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Right, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, TRUE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Right, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, TRUE, TRUE);
-
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_minus, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_minus, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Subtract, 0,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, FALSE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Subtract, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", TRUE, FALSE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Left, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, FALSE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Left, GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, FALSE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_Left, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, FALSE, TRUE);
- gtk_widget_class_add_binding_signal (widget_class,
- GDK_KEY_KP_Left, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "expand-collapse-cursor-row",
- "(bbb)", FALSE, FALSE, TRUE);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_BackSpace, 0, "select-cursor-parent", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", NULL);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_f, GDK_CONTROL_MASK, "start-interactive-search", NULL);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_F, GDK_CONTROL_MASK, "start-interactive-search", NULL);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_plus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, 0, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Add, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right, GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right, GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Right,
+ GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Right,
+ GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, 0, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_minus, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, 0, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Subtract, GDK_SHIFT_MASK, "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left, GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left, GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Left,
+ GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Left,
+ GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "expand-collapse-cursor-row", 3,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, FALSE,
+ G_TYPE_BOOLEAN, TRUE);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, 0, "select-cursor-parent", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_BackSpace, GDK_CONTROL_MASK, "select-cursor-parent", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_f, GDK_CONTROL_MASK, "start-interactive-search", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_F, GDK_CONTROL_MASK, "start-interactive-search", 0);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TREE_VIEW_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, I_("treeview"));
@@ -1704,7 +1725,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
GtkCssNode *widget_node;
GtkGesture *gesture;
GtkEventController *controller;
- GList *list, *controllers;
gtk_widget_set_can_focus (GTK_WIDGET (tree_view), TRUE);
gtk_widget_set_overflow (GTK_WIDGET (tree_view), GTK_OVERFLOW_HIDDEN);
@@ -1766,24 +1786,6 @@ gtk_tree_view_init (GtkTreeView *tree_view)
gtk_css_node_set_state (tree_view->header_node, gtk_css_node_get_state (widget_node));
g_object_unref (tree_view->header_node);
- controller = gtk_event_controller_key_new ();
- g_signal_connect (controller, "key-pressed",
- G_CALLBACK (gtk_tree_view_forward_controller_key_pressed), tree_view);
- gtk_widget_add_controller (GTK_WIDGET (tree_view), controller);
-
- controllers = gtk_widget_list_controllers (GTK_WIDGET (tree_view), GTK_PHASE_BUBBLE);
- for (list = controllers; list; list = list->next)
- {
- if (GTK_IS_SHORTCUT_CONTROLLER (list->data))
- {
- g_object_ref (list->data);
- gtk_widget_remove_controller (GTK_WIDGET (tree_view), list->data);
- gtk_widget_add_controller (GTK_WIDGET (tree_view), list->data);
- break;
- }
- }
- g_list_free (controllers);
-
tree_view->click_gesture = gtk_gesture_click_new ();
gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (tree_view->click_gesture), 0);
g_signal_connect (tree_view->click_gesture, "pressed",
@@ -5310,6 +5312,7 @@ gtk_tree_view_key_controller_key_pressed (GtkEventControllerKey *key,
{
GtkWidget *widget = GTK_WIDGET (tree_view);
GtkWidget *button;
+ GdkEvent *event;
if (tree_view->rubber_band_status)
{
@@ -5429,16 +5432,16 @@ gtk_tree_view_key_controller_key_pressed (GtkEventControllerKey *key,
}
}
- return FALSE;
-}
+ /* Handle the keybindings. */
+ event = gtk_get_current_event ();
+ if (gtk_bindings_activate_event (G_OBJECT (widget), event))
+ {
+ gdk_event_unref (event);
+ return TRUE;
+ }
+
+ gdk_event_unref (event);
-static gboolean
-gtk_tree_view_forward_controller_key_pressed (GtkEventControllerKey *key,
- guint keyval,
- guint keycode,
- GdkModifierType state,
- GtkTreeView *tree_view)
-{
if (tree_view->search_entry_avoid_unhandled_binding)
{
tree_view->search_entry_avoid_unhandled_binding = FALSE;
@@ -5484,6 +5487,15 @@ gtk_tree_view_key_controller_key_released (GtkEventControllerKey *key,
GdkModifierType state,
GtkTreeView *tree_view)
{
+ GdkEvent *event;
+
+ if (tree_view->rubber_band_status)
+ return;
+
+ /* Handle the keybindings. */
+ event = gtk_get_current_event ();
+ gtk_bindings_activate_event (G_OBJECT (tree_view), event);
+ gdk_event_unref (event);
}
static void
@@ -8902,7 +8914,7 @@ gtk_tree_view_draw_expanders (GtkTreeView *tree_view)
}
static void
-gtk_tree_view_add_move_binding (GtkWidgetClass *widget_class,
+gtk_tree_view_add_move_binding (GtkBindingSet *binding_set,
guint keyval,
guint modmask,
gboolean add_shifted_binding,
@@ -8910,29 +8922,29 @@ gtk_tree_view_add_move_binding (GtkWidgetClass *widget_class,
gint count)
{
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, modmask,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, modmask,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
if (add_shifted_binding)
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, GDK_SHIFT_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_SHIFT_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
if ((modmask & GDK_CONTROL_MASK) == GDK_CONTROL_MASK)
return;
- gtk_widget_class_add_binding_signal (widget_class, keyval,
- GDK_CONTROL_MASK | GDK_SHIFT_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK | GDK_SHIFT_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
- gtk_widget_class_add_binding_signal (widget_class,
- keyval, GDK_CONTROL_MASK,
- "move-cursor",
- "(ii)", step, count);
+ gtk_binding_entry_add_signal (binding_set, keyval, GDK_CONTROL_MASK,
+ "move-cursor", 2,
+ G_TYPE_ENUM, step,
+ G_TYPE_INT, count);
}
static gint
diff --git a/gtk/gtktypes.h b/gtk/gtktypes.h
index 8edd13fcd1..a5ad190720 100644
--- a/gtk/gtktypes.h
+++ b/gtk/gtktypes.h
@@ -45,9 +45,6 @@ typedef struct _GtkNative GtkNative;
typedef struct _GtkRequisition GtkRequisition;
typedef struct _GtkRoot GtkRoot;
typedef struct _GtkSettings GtkSettings;
-typedef struct _GtkShortcut GtkShortcut;
-typedef struct _GtkShortcutAction GtkShortcutAction;
-typedef struct _GtkShortcutTrigger GtkShortcutTrigger;
typedef GdkSnapshot GtkSnapshot;
typedef struct _GtkStyleContext GtkStyleContext;
typedef struct _GtkTooltip GtkTooltip;
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 8a02f96012..634a50dbea 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -26,12 +26,13 @@
#include "gtkwidgetprivate.h"
+#include "gtkaccelmapprivate.h"
#include "gtkaccelgroupprivate.h"
#include "gtkaccessible.h"
#include "gtkapplicationprivate.h"
+#include "gtkbindings.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
-#include "gtkconcatmodelprivate.h"
#include "gtkcontainerprivate.h"
#include "gtkcssboxesprivate.h"
#include "gtkcssfiltervalueprivate.h"
@@ -58,11 +59,6 @@
#include "gtknativeprivate.h"
#include "gtkscrollable.h"
#include "gtksettingsprivate.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontrollerprivate.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcutmanagerprivate.h"
-#include "gtkshortcuttrigger.h"
#include "gtksizegroup-private.h"
#include "gtksnapshotprivate.h"
#include "gtkstylecontextprivate.h"
@@ -497,7 +493,6 @@ typedef struct {
struct _GtkWidgetClassPrivate
{
GtkWidgetTemplate *template;
- GListStore *shortcuts;
GType accessible_type;
AtkRole accessible_role;
GQuark css_name;
@@ -520,6 +515,7 @@ enum {
MNEMONIC_ACTIVATE,
MOVE_FOCUS,
KEYNAV_FAILED,
+ POPUP_MENU,
ACCEL_CLOSURES_CHANGED,
CAN_ACTIVATE_ACCEL,
QUERY_TOOLTIP,
@@ -705,6 +701,8 @@ static gpointer gtk_widget_parent_class = NULL;
static guint widget_signals[LAST_SIGNAL] = { 0 };
GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
+static GQuark quark_accel_path = 0;
+static GQuark quark_accel_closures = 0;
static GQuark quark_pango_context = 0;
static GQuark quark_mnemonic_labels = 0;
static GQuark quark_tooltip_markup = 0;
@@ -786,29 +784,9 @@ static void
gtk_widget_base_class_init (gpointer g_class)
{
GtkWidgetClass *klass = g_class;
- GtkWidgetClassPrivate *priv;
-
- priv = klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
-
- priv->template = NULL;
- if (priv->shortcuts == NULL)
- {
- priv->shortcuts = g_list_store_new (GTK_TYPE_SHORTCUT);
- }
- else
- {
- GListModel *parent_shortcuts = G_LIST_MODEL (priv->shortcuts);
- guint i;
-
- priv->shortcuts = g_list_store_new (GTK_TYPE_SHORTCUT);
- for (i = 0; i < g_list_model_get_n_items (parent_shortcuts); i++)
- {
- GtkShortcut *shortcut = g_list_model_get_item (parent_shortcuts, i);
- g_list_store_append (priv->shortcuts, shortcut);
- g_object_unref (shortcut);
- }
- }
+ klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
+ klass->priv->template = NULL;
}
static void
@@ -861,30 +839,12 @@ gtk_widget_real_grab_notify (GtkWidget *widget,
static void
gtk_widget_real_root (GtkWidget *widget)
{
- GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
- GList *l;
-
gtk_widget_forall (widget, (GtkCallback) gtk_widget_root, NULL);
-
- for (l = priv->event_controllers; l; l = l->next)
- {
- if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
- gtk_shortcut_controller_root (GTK_SHORTCUT_CONTROLLER (l->data));
- }
}
static void
gtk_widget_real_unroot (GtkWidget *widget)
{
- GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
- GList *l;
-
- for (l = priv->event_controllers; l; l = l->next)
- {
- if (GTK_IS_SHORTCUT_CONTROLLER (l->data))
- gtk_shortcut_controller_unroot (GTK_SHORTCUT_CONTROLLER (l->data));
- }
-
gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL);
}
@@ -892,10 +852,13 @@ static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkBindingSet *binding_set;
g_type_class_adjust_private_offset (klass, &GtkWidget_private_offset);
gtk_widget_parent_class = g_type_class_peek_parent (klass);
+ quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
+ quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
@@ -1675,6 +1638,32 @@ gtk_widget_class_init (GtkWidgetClass *klass)
_gtk_marshal_BOOLEAN__INT_INT_BOOLEAN_OBJECTv);
/**
+ * GtkWidget::popup-menu:
+ * @widget: the object which received the signal
+ *
+ * This signal gets emitted whenever a widget should pop up a context
+ * menu. This usually happens through the standard key binding mechanism;
+ * by pressing a certain key while a widget is focused, the user can cause
+ * the widget to pop up a menu. For example, the #GtkEntry widget creates
+ * a menu with clipboard commands. See the
+ * [Popup Menu Migration Checklist][checklist-popup-menu]
+ * for an example of how to use this signal.
+ *
+ * Returns: %TRUE if a menu was activated
+ */
+ widget_signals[POPUP_MENU] =
+ g_signal_new (I_("popup-menu"),
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_STRUCT_OFFSET (GtkWidgetClass, popup_menu),
+ _gtk_boolean_handled_accumulator, NULL,
+ _gtk_marshal_BOOLEAN__VOID,
+ G_TYPE_BOOLEAN, 0);
+ g_signal_set_va_marshaller (widget_signals[POPUP_MENU],
+ G_TYPE_FROM_CLASS (klass),
+ _gtk_marshal_BOOLEAN__VOIDv);
+
+ /**
* GtkWidget::accel-closures-changed:
* @widget: the object which received the signal.
*
@@ -1715,6 +1704,12 @@ gtk_widget_class_init (GtkWidgetClass *klass)
G_TYPE_FROM_CLASS (klass),
_gtk_marshal_BOOLEAN__UINTv);
+ binding_set = gtk_binding_set_by_class (klass);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK,
+ "popup-menu", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Menu, 0,
+ "popup-menu", 0);
+
gtk_widget_class_set_accessible_type (klass, GTK_TYPE_WIDGET_ACCESSIBLE);
gtk_widget_class_set_css_name (klass, I_("widget"));
}
@@ -1722,9 +1717,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
static void
gtk_widget_base_class_finalize (GtkWidgetClass *klass)
{
-
template_data_free (klass->priv->template);
- g_object_unref (klass->priv->shortcuts);
}
static void
@@ -2355,7 +2348,6 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
GtkWidget *widget = GTK_WIDGET (instance);
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
GType layout_manager_type;
- GtkEventController *controller;
widget->priv = priv;
@@ -2424,19 +2416,9 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_ROOT))
priv->root = (GtkRoot *) widget;
- if (g_type_is_a (G_TYPE_FROM_CLASS (g_class), GTK_TYPE_SHORTCUT_MANAGER))
- gtk_shortcut_manager_create_controllers (widget);
-
layout_manager_type = gtk_widget_class_get_layout_manager_type (g_class);
if (layout_manager_type != G_TYPE_INVALID)
gtk_widget_set_layout_manager (widget, g_object_new (layout_manager_type, NULL));
-
- if (g_list_model_get_n_items (G_LIST_MODEL (GTK_WIDGET_CLASS (g_class)->priv->shortcuts)) > 0)
- {
- controller = gtk_shortcut_controller_new_for_model (G_LIST_MODEL (GTK_WIDGET_CLASS (g_class)->priv->shortcuts));
- gtk_event_controller_set_name (controller, "gtk-widget-class-shortcuts");
- gtk_widget_add_controller (widget, controller);
- }
}
/**
@@ -4329,220 +4311,350 @@ gtk_widget_real_size_allocate (GtkWidget *widget,
{
}
+static gboolean
+gtk_widget_real_can_activate_accel (GtkWidget *widget,
+ guint signal_id)
+{
+ GdkSurface *surface;
+
+ /* widgets must be onscreen for accels to take effect */
+ if (!gtk_widget_is_sensitive (widget) ||
+ !_gtk_widget_get_mapped (widget))
+ return FALSE;
+
+ surface = gtk_widget_get_surface (widget);
+
+ return gdk_surface_is_viewable (surface);
+}
+
/**
- * gtk_widget_class_add_binding: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @callback: the callback to call upon activation
- * @format_string: GVariant format string for arguments or %NULL for
- * no arguments
- * @...: arguments, as given by format string.
+ * gtk_widget_can_activate_accel:
+ * @widget: a #GtkWidget
+ * @signal_id: the ID of a signal installed on @widget
*
- * Creates a new shortcut for @widget_class that calls the given @callback
- * with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * Determines whether an accelerator that activates the signal
+ * identified by @signal_id can currently be activated.
+ * This is done by emitting the #GtkWidget::can-activate-accel
+ * signal on @widget; if the signal isn’t overridden by a
+ * handler or in a derived widget, then the default check is
+ * that the widget must be sensitive, and the widget and all
+ * its ancestors mapped.
*
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization. It does not provide for user_data, if you need that,
- * you will have to use gtk_widget_class_add_shortcut() with a custom
- * shortcut.
+ * Returns: %TRUE if the accelerator can be activated.
**/
-void
-gtk_widget_class_add_binding (GtkWidgetClass *widget_class,
- guint keyval,
- GdkModifierType mods,
- GtkShortcutFunc func,
- const gchar *format_string,
- ...)
+gboolean
+gtk_widget_can_activate_accel (GtkWidget *widget,
+ guint signal_id)
{
- GtkShortcut *shortcut;
+ gboolean can_activate = FALSE;
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_signal_emit (widget, widget_signals[CAN_ACTIVATE_ACCEL], 0, signal_id, &can_activate);
+ return can_activate;
+}
- g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
+typedef struct {
+ GClosure closure;
+ guint signal_id;
+} AccelClosure;
+
+static void
+closure_accel_activate (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ AccelClosure *aclosure = (AccelClosure*) closure;
+ gboolean can_activate = gtk_widget_can_activate_accel (closure->data, aclosure->signal_id);
+
+ if (can_activate)
+ g_signal_emit (closure->data, aclosure->signal_id, 0);
- shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
- gtk_callback_action_new (func, NULL, NULL));
- if (format_string)
+ /* whether accelerator was handled */
+ g_value_set_boolean (return_value, can_activate);
+}
+
+static void
+closures_destroy (gpointer data)
+{
+ GSList *slist, *closures = data;
+
+ for (slist = closures; slist; slist = slist->next)
{
- va_list args;
- va_start (args, format_string);
- gtk_shortcut_set_arguments (shortcut,
- g_variant_new_va (format_string, NULL, &args));
- va_end (args);
+ g_closure_invalidate (slist->data);
+ g_closure_unref (slist->data);
}
+ g_slist_free (closures);
+}
- gtk_widget_class_add_shortcut (widget_class, shortcut);
+static GClosure*
+widget_new_accel_closure (GtkWidget *widget,
+ guint signal_id)
+{
+ AccelClosure *aclosure;
+ GClosure *closure = NULL;
+ GSList *slist, *closures;
- g_object_unref (shortcut);
+ closures = g_object_steal_qdata (G_OBJECT (widget), quark_accel_closures);
+ for (slist = closures; slist; slist = slist->next)
+ if (!gtk_accel_group_from_accel_closure (slist->data))
+ {
+ /* reuse this closure */
+ closure = slist->data;
+ break;
+ }
+ if (!closure)
+ {
+ closure = g_closure_new_object (sizeof (AccelClosure), G_OBJECT (widget));
+ closures = g_slist_prepend (closures, g_closure_ref (closure));
+ g_closure_sink (closure);
+ g_closure_set_marshal (closure, closure_accel_activate);
+ }
+ g_object_set_qdata_full (G_OBJECT (widget), quark_accel_closures, closures, closures_destroy);
+
+ aclosure = (AccelClosure*) closure;
+ g_assert (closure->data == widget);
+ g_assert (closure->marshal == closure_accel_activate);
+ aclosure->signal_id = signal_id;
+
+ return closure;
}
/**
- * gtk_widget_class_add_binding_signal: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @signal: the signal to execute
- * @format_string: GVariant format string for arguments or %NULL for
- * no arguments
- * @...: arguments, as given by format string.
- *
- * Creates a new shortcut for @widget_class that emits the given action
- * @signal with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * gtk_widget_add_accelerator:
+ * @widget: widget to install an accelerator on
+ * @accel_signal: widget signal to emit on accelerator activation
+ * @accel_group: accel group for this widget, added to its toplevel
+ * @accel_key: GDK keyval of the accelerator
+ * @accel_mods: modifier key combination of the accelerator
+ * @accel_flags: flag accelerators, e.g. %GTK_ACCEL_VISIBLE
*
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization.
+ * Installs an accelerator for this @widget in @accel_group that causes
+ * @accel_signal to be emitted if the accelerator is activated.
+ * The @accel_group needs to be added to the widget’s toplevel via
+ * gtk_window_add_accel_group(), and the signal must be of type %G_SIGNAL_ACTION.
+ * Accelerators added through this function are not user changeable during
+ * runtime. If you want to support accelerators that can be changed by the
+ * user, use gtk_accel_map_add_entry() and gtk_widget_set_accel_path() or
+ * gtk_menu_item_set_accel_path() instead.
*/
void
-gtk_widget_class_add_binding_signal (GtkWidgetClass *widget_class,
- guint keyval,
- GdkModifierType mods,
- const gchar *signal,
- const gchar *format_string,
- ...)
+gtk_widget_add_accelerator (GtkWidget *widget,
+ const gchar *accel_signal,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags)
{
- GtkShortcut *shortcut;
+ GClosure *closure;
+ GSignalQuery query;
- g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
- g_return_if_fail (g_signal_lookup (signal, G_TYPE_FROM_CLASS (widget_class)));
- /* XXX: validate variant format for signal */
-
- shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
- gtk_signal_action_new (signal));
- if (format_string)
- {
- va_list args;
- va_start (args, format_string);
- gtk_shortcut_set_arguments (shortcut,
- g_variant_new_va (format_string, NULL, &args));
- va_end (args);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (accel_signal != NULL);
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
+ if (!query.signal_id ||
+ !(query.signal_flags & G_SIGNAL_ACTION) ||
+ query.return_type != G_TYPE_NONE ||
+ query.n_params)
+ {
+ /* hmm, should be elaborate enough */
+ g_warning (G_STRLOC ": widget '%s' has no activatable signal \"%s\" without arguments",
+ G_OBJECT_TYPE_NAME (widget), accel_signal);
+ return;
}
- gtk_widget_class_add_shortcut (widget_class, shortcut);
+ closure = widget_new_accel_closure (widget, query.signal_id);
+
+ g_object_ref (widget);
+
+ /* install the accelerator. since we don't map this onto an accel_path,
+ * the accelerator will automatically be locked.
+ */
+ gtk_accel_group_connect (accel_group,
+ accel_key,
+ accel_mods,
+ accel_flags | GTK_ACCEL_LOCKED,
+ closure);
+
+ g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
- g_object_unref (shortcut);
+ g_object_unref (widget);
}
/**
- * gtk_widget_class_add_binding_action: (skip)
- * @widget_class: the class to add the binding to
- * @keyval: key value of binding to install
- * @mods: key modifier of binding to install
- * @action_name: the action to activate
- * @format_string: GVariant format string for arguments or %NULL for
- * no arguments
- * @...: arguments, as given by format string.
+ * gtk_widget_remove_accelerator:
+ * @widget: widget to install an accelerator on
+ * @accel_group: accel group for this widget
+ * @accel_key: GDK keyval of the accelerator
+ * @accel_mods: modifier key combination of the accelerator
*
- * Creates a new shortcut for @widget_class that activates the given
- * @action_name with arguments read according to @format_string.
- * The arguments and format string must be provided in the same way as
- * with g_variant_new().
+ * Removes an accelerator from @widget, previously installed with
+ * gtk_widget_add_accelerator().
*
- * This function is a convenience wrapper around
- * gtk_widget_class_add_shortcut() and must be called during class
- * initialization.
+ * Returns: whether an accelerator was installed and could be removed
*/
-void
-gtk_widget_class_add_binding_action (GtkWidgetClass *widget_class,
- guint keyval,
- GdkModifierType mods,
- const gchar *action_name,
- const gchar *format_string,
- ...)
+gboolean
+gtk_widget_remove_accelerator (GtkWidget *widget,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods)
{
- GtkShortcut *shortcut;
+ GtkAccelGroupEntry *ag_entry;
+ GList *slist, *clist;
+ guint n;
- g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
- /* XXX: validate variant format for action */
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
- shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, mods),
- gtk_action_action_new (action_name));
- if (format_string)
+ ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n);
+ clist = gtk_widget_list_accel_closures (widget);
+ for (slist = clist; slist; slist = slist->next)
{
- va_list args;
- va_start (args, format_string);
- gtk_shortcut_set_arguments (shortcut,
- g_variant_new_va (format_string, NULL, &args));
- va_end (args);
+ guint i;
+
+ for (i = 0; i < n; i++)
+ if (slist->data == (gpointer) ag_entry[i].closure)
+ {
+ gboolean is_removed = gtk_accel_group_disconnect (accel_group, slist->data);
+
+ g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+
+ g_list_free (clist);
+
+ return is_removed;
+ }
}
+ g_list_free (clist);
- gtk_widget_class_add_shortcut (widget_class, shortcut);
+ g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)",
+ accel_key, accel_mods, accel_group,
+ G_OBJECT_TYPE_NAME (widget), widget);
- g_object_unref (shortcut);
+ return FALSE;
}
/**
- * gtk_widget_class_add_shortcut:
- * @widget_class: the class to add the shortcut to
- * @shortcut: (transfer none): the #GtkShortcut to add
- *
- * Installs a shortcut in @widget_class. Every instance created for
- * @widget_class or its subclasses will inherit this shortcut and
- * trigger it.
+ * gtk_widget_list_accel_closures:
+ * @widget: widget to list accelerator closures for
*
- * Shortcuts added this way will be triggered in the @GTK_PHASE_BUBBLE
- * phase, which means they may also trigger if child widgets have focus.
+ * Lists the closures used by @widget for accelerator group connections
+ * with gtk_accel_group_connect_by_path() or gtk_accel_group_connect().
+ * The closures can be used to monitor accelerator changes on @widget,
+ * by connecting to the @GtkAccelGroup::accel-changed signal of the
+ * #GtkAccelGroup of a closure which can be found out with
+ * gtk_accel_group_from_accel_closure().
*
- * This function must only be used in class initialization functions
- * otherwise it is not guaranteed that the shortcut will be installed.
- **/
-void
-gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
- GtkShortcut *shortcut)
+ * Returns: (transfer container) (element-type GClosure):
+ * a newly allocated #GList of closures
+ */
+GList*
+gtk_widget_list_accel_closures (GtkWidget *widget)
{
- GtkWidgetClassPrivate *priv;
-
- g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
- g_return_if_fail (GTK_IS_SHORTCUT (shortcut));
+ GSList *slist;
+ GList *clist = NULL;
- priv = widget_class->priv;
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- g_list_store_append (priv->shortcuts, shortcut);
+ for (slist = g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); slist; slist = slist->next)
+ if (gtk_accel_group_from_accel_closure (slist->data))
+ clist = g_list_prepend (clist, slist->data);
+ return clist;
}
-static gboolean
-gtk_widget_real_can_activate_accel (GtkWidget *widget,
- guint signal_id)
+typedef struct {
+ GQuark path_quark;
+ GtkAccelGroup *accel_group;
+ GClosure *closure;
+} AccelPath;
+
+static void
+destroy_accel_path (gpointer data)
{
- GdkSurface *surface;
+ AccelPath *apath = data;
- /* widgets must be onscreen for accels to take effect */
- if (!gtk_widget_is_sensitive (widget) ||
- !_gtk_widget_get_mapped (widget))
- return FALSE;
+ gtk_accel_group_disconnect (apath->accel_group, apath->closure);
- surface = gtk_widget_get_surface (widget);
+ /* closures_destroy takes care of unrefing the closure */
+ g_object_unref (apath->accel_group);
- return gdk_surface_is_viewable (surface);
+ g_slice_free (AccelPath, apath);
}
+
/**
- * gtk_widget_can_activate_accel:
+ * gtk_widget_set_accel_path:
* @widget: a #GtkWidget
- * @signal_id: the ID of a signal installed on @widget
+ * @accel_path: (allow-none): path used to look up the accelerator
+ * @accel_group: (allow-none): a #GtkAccelGroup.
*
- * Determines whether an accelerator that activates the signal
- * identified by @signal_id can currently be activated.
- * This is done by emitting the #GtkWidget::can-activate-accel
- * signal on @widget; if the signal isn’t overridden by a
- * handler or in a derived widget, then the default check is
- * that the widget must be sensitive, and the widget and all
- * its ancestors mapped.
+ * Given an accelerator group, @accel_group, and an accelerator path,
+ * @accel_path, sets up an accelerator in @accel_group so whenever the
+ * key binding that is defined for @accel_path is pressed, @widget
+ * will be activated. This removes any accelerators (for any
+ * accelerator group) installed by previous calls to
+ * gtk_widget_set_accel_path(). Associating accelerators with
+ * paths allows them to be modified by the user and the modifications
+ * to be saved for future use. (See gtk_accel_map_save().)
*
- * Returns: %TRUE if the accelerator can be activated.
+ * This function is a low level function that would most likely
+ * be used by a menu creation system.
+ *
+ * If you only want to
+ * set up accelerators on menu items gtk_menu_item_set_accel_path()
+ * provides a somewhat more convenient interface.
+ *
+ * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
+ * pass a static string, you can save some memory by interning it first with
+ * g_intern_static_string().
**/
-gboolean
-gtk_widget_can_activate_accel (GtkWidget *widget,
- guint signal_id)
+void
+gtk_widget_set_accel_path (GtkWidget *widget,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group)
{
- gboolean can_activate = FALSE;
- g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
- g_signal_emit (widget, widget_signals[CAN_ACTIVATE_ACCEL], 0, signal_id, &can_activate);
- return can_activate;
+ AccelPath *apath;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
+
+ if (accel_path)
+ {
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+ g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
+
+ gtk_accel_map_add_entry (accel_path, 0, 0);
+ apath = g_slice_new (AccelPath);
+ apath->accel_group = g_object_ref (accel_group);
+ apath->path_quark = g_quark_from_string (accel_path);
+ apath->closure = widget_new_accel_closure (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal);
+ }
+ else
+ apath = NULL;
+
+ /* also removes possible old settings */
+ g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path);
+
+ if (apath)
+ gtk_accel_group_connect_by_path (apath->accel_group, g_quark_to_string (apath->path_quark), apath->closure);
+
+ g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
+}
+
+const gchar*
+_gtk_widget_get_accel_path (GtkWidget *widget,
+ gboolean *locked)
+{
+ AccelPath *apath;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
+
+ apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path);
+ if (locked)
+ *locked = apath ? gtk_accel_group_get_is_locked (apath->accel_group) : TRUE;
+ return apath ? g_quark_to_string (apath->path_quark) : NULL;
}
/**
@@ -4798,6 +4910,11 @@ gtk_widget_event (GtkWidget *widget,
if (return_val == FALSE)
return_val |= gtk_widget_run_controllers (widget, event, target, x, y, GTK_PHASE_BUBBLE);
+ if (return_val == FALSE &&
+ (gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+ gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
+ return_val |= gtk_bindings_activate_event (G_OBJECT (widget), event);
+
return return_val;
}
@@ -7440,6 +7557,10 @@ gtk_widget_real_destroy (GtkWidget *object)
priv->accessible = NULL;
}
+ /* wipe accelerator closures (keep order) */
+ g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
+ g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
+
/* Callers of add_mnemonic_label() should disconnect on ::destroy */
g_object_set_qdata (G_OBJECT (widget), quark_mnemonic_labels, NULL);
@@ -8877,6 +8998,90 @@ static const GtkBuildableParser accessibility_parser =
typedef struct
{
+ GObject *object;
+ GtkBuilder *builder;
+ guint key;
+ guint modifiers;
+ gchar *signal;
+} AccelGroupParserData;
+
+static void
+accel_group_start_element (GtkBuildableParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ AccelGroupParserData *data = (AccelGroupParserData*)user_data;
+
+ if (strcmp (element_name, "accelerator") == 0)
+ {
+ const gchar *key_str = NULL;
+ const gchar *signal = NULL;
+ const gchar *modifiers_str = NULL;
+ guint key = 0;
+ guint modifiers = 0;
+
+ if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+ return;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_STRING, "key", &key_str,
+ G_MARKUP_COLLECT_STRING, "signal", &signal,
+ G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "modifiers", &modifiers_str,
+ G_MARKUP_COLLECT_INVALID))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ key = gdk_keyval_from_name (key_str);
+ if (key == 0)
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
+ "Could not parse key '%s'", key_str);
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ if (modifiers_str != NULL)
+ {
+ GFlagsValue aliases[2] = {
+ { 0, "primary", "primary" },
+ { 0, NULL, NULL }
+ };
+
+ aliases[0].value = _gtk_get_primary_accel_mod ();
+
+ if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, aliases,
+ modifiers_str, &modifiers, error))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+ }
+
+ data->key = key;
+ data->modifiers = modifiers;
+ data->signal = g_strdup (signal);
+ }
+ else
+ {
+ _gtk_builder_error_unhandled_tag (data->builder, context,
+ "GtkWidget", element_name,
+ error);
+ }
+}
+
+static const GtkBuildableParser accel_group_parser =
+ {
+ accel_group_start_element,
+ };
+
+typedef struct
+{
GtkBuilder *builder;
GSList *classes;
} StyleParserData;
@@ -9078,6 +9283,20 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable,
GtkBuildableParser *parser,
gpointer *parser_data)
{
+ if (strcmp (tagname, "accelerator") == 0)
+ {
+ AccelGroupParserData *data;
+
+ data = g_slice_new0 (AccelGroupParserData);
+ data->object = (GObject *)g_object_ref (buildable);
+ data->builder = builder;
+
+ *parser = accel_group_parser;
+ *parser_data = data;
+
+ return TRUE;
+ }
+
if (strcmp (tagname, "accessibility") == 0)
{
AccessibilitySubParserData *data;
@@ -9130,6 +9349,45 @@ gtk_widget_buildable_custom_tag_end (GtkBuildable *buildable,
{
}
+void
+_gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
+ GtkWidget *toplevel,
+ gpointer user_data)
+{
+ AccelGroupParserData *accel_data;
+ GSList *accel_groups;
+ GtkAccelGroup *accel_group;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GTK_IS_WIDGET (toplevel));
+ g_return_if_fail (user_data != NULL);
+
+ accel_data = (AccelGroupParserData*)user_data;
+ accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
+ if (g_slist_length (accel_groups) == 0)
+ {
+ accel_group = gtk_accel_group_new ();
+ if (GTK_IS_WINDOW (toplevel))
+ gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
+ }
+ else
+ {
+ g_assert (g_slist_length (accel_groups) == 1);
+ accel_group = g_slist_nth_data (accel_groups, 0);
+ }
+
+ gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object),
+ accel_data->signal,
+ accel_group,
+ accel_data->key,
+ accel_data->modifiers,
+ GTK_ACCEL_VISIBLE);
+
+ g_object_unref (accel_data->object);
+ g_free (accel_data->signal);
+ g_slice_free (AccelGroupParserData, accel_data);
+}
+
static void
gtk_widget_buildable_finish_layout_properties (GtkWidget *widget,
GtkWidget *parent,
@@ -9203,7 +9461,19 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
const gchar *tagname,
gpointer user_data)
{
- if (strcmp (tagname, "accessibility") == 0)
+ if (strcmp (tagname, "accelerator") == 0)
+ {
+ AccelGroupParserData *accel_data;
+ GtkRoot *root;
+
+ accel_data = (AccelGroupParserData*)user_data;
+ g_assert (accel_data->object);
+
+ root = _gtk_widget_get_root (GTK_WIDGET (accel_data->object));
+
+ _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), GTK_WIDGET (root), user_data);
+ }
+ else if (strcmp (tagname, "accessibility") == 0)
{
AccessibilitySubParserData *a11y_data;
@@ -11583,24 +11853,6 @@ gtk_widget_reset_controllers (GtkWidget *widget)
}
}
-GList *
-gtk_widget_list_controllers (GtkWidget *widget,
- GtkPropagationPhase phase)
-{
- GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
- GList *res = NULL, *l;
-
- for (l = priv->event_controllers; l; l = l->next)
- {
- GtkEventController *controller = l->data;
-
- if (gtk_event_controller_get_propagation_phase (controller) == phase)
- res = g_list_prepend (res, controller);
- }
-
- return g_list_reverse (res);
-}
-
static inline void
gtk_widget_maybe_add_debug_render_nodes (GtkWidget *widget,
GtkSnapshot *snapshot)
diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h
index d9becfab17..9121d5bb7e 100644
--- a/gtk/gtkwidget.h
+++ b/gtk/gtkwidget.h
@@ -33,8 +33,6 @@
#include <gsk/gsk.h>
#include <gtk/gtkaccelgroup.h>
#include <gtk/gtkborder.h>
-#include <gtk/gtkshortcut.h>
-#include <gtk/gtkshortcutaction.h>
#include <gtk/gtktypes.h>
#include <atk/atk.h>
@@ -376,32 +374,23 @@ GDK_AVAILABLE_IN_ALL
GType gtk_widget_class_get_layout_manager_type (GtkWidgetClass *widget_class);
GDK_AVAILABLE_IN_ALL
-void gtk_widget_class_add_binding (GtkWidgetClass *widget_class,
- guint keyval,
- GdkModifierType mods,
- GtkShortcutFunc callback,
- const gchar *format_string,
- ...);
+void gtk_widget_add_accelerator (GtkWidget *widget,
+ const gchar *accel_signal,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods,
+ GtkAccelFlags accel_flags);
GDK_AVAILABLE_IN_ALL
-void gtk_widget_class_add_binding_signal
- (GtkWidgetClass *widget_class,
- GdkModifierType mods,
- guint keyval,
- const gchar *signal,
- const gchar *format_string,
- ...);
+gboolean gtk_widget_remove_accelerator (GtkWidget *widget,
+ GtkAccelGroup *accel_group,
+ guint accel_key,
+ GdkModifierType accel_mods);
GDK_AVAILABLE_IN_ALL
-void gtk_widget_class_add_binding_action
- (GtkWidgetClass *widget_class,
- GdkModifierType mods,
- guint keyval,
- const gchar *action_name,
- const gchar *format_string,
- ...);
+void gtk_widget_set_accel_path (GtkWidget *widget,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group);
GDK_AVAILABLE_IN_ALL
-void gtk_widget_class_add_shortcut (GtkWidgetClass *widget_class,
- GtkShortcut *shortcut);
-
+GList* gtk_widget_list_accel_closures (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
gboolean gtk_widget_can_activate_accel (GtkWidget *widget,
guint signal_id);
diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h
index 82943b5eb5..1018c9c915 100644
--- a/gtk/gtkwidgetprivate.h
+++ b/gtk/gtkwidgetprivate.h
@@ -230,6 +230,9 @@ void _gtk_widget_add_attached_window (GtkWidget *widget,
void _gtk_widget_remove_attached_window (GtkWidget *widget,
GtkWindow *window);
+const gchar* _gtk_widget_get_accel_path (GtkWidget *widget,
+ gboolean *locked);
+
AtkObject * _gtk_widget_peek_accessible (GtkWidget *widget);
void _gtk_widget_set_has_default (GtkWidget *widget,
@@ -255,6 +258,9 @@ void _gtk_widget_synthesize_crossing (GtkWidget *fro
GdkDevice *device,
GdkCrossingMode mode);
+void _gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
+ GtkWidget *toplevel,
+ gpointer user_data);
GtkStyleContext * _gtk_widget_peek_style_context (GtkWidget *widget);
gboolean _gtk_widget_captured_event (GtkWidget *widget,
@@ -277,9 +283,6 @@ gboolean gtk_widget_has_size_request (GtkWidget *widget);
void gtk_widget_reset_controllers (GtkWidget *widget);
-GList * gtk_widget_list_controllers (GtkWidget *widget,
- GtkPropagationPhase phase);
-
gboolean gtk_widget_query_tooltip (GtkWidget *widget,
gint x,
gint y,
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index be93fa6e90..3549009b2e 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -28,6 +28,7 @@
#include "gtkaccelgroupprivate.h"
#include "gtkapplicationprivate.h"
+#include "gtkbindings.h"
#include "gtkbox.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
@@ -53,6 +54,7 @@
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkmessagedialog.h"
+#include "gtkmnemonichash.h"
#include "gtkpointerfocusprivate.h"
#include "gtkpopovermenuprivate.h"
#include "gtkmodelbuttonprivate.h"
@@ -61,10 +63,6 @@
#include "gtkroot.h"
#include "gtknative.h"
#include "gtksettings.h"
-#include "gtkshortcut.h"
-#include "gtkshortcutcontroller.h"
-#include "gtkshortcutmanager.h"
-#include "gtkshortcuttrigger.h"
#include "gtksnapshot.h"
#include "gtkstylecontextprivate.h"
#include "gtktypebuiltins.h"
@@ -162,7 +160,7 @@
* widget that is added as a titlebar child.
*/
-#define MENU_BAR_ACCEL GDK_KEY_F10
+#define MENU_BAR_ACCEL "F10"
#define RESIZE_HANDLE_SIZE 20
#define MNEMONICS_DELAY 300 /* ms */
#define NO_CONTENT_CHILD_NAT 200
@@ -185,6 +183,8 @@ struct _GtkWindowPopover
typedef struct
{
+ GtkMnemonicHash *mnemonic_hash;
+
GtkWidget *attach_widget;
GtkWidget *default_widget;
GtkWidget *initial_focus;
@@ -197,6 +197,8 @@ typedef struct
GQueue popovers;
+ GdkModifierType mnemonic_modifier;
+
gchar *startup_id;
gchar *title;
@@ -260,7 +262,6 @@ typedef struct
GtkGesture *drag_gesture;
GtkGesture *bubble_drag_gesture;
GtkEventController *key_controller;
- GtkEventController *application_shortcut_controller;
GtkCssNode *decoration_node;
@@ -470,9 +471,6 @@ static void update_window_buttons (GtkWindow *window);
static void get_shadow_width (GtkWindow *window,
GtkBorder *shadow_width);
-static gboolean gtk_window_activate_menubar (GtkWidget *widget,
- GVariant *args,
- gpointer unused);
static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
static void gtk_window_free_key_hash (GtkWindow *window);
#ifdef GDK_WINDOWING_X11
@@ -507,6 +505,7 @@ static gboolean disable_startup_notification = FALSE;
static GQuark quark_gtk_window_key_hash = 0;
static GQuark quark_gtk_window_icon_info = 0;
+static GQuark quark_gtk_buildable_accels = 0;
static GtkBuildableIface *parent_buildable_iface;
@@ -529,8 +528,20 @@ static void gtk_window_buildable_set_buildable_property (GtkBuildable
GtkBuilder *builder,
const gchar *name,
const GValue *value);
+static void gtk_window_buildable_parser_finished (GtkBuildable *buildable,
+ GtkBuilder *builder);
+static gboolean gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GtkBuildableParser *parser,
+ gpointer *data);
+static void gtk_window_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data);
-static void gtk_window_shortcut_manager_interface_init (GtkShortcutManagerInterface *iface);
/* GtkRoot */
static void gtk_window_root_interface_init (GtkRootInterface *iface);
static void gtk_window_native_interface_init (GtkNativeInterface *iface);
@@ -551,52 +562,41 @@ G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
gtk_window_buildable_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_NATIVE,
gtk_window_native_interface_init)
- G_IMPLEMENT_INTERFACE (GTK_TYPE_SHORTCUT_MANAGER,
- gtk_window_shortcut_manager_interface_init)
G_IMPLEMENT_INTERFACE (GTK_TYPE_ROOT,
gtk_window_root_interface_init))
static void
-add_tab_bindings (GtkWidgetClass *widget_class,
+add_tab_bindings (GtkBindingSet *binding_set,
GdkModifierType modifiers,
GtkDirectionType direction)
{
- GtkShortcut *shortcut;
-
- shortcut = gtk_shortcut_new_with_arguments (
- gtk_alternative_trigger_new (gtk_keyval_trigger_new (GDK_KEY_Tab, modifiers),
- gtk_keyval_trigger_new (GDK_KEY_KP_Tab, modifiers)),
- gtk_signal_action_new ("move-focus"),
- "(i)", direction);
-
- gtk_widget_class_add_shortcut (widget_class, shortcut);
-
- g_object_unref (shortcut);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static void
-add_arrow_bindings (GtkWidgetClass *widget_class,
+add_arrow_bindings (GtkBindingSet *binding_set,
guint keysym,
GtkDirectionType direction)
{
guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
- gtk_widget_class_add_binding_signal (widget_class, keysym, 0,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, 0,
- "move-focus",
- "(i)",
- direction);
- gtk_widget_class_add_binding_signal (widget_class, keypad_keysym, GDK_CONTROL_MASK,
- "move-focus",
- "(i)",
- direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, 0,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
+ gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+ "move-focus", 1,
+ GTK_TYPE_DIRECTION_TYPE, direction);
}
static guint32
@@ -757,11 +757,16 @@ static void
gtk_window_class_init (GtkWindowClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+ GtkWidgetClass *widget_class;
+ GtkContainerClass *container_class;
+ GtkBindingSet *binding_set;
+ widget_class = (GtkWidgetClass*) klass;
+ container_class = (GtkContainerClass*) klass;
+
quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash");
quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info");
+ quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels");
if (toplevel_list == NULL)
toplevel_list = g_list_store_new (GTK_TYPE_WIDGET);
@@ -1100,32 +1105,36 @@ gtk_window_class_init (GtkWindowClass *klass)
gtk_widget_class_install_action (widget_class, "default.activate", NULL,
gtk_window_activate_default_activate);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_space, 0,
- "activate-focus", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Space, 0,
- "activate-focus", NULL);
+ binding_set = gtk_binding_set_by_class (klass);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_space, 0,
+ "activate-focus", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Space, 0,
+ "activate-focus", 0);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_Return, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_ISO_Enter, 0,
- "activate-default", NULL);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_KP_Enter, 0,
- "activate-default", NULL);
-
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
- "enable-debugging", "(b)", FALSE);
- gtk_widget_class_add_binding_signal (widget_class, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
- "enable-debugging", "(b)", TRUE);
-
- add_arrow_bindings (widget_class, GDK_KEY_Up, GTK_DIR_UP);
- add_arrow_bindings (widget_class, GDK_KEY_Down, GTK_DIR_DOWN);
- add_arrow_bindings (widget_class, GDK_KEY_Left, GTK_DIR_LEFT);
- add_arrow_bindings (widget_class, GDK_KEY_Right, GTK_DIR_RIGHT);
-
- add_tab_bindings (widget_class, 0, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
- add_tab_bindings (widget_class, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
- add_tab_bindings (widget_class, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_Return, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_ISO_Enter, 0,
+ "activate-default", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Enter, 0,
+ "activate-default", 0);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_I, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+ "enable-debugging", 1,
+ G_TYPE_BOOLEAN, FALSE);
+ gtk_binding_entry_add_signal (binding_set, GDK_KEY_D, GDK_CONTROL_MASK|GDK_SHIFT_MASK,
+ "enable-debugging", 1,
+ G_TYPE_BOOLEAN, TRUE);
+
+ add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
+ add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
+ add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
+ add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);
+
+ add_tab_bindings (binding_set, 0, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
+ add_tab_bindings (binding_set, GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
+ add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE);
gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_FRAME);
@@ -1716,9 +1725,9 @@ gtk_window_init (GtkWindow *window)
GtkWidget *widget;
GtkCssNode *widget_node;
GdkSeat *seat;
+ GtkEventController *motion_controller;
GtkEventController *controller;
GtkDropTargetAsync *target;
- GtkShortcut *shortcut;
widget = GTK_WIDGET (window);
@@ -1733,6 +1742,7 @@ gtk_window_init (GtkWindow *window)
priv->modal = FALSE;
priv->gravity = GDK_GRAVITY_NORTH_WEST;
priv->decorated = TRUE;
+ priv->mnemonic_modifier = GDK_MOD1_MASK;
priv->display = gdk_display_get_default ();
priv->state = GDK_SURFACE_STATE_WITHDRAWN;
@@ -1774,12 +1784,12 @@ gtk_window_init (GtkWindow *window)
g_signal_connect (seat, "device-removed",
G_CALLBACK (device_removed_cb), window);
- controller = gtk_event_controller_motion_new ();
- gtk_event_controller_set_propagation_phase (controller,
+ motion_controller = gtk_event_controller_motion_new ();
+ gtk_event_controller_set_propagation_phase (motion_controller,
GTK_PHASE_CAPTURE);
- g_signal_connect_swapped (controller, "motion",
+ g_signal_connect_swapped (motion_controller, "motion",
G_CALLBACK (gtk_window_capture_motion), window);
- gtk_widget_add_controller (widget, controller);
+ gtk_widget_add_controller (widget, motion_controller);
priv->key_controller = gtk_event_controller_key_new ();
gtk_event_controller_set_propagation_phase (priv->key_controller, GTK_PHASE_CAPTURE);
@@ -1797,15 +1807,6 @@ gtk_window_init (GtkWindow *window)
/* Shared constraint solver */
priv->constraint_solver = gtk_constraint_solver_new ();
-
- controller = gtk_shortcut_controller_new ();
- gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
-
- shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (MENU_BAR_ACCEL, 0),
- gtk_callback_action_new (gtk_window_activate_menubar, NULL, NULL));
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- gtk_event_controller_set_name (controller, "gtk-window-menubar-accel");
- gtk_widget_add_controller (widget, controller);
}
static GtkGesture *
@@ -2013,6 +2014,9 @@ gtk_window_buildable_interface_init (GtkBuildableIface *iface)
{
parent_buildable_iface = g_type_interface_peek_parent (iface);
iface->set_buildable_property = gtk_window_buildable_set_buildable_property;
+ iface->parser_finished = gtk_window_buildable_parser_finished;
+ iface->custom_tag_start = gtk_window_buildable_custom_tag_start;
+ iface->custom_finished = gtk_window_buildable_custom_finished;
iface->add_child = gtk_window_buildable_add_child;
}
@@ -2045,9 +2049,166 @@ gtk_window_buildable_set_buildable_property (GtkBuildable *buildable,
g_object_set_property (G_OBJECT (buildable), name, value);
}
+typedef struct {
+ gchar *name;
+ gint line;
+ gint col;
+} ItemData;
+
+static void
+item_data_free (gpointer data)
+{
+ ItemData *item_data = data;
+
+ g_free (item_data->name);
+ g_free (item_data);
+}
+
+static void
+item_list_free (gpointer data)
+{
+ GSList *list = data;
+
+ g_slist_free_full (list, item_data_free);
+}
+
+static void
+gtk_window_buildable_parser_finished (GtkBuildable *buildable,
+ GtkBuilder *builder)
+{
+ GtkWindow *window = GTK_WINDOW (buildable);
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GObject *object;
+ GSList *accels, *l;
+
+ if (priv->builder_visible)
+ gtk_widget_show (GTK_WIDGET (buildable));
+
+ accels = g_object_get_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels);
+ for (l = accels; l; l = l->next)
+ {
+ ItemData *data = l->data;
+
+ object = _gtk_builder_lookup_object (builder, data->name, data->line, data->col);
+ if (!object)
+ continue;
+ gtk_window_add_accel_group (GTK_WINDOW (buildable), GTK_ACCEL_GROUP (object));
+ }
+
+ g_object_set_qdata (G_OBJECT (buildable), quark_gtk_buildable_accels, NULL);
+
+ parent_buildable_iface->parser_finished (buildable, builder);
+}
+
+typedef struct {
+ GObject *object;
+ GtkBuilder *builder;
+ GSList *items;
+} GSListSubParserData;
+
+static void
+window_start_element (GtkBuildableParseContext *context,
+ const gchar *element_name,
+ const gchar **names,
+ const gchar **values,
+ gpointer user_data,
+ GError **error)
+{
+ GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+ if (strcmp (element_name, "group") == 0)
+ {
+ const gchar *name;
+ ItemData *item_data;
+
+ if (!_gtk_builder_check_parent (data->builder, context, "accel-groups", error))
+ return;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_STRING, "name", &name,
+ G_MARKUP_COLLECT_INVALID))
+ {
+ _gtk_builder_prefix_error (data->builder, context, error);
+ return;
+ }
+
+ item_data = g_new (ItemData, 1);
+ item_data->name = g_strdup (name);
+ gtk_buildable_parse_context_get_position (context, &item_data->line, &item_data->col);
+ data->items = g_slist_prepend (data->items, item_data);
+ }
+ else if (strcmp (element_name, "accel-groups") == 0)
+ {
+ if (!_gtk_builder_check_parent (data->builder, context, "object", error))
+ return;
+
+ if (!g_markup_collect_attributes (element_name, names, values, error,
+ G_MARKUP_COLLECT_INVALID, NULL, NULL,
+ G_MARKUP_COLLECT_INVALID))
+ _gtk_builder_prefix_error (data->builder, context, error);
+ }
+ else
+ {
+ _gtk_builder_error_unhandled_tag (data->builder, context,
+ "GtkWindow", element_name,
+ error);
+ }
+}
+
+static const GtkBuildableParser window_parser =
+ {
+ window_start_element
+ };
+
+static gboolean
+gtk_window_buildable_custom_tag_start (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ GtkBuildableParser *parser,
+ gpointer *parser_data)
+{
+ if (parent_buildable_iface->custom_tag_start (buildable, builder, child,
+ tagname, parser, parser_data))
+ return TRUE;
+
+ if (strcmp (tagname, "accel-groups") == 0)
+ {
+ GSListSubParserData *data;
+
+ data = g_slice_new0 (GSListSubParserData);
+ data->items = NULL;
+ data->object = G_OBJECT (buildable);
+ data->builder = builder;
+
+ *parser = window_parser;
+ *parser_data = data;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static void
-gtk_window_shortcut_manager_interface_init (GtkShortcutManagerInterface *iface)
+gtk_window_buildable_custom_finished (GtkBuildable *buildable,
+ GtkBuilder *builder,
+ GObject *child,
+ const gchar *tagname,
+ gpointer user_data)
{
+ parent_buildable_iface->custom_finished (buildable, builder, child,
+ tagname, user_data);
+
+ if (strcmp (tagname, "accel-groups") == 0)
+ {
+ GSListSubParserData *data = (GSListSubParserData*)user_data;
+
+ g_object_set_qdata_full (G_OBJECT (buildable), quark_gtk_buildable_accels,
+ data->items, (GDestroyNotify) item_list_free);
+
+ g_slice_free (GSListSubParserData, data);
+ }
}
static GdkDisplay *
@@ -2382,6 +2543,174 @@ _gtk_window_notify_keys_changed (GtkWindow *window)
}
/**
+ * gtk_window_add_accel_group:
+ * @window: window to attach accelerator group to
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Associate @accel_group with @window, such that calling
+ * gtk_accel_groups_activate() on @window will activate accelerators
+ * in @accel_group.
+ **/
+void
+gtk_window_add_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ _gtk_accel_group_attach (accel_group, G_OBJECT (window));
+ g_signal_connect_object (accel_group, "accel-changed",
+ G_CALLBACK (_gtk_window_notify_keys_changed),
+ window, G_CONNECT_SWAPPED);
+ _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_remove_accel_group:
+ * @window: a #GtkWindow
+ * @accel_group: a #GtkAccelGroup
+ *
+ * Reverses the effects of gtk_window_add_accel_group().
+ **/
+void
+gtk_window_remove_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ g_signal_handlers_disconnect_by_func (accel_group,
+ _gtk_window_notify_keys_changed,
+ window);
+ _gtk_accel_group_detach (accel_group, G_OBJECT (window));
+ _gtk_window_notify_keys_changed (window);
+}
+
+static GtkMnemonicHash *
+gtk_window_get_mnemonic_hash (GtkWindow *window,
+ gboolean create)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ if (!priv->mnemonic_hash && create)
+ priv->mnemonic_hash = _gtk_mnemonic_hash_new ();
+
+ return priv->mnemonic_hash;
+}
+
+/**
+ * gtk_window_add_mnemonic:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @target: the widget that gets activated by the mnemonic
+ *
+ * Adds a mnemonic to this window.
+ */
+void
+gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ _gtk_mnemonic_hash_add (gtk_window_get_mnemonic_hash (window, TRUE),
+ keyval, target);
+ _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_remove_mnemonic:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @target: the widget that gets activated by the mnemonic
+ *
+ * Removes a mnemonic from this window.
+ */
+void
+gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target)
+{
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail (GTK_IS_WIDGET (target));
+
+ _gtk_mnemonic_hash_remove (gtk_window_get_mnemonic_hash (window, TRUE),
+ keyval, target);
+ _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_mnemonic_activate:
+ * @window: a #GtkWindow
+ * @keyval: the mnemonic
+ * @modifier: the modifiers
+ *
+ * Activates the targets associated with the mnemonic.
+ *
+ * Returns: %TRUE if the activation is done.
+ */
+gboolean
+gtk_window_mnemonic_activate (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifier)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ()))
+ {
+ GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+ if (mnemonic_hash)
+ return _gtk_mnemonic_hash_activate (mnemonic_hash, keyval);
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_window_set_mnemonic_modifier:
+ * @window: a #GtkWindow
+ * @modifier: the modifier mask used to activate
+ * mnemonics on this window.
+ *
+ * Sets the mnemonic modifier for this window.
+ **/
+void
+gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ GdkModifierType modifier)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ g_return_if_fail (GTK_IS_WINDOW (window));
+ g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0);
+
+ priv->mnemonic_modifier = modifier;
+ _gtk_window_notify_keys_changed (window);
+}
+
+/**
+ * gtk_window_get_mnemonic_modifier:
+ * @window: a #GtkWindow
+ *
+ * Returns the mnemonic modifier for this window. See
+ * gtk_window_set_mnemonic_modifier().
+ *
+ * Returns: the modifier mask used to activate
+ * mnemonics on this window.
+ **/
+GdkModifierType
+gtk_window_get_mnemonic_modifier (GtkWindow *window)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
+
+ return priv->mnemonic_modifier;
+}
+
+/**
* gtk_window_get_focus:
* @window: a #GtkWindow
*
@@ -2796,9 +3125,6 @@ gtk_window_release_application (GtkWindow *window)
/* steal reference into temp variable */
application = priv->application;
priv->application = NULL;
- gtk_widget_remove_controller (GTK_WIDGET (window),
- priv->application_shortcut_controller);
- priv->application_shortcut_controller = NULL;
gtk_application_remove_window (application, window);
g_object_unref (application);
@@ -2839,18 +3165,9 @@ gtk_window_set_application (GtkWindow *window,
if (priv->application != NULL)
{
- GtkApplicationAccels *app_accels;
-
g_object_ref (priv->application);
gtk_application_add_window (priv->application, window);
-
- app_accels = gtk_application_get_application_accels (priv->application);
- priv->application_shortcut_controller = gtk_shortcut_controller_new_for_model (gtk_application_accels_get_shortcuts (app_accels));
- gtk_event_controller_set_name (priv->application_shortcut_controller, "gtk-application-shortcuts");
- gtk_event_controller_set_propagation_phase (priv->application_shortcut_controller, GTK_PHASE_CAPTURE);
- gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (priv->application_shortcut_controller), GTK_SHORTCUT_SCOPE_GLOBAL);
- gtk_widget_add_controller (GTK_WIDGET (window), priv->application_shortcut_controller);
}
_gtk_widget_update_parent_muxer (GTK_WIDGET (window));
@@ -4037,11 +4354,16 @@ gtk_window_finalize (GObject *object)
{
GtkWindow *window = GTK_WINDOW (object);
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GtkMnemonicHash *mnemonic_hash;
g_clear_pointer (&priv->extra_input_region, cairo_region_destroy);
g_free (priv->title);
gtk_window_release_application (window);
+ mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+ if (mnemonic_hash)
+ _gtk_mnemonic_hash_free (mnemonic_hash);
+
if (priv->geometry_info)
{
g_free (priv->geometry_info);
@@ -5360,6 +5682,8 @@ _gtk_window_query_nonaccels (GtkWindow *window,
guint accel_key,
GdkModifierType accel_mods)
{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+
g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
/* movement keys are considered locked accels */
@@ -5376,9 +5700,77 @@ _gtk_window_query_nonaccels (GtkWindow *window,
return TRUE;
}
+ /* mnemonics are considered locked accels */
+ if (accel_mods == priv->mnemonic_modifier)
+ {
+ GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+ if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key))
+ return TRUE;
+ }
+
return FALSE;
}
+/**
+ * gtk_window_propagate_key_event:
+ * @window: a #GtkWindow
+ * @event: a #GdkEvent
+ *
+ * Propagate a key press or release event to the focus widget and
+ * up the focus container chain until a widget handles @event.
+ * This is normally called by the default ::key_press_event and
+ * ::key_release_event handlers for toplevel windows,
+ * however in some cases it may be useful to call this directly when
+ * overriding the standard key handling for a toplevel window.
+ *
+ * Returns: %TRUE if a widget in the focus chain handled the event.
+ */
+gboolean
+gtk_window_propagate_key_event (GtkWindow *window,
+ GdkEvent *event)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ gboolean handled = FALSE;
+ GtkWidget *widget, *focus, *target;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+
+ widget = GTK_WIDGET (window);
+
+ focus = priv->focus_widget;
+ if (focus)
+ g_object_ref (focus);
+
+ target = focus;
+
+ while (!handled &&
+ focus && focus != widget &&
+ gtk_widget_get_root (focus) == GTK_ROOT (widget))
+ {
+ GtkWidget *parent;
+
+ if (gtk_widget_is_sensitive (focus))
+ {
+ handled = gtk_widget_event (focus, (GdkEvent *)event, target);
+ if (handled)
+ break;
+ }
+
+ parent = _gtk_widget_get_parent (focus);
+ if (parent)
+ g_object_ref (parent);
+
+ g_object_unref (focus);
+
+ focus = parent;
+ }
+
+ if (focus)
+ g_object_unref (focus);
+
+ return handled;
+}
+
static GtkWindowRegion
get_active_region_type (GtkWindow *window, gint x, gint y)
{
@@ -5424,6 +5816,9 @@ gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
GList *seats, *s;
gboolean retval = FALSE;
+ if (!priv->mnemonic_modifier)
+ return FALSE;
+
seats = gdk_display_list_seats (gtk_widget_get_display (GTK_WIDGET (window)));
for (s = seats; s; s = s->next)
@@ -5432,7 +5827,7 @@ gtk_window_has_mnemonic_modifier_pressed (GtkWindow *window)
GdkModifierType mask;
gdk_device_get_state (dev, priv->surface, NULL, &mask);
- if ((mask & gtk_accelerator_get_default_mod_mask ()) == GDK_MOD1_MASK)
+ if (priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ()))
{
retval = TRUE;
break;
@@ -7378,42 +7773,130 @@ _gtk_window_set_window_group (GtkWindow *window,
}
static gboolean
-gtk_window_activate_menubar (GtkWidget *widget,
- GVariant *args,
- gpointer unused)
+gtk_window_activate_menubar (GtkWindow *window,
+ GdkEvent *event)
{
- GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
- GList *tmp_menubars, *l;
- GPtrArray *menubars;
- GtkWidget *focus;
- GtkWidget *first;
+ guint keyval = 0;
+ GdkModifierType mods = 0;
- focus = gtk_window_get_focus (window);
+ gtk_accelerator_parse (MENU_BAR_ACCEL, &keyval, &mods);
- if (priv->title_box != NULL &&
- (focus == NULL || !gtk_widget_is_ancestor (focus, priv->title_box)) &&
- gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD))
- return TRUE;
+ if (keyval == 0)
+ {
+ g_warning ("Failed to parse menu bar accelerator '%s'", MENU_BAR_ACCEL);
+ return FALSE;
+ }
- tmp_menubars = gtk_popover_menu_bar_get_viewable_menu_bars (window);
- if (tmp_menubars == NULL)
+ if (!(gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+ gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
return FALSE;
- menubars = g_ptr_array_sized_new (g_list_length (tmp_menubars));;
- for (l = tmp_menubars; l; l = l->next)
- g_ptr_array_add (menubars, l->data);
+ /* FIXME this is wrong, needs to be in the global accel resolution
+ * thing, to properly consider i18n etc., but that probably requires
+ * AccelGroup changes etc.
+ */
+ if (gdk_key_event_get_keyval (event) == keyval &&
+ ((gdk_event_get_modifier_state (event) & gtk_accelerator_get_default_mod_mask ()) ==
+ (mods & gtk_accelerator_get_default_mod_mask ())))
+ {
+ GList *tmp_menubars, *l;
+ GPtrArray *menubars;
+ GtkWidget *focus;
+ GtkWidget *first;
+
+ focus = gtk_window_get_focus (window);
+
+ if (priv->title_box != NULL &&
+ (focus == NULL || !gtk_widget_is_ancestor (focus, priv->title_box)) &&
+ gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD))
+ return TRUE;
+
+ tmp_menubars = gtk_popover_menu_bar_get_viewable_menu_bars (window);
+ if (tmp_menubars == NULL)
+ return FALSE;
- g_list_free (tmp_menubars);
+ menubars = g_ptr_array_sized_new (g_list_length (tmp_menubars));;
+ for (l = tmp_menubars; l; l = l->next)
+ g_ptr_array_add (menubars, l->data);
- gtk_widget_focus_sort (GTK_WIDGET (window), GTK_DIR_TAB_FORWARD, menubars);
+ g_list_free (tmp_menubars);
- first = g_ptr_array_index (menubars, 0);
- gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
+ gtk_widget_focus_sort (GTK_WIDGET (window), GTK_DIR_TAB_FORWARD, menubars);
- g_ptr_array_free (menubars, TRUE);
+ first = g_ptr_array_index (menubars, 0);
+ gtk_popover_menu_bar_select_first (GTK_POPOVER_MENU_BAR (first));
- return TRUE;
+ g_ptr_array_free (menubars, TRUE);
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+gtk_window_mnemonic_hash_foreach (guint keyval,
+ GSList *targets,
+ gpointer data)
+{
+ struct {
+ GtkWindow *window;
+ GtkWindowKeysForeachFunc func;
+ gpointer func_data;
+ } *info = data;
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (info->window);
+
+ (*info->func) (info->window, keyval, priv->mnemonic_modifier, TRUE, info->func_data);
+}
+
+static void
+_gtk_window_keys_foreach (GtkWindow *window,
+ GtkWindowKeysForeachFunc func,
+ gpointer func_data)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GSList *groups;
+ GtkMnemonicHash *mnemonic_hash;
+
+ struct {
+ GtkWindow *window;
+ GtkWindowKeysForeachFunc func;
+ gpointer func_data;
+ } info;
+
+ info.window = window;
+ info.func = func;
+ info.func_data = func_data;
+
+ mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE);
+ if (mnemonic_hash)
+ _gtk_mnemonic_hash_foreach (mnemonic_hash,
+ gtk_window_mnemonic_hash_foreach, &info);
+
+ groups = gtk_accel_groups_from_object (G_OBJECT (window));
+ while (groups)
+ {
+ GtkAccelGroup *group = groups->data;
+ gint i;
+
+ for (i = 0; i < group->priv->n_accels; i++)
+ {
+ GtkAccelKey *key = &group->priv->priv_accels[i].key;
+
+ if (key->accel_key)
+ (*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
+ }
+
+ groups = groups->next;
+ }
+
+ if (priv->application)
+ {
+ GtkApplicationAccels *app_accels;
+
+ app_accels = gtk_application_get_application_accels (priv->application);
+ gtk_application_accels_foreach_key (app_accels, window, func, func_data);
+ }
}
static void
@@ -7429,6 +7912,7 @@ struct _GtkWindowKeyEntry
{
guint keyval;
guint modifiers;
+ guint is_mnemonic : 1;
};
static void
@@ -7437,6 +7921,35 @@ window_key_entry_destroy (gpointer data)
g_slice_free (GtkWindowKeyEntry, data);
}
+static void
+add_to_key_hash (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifiers,
+ gboolean is_mnemonic,
+ gpointer data)
+{
+ GtkKeyHash *key_hash = data;
+
+ GtkWindowKeyEntry *entry = g_slice_new (GtkWindowKeyEntry);
+
+ entry->keyval = keyval;
+ entry->modifiers = modifiers;
+ entry->is_mnemonic = is_mnemonic;
+
+ /* GtkAccelGroup stores lowercased accelerators. To deal
+ * with this, if <Shift> was specified, uppercase.
+ */
+ if (modifiers & GDK_SHIFT_MASK)
+ {
+ if (keyval == GDK_KEY_Tab)
+ keyval = GDK_KEY_ISO_Left_Tab;
+ else
+ keyval = gdk_keyval_to_upper (keyval);
+ }
+
+ _gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
+}
+
static GtkKeyHash *
gtk_window_get_key_hash (GtkWindow *window)
{
@@ -7448,6 +7961,7 @@ gtk_window_get_key_hash (GtkWindow *window)
key_hash = _gtk_key_hash_new (gdk_display_get_keymap (priv->display),
(GDestroyNotify)window_key_entry_destroy);
+ _gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
g_object_set_qdata (G_OBJECT (window), quark_gtk_window_key_hash, key_hash);
return key_hash;
@@ -7464,6 +7978,111 @@ gtk_window_free_key_hash (GtkWindow *window)
}
}
+/**
+ * gtk_window_activate_key:
+ * @window: a #GtkWindow
+ * @event: a #GdkEvent
+ *
+ * Activates mnemonics and accelerators for this #GtkWindow. This is normally
+ * called by the default ::key_press_event handler for toplevel windows,
+ * however in some cases it may be useful to call this directly when
+ * overriding the standard key handling for a toplevel window.
+ *
+ * Returns: %TRUE if a mnemonic or accelerator was found and activated.
+ */
+gboolean
+gtk_window_activate_key (GtkWindow *window,
+ GdkEvent *event)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GtkKeyHash *key_hash;
+ GtkWindowKeyEntry *found_entry = NULL;
+ gboolean enable_accels;
+
+ g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (!(gdk_event_get_event_type (event) == GDK_KEY_PRESS ||
+ gdk_event_get_event_type (event) == GDK_KEY_RELEASE))
+ return FALSE;
+
+ key_hash = gtk_window_get_key_hash (window);
+
+ if (key_hash)
+ {
+ GSList *tmp_list;
+ GSList *entries = _gtk_key_hash_lookup (key_hash,
+ gdk_key_event_get_keycode (event),
+ gdk_event_get_modifier_state (event),
+ gtk_accelerator_get_default_mod_mask (),
+ gdk_key_event_get_group (event));
+
+ g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)),
+ "gtk-enable-accels", &enable_accels,
+ NULL);
+
+ for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
+ {
+ GtkWindowKeyEntry *entry = tmp_list->data;
+ if (entry->is_mnemonic)
+ {
+ found_entry = entry;
+ break;
+ }
+ else
+ {
+ if (enable_accels && !found_entry)
+ {
+ found_entry = entry;
+ }
+ }
+ }
+
+ g_slist_free (entries);
+ }
+
+ if (found_entry)
+ {
+ if (found_entry->is_mnemonic)
+ {
+ return gtk_window_mnemonic_activate (window, found_entry->keyval,
+ found_entry->modifiers);
+ }
+ else
+ {
+ if (enable_accels)
+ {
+ if (gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers))
+ return TRUE;
+
+ if (priv->application)
+ {
+ GtkWidget *focused_widget;
+ GtkActionMuxer *muxer;
+ GtkApplicationAccels *app_accels;
+
+ focused_widget = gtk_window_get_focus (window);
+
+ if (focused_widget)
+ muxer = _gtk_widget_get_action_muxer (focused_widget, FALSE);
+ else
+ muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (window), FALSE);
+
+ if (muxer == NULL)
+ return FALSE;
+
+ app_accels = gtk_application_get_application_accels (priv->application);
+ return gtk_application_accels_activate (app_accels,
+ G_ACTION_GROUP (muxer),
+ found_entry->keyval, found_entry->modifiers);
+ }
+ }
+ }
+ }
+
+ return gtk_window_activate_menubar (window, event);
+}
+
/*
* _gtk_window_set_is_active:
* @window: a #GtkWindow
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index 2563ac5cac..8f4c964fee 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -97,6 +97,12 @@ GDK_AVAILABLE_IN_ALL
void gtk_window_set_startup_id (GtkWindow *window,
const gchar *startup_id);
GDK_AVAILABLE_IN_ALL
+void gtk_window_add_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
+void gtk_window_remove_accel_group (GtkWindow *window,
+ GtkAccelGroup *accel_group);
+GDK_AVAILABLE_IN_ALL
void gtk_window_set_focus (GtkWindow *window,
GtkWidget *focus);
GDK_AVAILABLE_IN_ALL
@@ -185,6 +191,31 @@ void gtk_window_set_has_user_ref_count (GtkWindow *window,
gboolean setting);
GDK_AVAILABLE_IN_ALL
+void gtk_window_add_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+GDK_AVAILABLE_IN_ALL
+void gtk_window_remove_mnemonic (GtkWindow *window,
+ guint keyval,
+ GtkWidget *target);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_mnemonic_activate (GtkWindow *window,
+ guint keyval,
+ GdkModifierType modifier);
+GDK_AVAILABLE_IN_ALL
+void gtk_window_set_mnemonic_modifier (GtkWindow *window,
+ GdkModifierType modifier);
+GDK_AVAILABLE_IN_ALL
+GdkModifierType gtk_window_get_mnemonic_modifier (GtkWindow *window);
+
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_activate_key (GtkWindow *window,
+ GdkEvent *event);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_window_propagate_key_event (GtkWindow *window,
+ GdkEvent *event);
+
+GDK_AVAILABLE_IN_ALL
void gtk_window_present (GtkWindow *window);
GDK_AVAILABLE_IN_ALL
void gtk_window_present_with_time (GtkWindow *window,
diff --git a/gtk/gtkwindowprivate.h b/gtk/gtkwindowprivate.h
index 8192644b72..5fc156f8f9 100644
--- a/gtk/gtkwindowprivate.h
+++ b/gtk/gtkwindowprivate.h
@@ -56,6 +56,7 @@ void gtk_window_check_resize (GtkWindow *self);
typedef void (*GtkWindowKeysForeachFunc) (GtkWindow *window,
guint keyval,
GdkModifierType modifiers,
+ gboolean is_mnemonic,
gpointer data);
gboolean gtk_window_emit_close_request (GtkWindow *window);
diff --git a/gtk/inspector/init.c b/gtk/inspector/init.c
index 126ce44b31..2681e62e81 100644
--- a/gtk/inspector/init.c
+++ b/gtk/inspector/init.c
@@ -40,7 +40,6 @@
#include "prop-list.h"
#include "recorder.h"
#include "resource-list.h"
-#include "shortcuts.h"
#include "size-groups.h"
#include "statistics.h"
#include "visual.h"
@@ -75,7 +74,6 @@ gtk_inspector_init (void)
g_type_ensure (GTK_TYPE_INSPECTOR_PROP_LIST);
g_type_ensure (GTK_TYPE_INSPECTOR_RECORDER);
g_type_ensure (GTK_TYPE_INSPECTOR_RESOURCE_LIST);
- g_type_ensure (GTK_TYPE_INSPECTOR_SHORTCUTS);
g_type_ensure (GTK_TYPE_INSPECTOR_SIZE_GROUPS);
g_type_ensure (GTK_TYPE_INSPECTOR_STATISTICS);
g_type_ensure (GTK_TYPE_INSPECTOR_VISUAL);
diff --git a/gtk/inspector/meson.build b/gtk/inspector/meson.build
index 4f32b75639..c945386d2d 100644
--- a/gtk/inspector/meson.build
+++ b/gtk/inspector/meson.build
@@ -28,7 +28,6 @@ inspector_sources = files(
'recording.c',
'renderrecording.c',
'resource-list.c',
- 'shortcuts.c',
'size-groups.c',
'startrecording.c',
'statistics.c',
diff --git a/gtk/inspector/shortcuts.c b/gtk/inspector/shortcuts.c
deleted file mode 100644
index 3f708371cd..0000000000
--- a/gtk/inspector/shortcuts.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2020 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "config.h"
-#include <glib/gi18n-lib.h>
-
-#include "shortcuts.h"
-#include "gtklabel.h"
-#include "gtklistbox.h"
-#include "gtksizegroup.h"
-#include "gtkstack.h"
-#include "gtkshortcut.h"
-#include "gtkshortcuttrigger.h"
-#include "gtkshortcutcontroller.h"
-
-struct _GtkInspectorShortcuts
-{
- GtkWidget parent;
-
- GtkWidget *box;
- GtkWidget *list;
-
- GtkSizeGroup *trigger;
- GtkSizeGroup *action;
-};
-
-G_DEFINE_TYPE (GtkInspectorShortcuts, gtk_inspector_shortcuts, GTK_TYPE_WIDGET)
-
-static void
-gtk_inspector_shortcuts_init (GtkInspectorShortcuts *sl)
-{
- gtk_widget_init_template (GTK_WIDGET (sl));
-}
-
-static GtkWidget *
-create_row (gpointer item,
- gpointer user_data)
-{
- GtkShortcut *shortcut = GTK_SHORTCUT (item);
- GtkInspectorShortcuts *sl = GTK_INSPECTOR_SHORTCUTS (user_data);
- GtkShortcutTrigger *trigger;
- GtkShortcutAction *action;
- char *s;
- GtkWidget *row;
- GtkWidget *label;
-
- trigger = gtk_shortcut_get_trigger (shortcut);
- action = gtk_shortcut_get_action (shortcut);
-
- row = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
-
- s = gtk_shortcut_trigger_to_string (trigger);
- label = gtk_label_new (s);
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- g_free (s);
- gtk_container_add (GTK_CONTAINER (row), label);
- gtk_size_group_add_widget (sl->trigger, label);
-
- s = gtk_shortcut_action_to_string (action);
- label = gtk_label_new (s);
- gtk_label_set_xalign (GTK_LABEL (label), 0.0);
- g_free (s);
- gtk_container_add (GTK_CONTAINER (row), label);
- gtk_size_group_add_widget (sl->action, label);
-
- return row;
-}
-
-void
-gtk_inspector_shortcuts_set_object (GtkInspectorShortcuts *sl,
- GObject *object)
-{
- GtkWidget *stack;
- GtkStackPage *page;
-
- stack = gtk_widget_get_parent (GTK_WIDGET (sl));
- page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
-
- if (GTK_IS_SHORTCUT_CONTROLLER (object))
- {
- g_object_set (page, "visible", TRUE, NULL);
- gtk_list_box_bind_model (GTK_LIST_BOX (sl->list),
- G_LIST_MODEL (object),
- create_row,
- sl,
- NULL);
- }
- else
- {
- g_object_set (page, "visible", FALSE, NULL);
- gtk_list_box_bind_model (GTK_LIST_BOX (sl->list),
- NULL,
- NULL,
- NULL,
- NULL);
- }
-}
-
-static void
-gtk_inspector_shortcuts_measure (GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
-{
- GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget);
-
- gtk_widget_measure (shortcuts->box,
- orientation,
- for_size,
- minimum, natural,
- minimum_baseline, natural_baseline);
-}
-
-static void
-gtk_inspector_shortcuts_size_allocate (GtkWidget *widget,
- int width,
- int height,
- int baseline)
-{
- GtkInspectorShortcuts *shortcuts = GTK_INSPECTOR_SHORTCUTS (widget);
-
- gtk_widget_size_allocate (shortcuts->box,
- &(GtkAllocation) { 0, 0, width, height },
- baseline);
-}
-
-
-static void
-gtk_inspector_shortcuts_class_init (GtkInspectorShortcutsClass *klass)
-{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
-
- widget_class->measure = gtk_inspector_shortcuts_measure;
- widget_class->size_allocate = gtk_inspector_shortcuts_size_allocate;
-
- gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/shortcuts.ui");
- gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, box);
- gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, list);
- gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, trigger);
- gtk_widget_class_bind_template_child (widget_class, GtkInspectorShortcuts, action);
-}
diff --git a/gtk/inspector/shortcuts.ui b/gtk/inspector/shortcuts.ui
deleted file mode 100644
index 7ac55eb17a..0000000000
--- a/gtk/inspector/shortcuts.ui
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface domain="gtk40">
- <template class="GtkInspectorShortcuts" parent="GtkWidget">
- <style>
- <class name="view"/>
- </style>
- <child>
- <object class="GtkBox" id="box">
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox">
- <style>
- <class name="header"/>
- </style>
- <child>
- <object class="GtkLabel" id="trigger_heading">
- <property name="label" translatable="yes">Trigger</property>
- <property name="xalign">0</property>
- </object>
- </child>
- <child>
- <object class="GtkLabel" id="action_heading">
- <property name="label" translatable="yes">Action</property>
- <property name="xalign">0</property>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkScrolledWindow">
- <property name="hexpand">1</property>
- <property name="vexpand">1</property>
- <property name="hscrollbar-policy">never</property>
- <child>
- <object class="GtkListBox" id="list">
- <style>
- <class name="list"/>
- </style>
- <property name="selection-mode">none</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </template>
- <object class="GtkSizeGroup" id="trigger">
- <property name="mode">horizontal</property>
- <widgets>
- <widget name="trigger_heading"/>
- </widgets>
- </object>
- <object class="GtkSizeGroup" id="action">
- <property name="mode">horizontal</property>
- <widgets>
- <widget name="action_heading"/>
- </widgets>
- </object>
-</interface>
diff --git a/gtk/inspector/window.c b/gtk/inspector/window.c
index 2b86655b43..6b4b2524d5 100644
--- a/gtk/inspector/window.c
+++ b/gtk/inspector/window.c
@@ -37,7 +37,6 @@
#include "size-groups.h"
#include "data-list.h"
#include "actions.h"
-#include "shortcuts.h"
#include "menu.h"
#include "misc-info.h"
#include "magnifier.h"
@@ -92,7 +91,6 @@ set_selected_object (GtkInspectorWindow *iw,
gtk_inspector_size_groups_set_object (GTK_INSPECTOR_SIZE_GROUPS (iw->size_groups), selected);
gtk_inspector_data_list_set_object (GTK_INSPECTOR_DATA_LIST (iw->data_list), selected);
gtk_inspector_actions_set_object (GTK_INSPECTOR_ACTIONS (iw->actions), selected);
- gtk_inspector_shortcuts_set_object (GTK_INSPECTOR_SHORTCUTS (iw->shortcuts), selected);
gtk_inspector_menu_set_object (GTK_INSPECTOR_MENU (iw->menu), selected);
gtk_inspector_controllers_set_object (GTK_INSPECTOR_CONTROLLERS (iw->controllers), selected);
gtk_inspector_magnifier_set_object (GTK_INSPECTOR_MAGNIFIER (iw->magnifier), selected);
@@ -423,7 +421,6 @@ gtk_inspector_window_class_init (GtkInspectorWindowClass *klass)
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, size_groups);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, data_list);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, actions);
- gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, shortcuts);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, menu);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, misc_info);
gtk_widget_class_bind_template_child (widget_class, GtkInspectorWindow, controllers);
diff --git a/gtk/inspector/window.h b/gtk/inspector/window.h
index 6ac9a7eafc..3f29706141 100644
--- a/gtk/inspector/window.h
+++ b/gtk/inspector/window.h
@@ -66,7 +66,6 @@ typedef struct
GtkWidget *size_groups;
GtkWidget *data_list;
GtkWidget *actions;
- GtkWidget *shortcuts;
GtkWidget *menu;
GtkWidget *misc_info;
GtkWidget *controllers;
diff --git a/gtk/inspector/window.ui b/gtk/inspector/window.ui
index 4623a72229..963464be7a 100644
--- a/gtk/inspector/window.ui
+++ b/gtk/inspector/window.ui
@@ -449,16 +449,6 @@
</property>
</object>
</child>
- <child>
- <object class="GtkStackPage">
- <property name="name">shortcuts</property>
- <property name="title" translatable="yes">Shortcuts</property>
- <property name="child">
- <object class="GtkInspectorShortcuts" id="shortcuts">
- </object>
- </property>
- </object>
- </child>
</object>
</child>
</object>
diff --git a/gtk/meson.build b/gtk/meson.build
index 095b71158d..bf7e08a06c 100644
--- a/gtk/meson.build
+++ b/gtk/meson.build
@@ -119,6 +119,7 @@ gtk_private_sources = files([
'gtkmenusectionbox.c',
'gtkmenutracker.c',
'gtkmenutrackeritem.c',
+ 'gtkmnemonichash.c',
'gtkpango.c',
'gskpango.c',
'gtkpathbar.c',
@@ -150,6 +151,7 @@ gtk_public_sources = files([
'gtkaboutdialog.c',
'gtkaccelgroup.c',
'gtkaccellabel.c',
+ 'gtkaccelmap.c',
'gtkaccessible.c',
'gtkactionable.c',
'gtkactionbar.c',
@@ -164,6 +166,7 @@ gtk_public_sources = files([
'gtkassistant.c',
'gtkbin.c',
'gtkbinlayout.c',
+ 'gtkbindings.c',
'gtkborder.c',
'gtkboxlayout.c',
'gtkbox.c',
@@ -199,7 +202,6 @@ gtk_public_sources = files([
'gtkcombobox.c',
'gtkcomboboxtext.c',
'gtkcomposetable.c',
- 'gtkconcatmodel.c',
'gtkconstraintguide.c',
'gtkconstraintlayout.c',
'gtkconstraint.c',
@@ -329,16 +331,11 @@ gtk_public_sources = files([
'gtkselectionmodel.c',
'gtkseparator.c',
'gtksettings.c',
- 'gtkshortcut.c',
- 'gtkshortcutaction.c',
- 'gtkshortcutcontroller.c',
'gtkshortcutlabel.c',
- 'gtkshortcutmanager.c',
'gtkshortcutsgroup.c',
'gtkshortcutssection.c',
'gtkshortcutsshortcut.c',
'gtkshortcutswindow.c',
- 'gtkshortcuttrigger.c',
'gtkshow.c',
'gtksidebarrow.c',
'gtksingleselection.c',
@@ -405,6 +402,7 @@ gtk_public_headers = files([
'gtkaboutdialog.h',
'gtkaccelgroup.h',
'gtkaccellabel.h',
+ 'gtkaccelmap.h',
'gtkaccessible.h',
'gtkactionable.h',
'gtkactionbar.h',
@@ -419,6 +417,7 @@ gtk_public_headers = files([
'gtkassistant.h',
'gtkbin.h',
'gtkbinlayout.h',
+ 'gtkbindings.h',
'gtkborder.h',
'gtkbox.h',
'gtkboxlayout.h',
@@ -569,16 +568,11 @@ gtk_public_headers = files([
'gtkselectionmodel.h',
'gtkseparator.h',
'gtksettings.h',
- 'gtkshortcut.h',
- 'gtkshortcutaction.h',
- 'gtkshortcutcontroller.h',
'gtkshortcutlabel.h',
- 'gtkshortcutmanager.h',
'gtkshortcutsgroup.h',
'gtkshortcutssection.h',
'gtkshortcutsshortcut.h',
'gtkshortcutswindow.h',
- 'gtkshortcuttrigger.h',
'gtkshow.h',
'gtksingleselection.h',
'gtksizegroup.h',
diff --git a/gtk/ui/gtkcoloreditor.ui b/gtk/ui/gtkcoloreditor.ui
index d03b287278..4075102a5e 100644
--- a/gtk/ui/gtkcoloreditor.ui
+++ b/gtk/ui/gtkcoloreditor.ui
@@ -83,12 +83,12 @@
</child>
<child>
<object class="GtkColorScale" id="h_slider">
- <property name="name">h</property>
<property name="can-focus">True</property>
<property name="orientation">vertical</property>
<property name="adjustment">h_adj</property>
<property name="draw-value">False</property>
<property name="has-origin">False</property>
+ <signal name="popup-menu" handler="popup_edit" swapped="no"/>
<layout>
<property name="left-attach">0</property>
<property name="top-attach">1</property>
@@ -97,7 +97,6 @@
</child>
<child>
<object class="GtkColorScale" id="a_slider">
- <property name="name">a</property>
<property name="can-focus">True</property>
<property name="adjustment">a_adj</property>
<property name="draw-value">False</property>
@@ -106,6 +105,7 @@
<style>
<class name="marks-before"/>
</style>
+ <signal name="popup-menu" handler="popup_edit" swapped="no"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">2</property>
@@ -115,13 +115,13 @@
</child>
<child>
<object class="GtkColorPlane" id="sv_plane">
- <property name="name">sv</property>
<property name="width-request">300</property>
<property name="height-request">300</property>
<property name="can-focus">True</property>
<property name="h-adjustment">h_adj</property>
<property name="s-adjustment">s_adj</property>
<property name="v-adjustment">v_adj</property>
+ <signal name="popup-menu" handler="popup_edit" swapped="no"/>
<layout>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
diff --git a/gtk/ui/gtkfilechooserwidget.ui b/gtk/ui/gtkfilechooserwidget.ui
index dca1716e23..ff7ad061fd 100644
--- a/gtk/ui/gtkfilechooserwidget.ui
+++ b/gtk/ui/gtkfilechooserwidget.ui
@@ -160,6 +160,12 @@
<signal name="pressed" handler="click_cb" swapped="no"/>
</object>
</child>
+ <child>
+ <object class="GtkEventControllerKey">
+ <signal name="key-pressed" handler="treeview_key_press_cb" swapped="no"/>
+ </object>
+ </child>
+ <signal name="popup-menu" handler="list_popup_menu_cb" swapped="no"/>
<signal name="query-tooltip" handler="file_list_query_tooltip_cb" swapped="no"/>
<signal name="row-activated" handler="list_row_activated" swapped="no"/>
<signal name="keynav-failed" handler="browse_files_tree_view_keynav_failed_cb"/>
@@ -362,6 +368,11 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkEventControllerKey">
+ <signal name="key-pressed" handler="widget_key_press_cb" swapped="no"/>
+ </object>
+ </child>
</template>
<object class="GtkSizeGroup" id="browse_path_bar_size_group">
<property name="mode">vertical</property>
diff --git a/gtk/ui/gtkplacesviewrow.ui b/gtk/ui/gtkplacesviewrow.ui
index 1177326b40..31b1473c8d 100644
--- a/gtk/ui/gtkplacesviewrow.ui
+++ b/gtk/ui/gtkplacesviewrow.ui
@@ -81,5 +81,11 @@
</child>
</object>
</child>
+ <child>
+ <object class="GtkGestureClick">
+ <property name="button">3</property>
+ <signal name="pressed" handler="pressed_cb" swapped="no"/>
+ </object>
+ </child>
</template>
</interface>
diff --git a/po-properties/POTFILES.in b/po-properties/POTFILES.in
index 2c3bd92850..8929b238fa 100644
--- a/po-properties/POTFILES.in
+++ b/po-properties/POTFILES.in
@@ -77,6 +77,7 @@ gtk/gtkapplicationwindow.c
gtk/gtkaspectframe.c
gtk/gtkassistant.c
gtk/gtkbin.c
+gtk/gtkbindings.c
gtk/gtkbookmarksmanager.c
gtk/gtkbox.c
gtk/gtkboxlayout.c
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0be7778fed..644f28115e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -77,6 +77,7 @@ gtk/gtkapplicationwindow.c
gtk/gtkaspectframe.c
gtk/gtkassistant.c
gtk/gtkbin.c
+gtk/gtkbindings.c
gtk/gtkbookmarksmanager.c
gtk/gtkbox.c
gtk/gtkboxlayout.c
diff --git a/tests/testgtk.c b/tests/testgtk.c
index 1f6b8c8439..4c591dfa49 100644
--- a/tests/testgtk.c
+++ b/tests/testgtk.c
@@ -1603,33 +1603,25 @@ create_listbox (GtkWidget *widget)
static GtkWidget *
-accel_button_new (const gchar *text,
- const gchar *accel)
+accel_button_new (GtkAccelGroup *accel_group,
+ const gchar *text,
+ const gchar *accel)
{
guint keyval;
GdkModifierType modifiers;
GtkWidget *button;
GtkWidget *label;
- GtkEventController *controller;
- GtkShortcut *shortcut;
- if (!gtk_accelerator_parse (accel, &keyval, &modifiers))
- {
- g_assert_not_reached ();
- }
+ gtk_accelerator_parse (accel, &keyval, &modifiers);
+ g_assert (keyval);
button = gtk_button_new ();
- controller = gtk_shortcut_controller_new ();
- gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller), GTK_SHORTCUT_SCOPE_GLOBAL);
- gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_CAPTURE);
- shortcut = gtk_shortcut_new (gtk_keyval_trigger_new (keyval, modifiers),
- gtk_activate_action_new ());
- gtk_shortcut_controller_add_shortcut (GTK_SHORTCUT_CONTROLLER (controller), shortcut);
- g_object_unref (shortcut);
- gtk_widget_add_controller (button, controller);
+ gtk_widget_add_accelerator (button, "activate", accel_group,
+ keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
label = gtk_accel_label_new (text);
- gtk_accel_label_set_accel (GTK_ACCEL_LABEL (label), keyval, modifiers);
+ gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
+ gtk_widget_show (label);
gtk_container_add (GTK_CONTAINER (button), label);
@@ -1644,6 +1636,7 @@ create_key_lookup (GtkWidget *widget)
if (!window)
{
+ GtkAccelGroup *accel_group = gtk_accel_group_new ();
GtkWidget *button;
GtkWidget *content_area;
@@ -1658,6 +1651,8 @@ create_key_lookup (GtkWidget *widget)
*/
gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
+ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
@@ -1670,23 +1665,23 @@ create_key_lookup (GtkWidget *widget)
gtk_container_add (GTK_CONTAINER (content_area), button);
button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 7", "<Alt><Shift>b");
+ button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 8", "<Alt>d");
+ button = accel_button_new (accel_group, "Button 8", "<Alt>d");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 9", "<Alt>Cyrillic_ve");
+ button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
gtk_container_add (GTK_CONTAINER (content_area), button);
button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
gtk_container_add (GTK_CONTAINER (content_area), button);
button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 12", "<Super>a");
+ button = accel_button_new (accel_group, "Button 12", "<Super>a");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 13", "<Hyper>a");
+ button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 14", "<Meta>a");
+ button = accel_button_new (accel_group, "Button 14", "<Meta>a");
gtk_container_add (GTK_CONTAINER (content_area), button);
- button = accel_button_new ("Button 15", "<Shift><Mod4>b");
+ button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
gtk_container_add (GTK_CONTAINER (content_area), button);
window_ptr = &window;
@@ -6237,6 +6232,7 @@ main (int argc, char *argv[])
{
GtkCssProvider *provider, *memory_provider;
GdkDisplay *display;
+ GtkBindingSet *binding_set;
int i;
gboolean done_benchmarks = FALSE;
@@ -6320,6 +6316,15 @@ main (int argc, char *argv[])
if (done_benchmarks)
return 0;
+ /* bindings test
+ */
+ binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
+ gtk_binding_entry_add_signal (binding_set,
+ '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
+ "debug_msg",
+ 1,
+ G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
+
memory_provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (memory_provider,
"#testgtk-version-label {\n"
diff --git a/tests/testmenubutton.c b/tests/testmenubutton.c
index cb2b647b0f..f165d88aa7 100644
--- a/tests/testmenubutton.c
+++ b/tests/testmenubutton.c
@@ -40,6 +40,7 @@ int main (int argc, char **argv)
GtkWidget *label;
GtkWidget *check;
GtkWidget *combo;
+ GtkAccelGroup *accel_group;
guint i;
guint row = 0;
GMenu *menu;
@@ -54,6 +55,9 @@ int main (int argc, char **argv)
gtk_grid_set_column_spacing (GTK_GRID (grid), 12);
gtk_container_add (GTK_CONTAINER (window), grid);
+ accel_group = gtk_accel_group_new ();
+ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
/* horizontal alignment */
label = gtk_label_new ("Horizontal Alignment:");
gtk_widget_show (label);
diff --git a/testsuite/css/parser/at-invalid-22.css b/testsuite/css/parser/at-invalid-22.css
new file mode 100644
index 0000000000..db9626914a
--- /dev/null
+++ b/testsuite/css/parser/at-invalid-22.css
@@ -0,0 +1 @@
+@define-color color darker ( @blue ) ;
diff --git a/testsuite/css/parser/at-invalid-22.errors b/testsuite/css/parser/at-invalid-22.errors
new file mode 100644
index 0000000000..168e43daff
--- /dev/null
+++ b/testsuite/css/parser/at-invalid-22.errors
@@ -0,0 +1 @@
+at-invalid-22.css:1:21-27: error: GTK_CSS_PARSER_ERROR_SYNTAX
diff --git a/testsuite/css/parser/at-invalid-22.ref.css b/testsuite/css/parser/at-invalid-22.ref.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testsuite/css/parser/at-invalid-22.ref.css
diff --git a/testsuite/css/parser/meson.build b/testsuite/css/parser/meson.build
index e128e1971b..ea4b815a59 100644
--- a/testsuite/css/parser/meson.build
+++ b/testsuite/css/parser/meson.build
@@ -92,6 +92,9 @@ test_data = [
'at-invalid-21.css',
'at-invalid-21.errors',
'at-invalid-21.ref.css',
+ 'at-invalid-22.css',
+ 'at-invalid-22.errors',
+ 'at-invalid-22.ref.css',
'at-valid-01.css',
'at-valid-01.ref.css',
'at-valid-02.css',
diff --git a/testsuite/gtk/accel.c b/testsuite/gtk/accel.c
index c49a10e72f..da031da7be 100644
--- a/testsuite/gtk/accel.c
+++ b/testsuite/gtk/accel.c
@@ -28,20 +28,19 @@ test_one_accel (const char *accel,
char *label, *name;
accel_key = 0;
- g_assert (gtk_accelerator_parse_with_keycode (accel,
- gdk_display_get_default (),
- &accel_key,
- &keycodes,
- &mods));
+ gtk_accelerator_parse_with_keycode (accel,
+ &accel_key,
+ &keycodes,
+ &mods);
if (has_keysym)
{
guint accel_key_2;
GdkModifierType mods_2;
- g_assert (gtk_accelerator_parse (accel,
- &accel_key_2,
- &mods_2));
+ gtk_accelerator_parse (accel,
+ &accel_key_2,
+ &mods_2);
g_assert (accel_key == accel_key_2);
g_assert (mods == mods_2);
}
diff --git a/testsuite/gtk/action.c b/testsuite/gtk/action.c
index f15dce7ac1..23a78fa23e 100644
--- a/testsuite/gtk/action.c
+++ b/testsuite/gtk/action.c
@@ -360,7 +360,6 @@ test_introspection (void)
} expected[] = {
{ GTK_TYPE_TEXT, "text.undo", NULL, NULL },
{ GTK_TYPE_TEXT, "text.redo", NULL, NULL },
- { GTK_TYPE_TEXT, "menu.popup", NULL, NULL },
{ GTK_TYPE_TEXT, "clipboard.cut", NULL, NULL },
{ GTK_TYPE_TEXT, "clipboard.copy", NULL, NULL },
{ GTK_TYPE_TEXT, "clipboard.paste", NULL, NULL },
@@ -379,9 +378,9 @@ test_introspection (void)
&property))
{
g_assert (expected[i].owner == owner);
- g_assert_cmpstr (expected[i].name, ==, name);
- g_assert_cmpstr (expected[i].params, ==, params ? g_variant_type_peek_string (params) : NULL);
- g_assert_cmpstr (expected[i].property, ==, property);
+ g_assert (strcmp (expected[i].name, name) == 0);
+ g_assert (g_strcmp0 (expected[i].params, params ? g_variant_type_peek_string (params) : NULL) == 0);
+ g_assert (g_strcmp0 (expected[i].property, property) == 0);
i++;
}
g_assert (i == G_N_ELEMENTS (expected));
diff --git a/testsuite/gtk/builder.c b/testsuite/gtk/builder.c
index c7178d476d..15afb24c4d 100644
--- a/testsuite/gtk/builder.c
+++ b/testsuite/gtk/builder.c
@@ -1390,6 +1390,58 @@ test_message_dialog (void)
}
static void
+test_accelerators (void)
+{
+ GtkBuilder *builder;
+ const gchar *buffer =
+ "<interface>"
+ " <object class=\"GtkWindow\" id=\"window1\">"
+ " <child>"
+ " <object class=\"GtkButton\" id=\"button1\">"
+ " <accelerator key=\"q\" modifiers=\"GDK_CONTROL_MASK\" signal=\"clicked\"/>"
+ " </object>"
+ " </child>"
+ " </object>"
+ "</interface>";
+ const gchar *buffer2 =
+ "<interface>"
+ " <object class=\"GtkWindow\" id=\"window1\">"
+ " <child>"
+ " <object class=\"GtkTreeView\" id=\"treeview1\">"
+ " </object>"
+ " </child>"
+ " </object>"
+ "</interface>";
+ GObject *window1;
+ GSList *accel_groups;
+ GObject *accel_group;
+
+ builder = builder_new_from_string (buffer, -1, NULL);
+ window1 = gtk_builder_get_object (builder, "window1");
+ g_assert (window1);
+ g_assert (GTK_IS_WINDOW (window1));
+
+ accel_groups = gtk_accel_groups_from_object (window1);
+ g_assert (g_slist_length (accel_groups) == 1);
+ accel_group = g_slist_nth_data (accel_groups, 0);
+ g_assert (accel_group);
+
+ gtk_widget_destroy (GTK_WIDGET (window1));
+ g_object_unref (builder);
+
+ builder = builder_new_from_string (buffer2, -1, NULL);
+ window1 = gtk_builder_get_object (builder, "window1");
+ g_assert (window1);
+ g_assert (GTK_IS_WINDOW (window1));
+
+ accel_groups = gtk_accel_groups_from_object (window1);
+ g_assert_cmpint (g_slist_length (accel_groups), ==, 0);
+
+ gtk_widget_destroy (GTK_WIDGET (window1));
+ g_object_unref (builder);
+}
+
+static void
test_widget (void)
{
const gchar *buffer =
@@ -2445,6 +2497,7 @@ main (int argc, char **argv)
#endif
g_test_add_func ("/Builder/CellView", test_cell_view);
g_test_add_func ("/Builder/Dialog", test_dialog);
+ g_test_add_func ("/Builder/Accelerators", test_accelerators);
g_test_add_func ("/Builder/Widget", test_widget);
g_test_add_func ("/Builder/Value From String", test_value_from_string);
g_test_add_func ("/Builder/Reference Counting", test_reference_counting);
diff --git a/testsuite/gtk/concatmodel.c b/testsuite/gtk/concatmodel.c
deleted file mode 100644
index 3e6292b536..0000000000
--- a/testsuite/gtk/concatmodel.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/* GtkRBTree tests.
- *
- * Copyright (C) 2011, Red Hat, Inc.
- * Authors: Benjamin Otte <otte@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <locale.h>
-
-#include "../../gtk/gtkconcatmodelprivate.h"
-
-/* _gtk_rbtree_test */
-
-static GQuark number_quark;
-static GQuark changes_quark;
-
-static guint
-get (GListModel *model,
- guint position)
-{
- GObject *object = g_list_model_get_item (model, position);
- g_assert (object != NULL);
- return GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark));
-}
-
-static char *
-model_to_string (GListModel *model)
-{
- GString *string = g_string_new (NULL);
- guint i;
-
- for (i = 0; i < g_list_model_get_n_items (model); i++)
- {
- if (i > 0)
- g_string_append (string, " ");
- g_string_append_printf (string, "%u", get (model, i));
- }
-
- return g_string_free (string, FALSE);
-}
-
-static void
-add (GListStore *store,
- guint number)
-{
- GObject *object;
-
- /* o cannot be differentiated from NULL, so don't use it */
- g_assert (number != 0);
-
- object = g_object_new (G_TYPE_OBJECT, NULL);
- g_object_set_qdata (object, number_quark, GUINT_TO_POINTER (number));
- g_list_store_append (store, object);
- g_object_unref (object);
-}
-
-static void
-remove (GListStore *store,
- guint position)
-{
- g_list_store_remove (store, position);
-}
-
-#define assert_model(model, expected) G_STMT_START{ \
- char *s = model_to_string (G_LIST_MODEL (model)); \
- if (!g_str_equal (s, expected)) \
- g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
- #model " == " #expected, s, "==", expected); \
- g_free (s); \
-}G_STMT_END
-
-#define assert_changes(model, expected) G_STMT_START{ \
- GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \
- if (!g_str_equal (changes->str, expected)) \
- g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \
- #model " == " #expected, changes->str, "==", expected); \
- g_string_set_size (changes, 0); \
-}G_STMT_END
-
-static GListStore *
-new_empty_store (void)
-{
- return g_list_store_new (G_TYPE_OBJECT);
-}
-
-static GListStore *
-new_store (guint start,
- guint end)
-{
- GListStore *store = new_empty_store ();
- guint i;
-
- for (i = start; i <= end; i++)
- add (store, i);
-
- return store;
-}
-
-static void
-items_changed (GListModel *model,
- guint position,
- guint removed,
- guint added,
- GString *changes)
-{
- g_assert (removed != 0 || added != 0);
-
- if (changes->len)
- g_string_append (changes, ", ");
-
- if (removed == 1 && added == 0)
- {
- g_string_append_printf (changes, "-%u", position);
- }
- else if (removed == 0 && added == 1)
- {
- g_string_append_printf (changes, "+%u", position);
- }
- else
- {
- g_string_append_printf (changes, "%u", position);
- if (removed > 0)
- g_string_append_printf (changes, "-%u", removed);
- if (added > 0)
- g_string_append_printf (changes, "+%u", added);
- }
-}
-
-static void
-free_changes (gpointer data)
-{
- GString *changes = data;
-
- /* all changes must have been checked via assert_changes() before */
- g_assert_cmpstr (changes->str, ==, "");
-
- g_string_free (changes, TRUE);
-}
-
-static GtkConcatModel *
-new_model (void)
-{
- GtkConcatModel *model = gtk_concat_model_new (G_TYPE_OBJECT);
- GString *changes;
-
- changes = g_string_new ("");
- g_object_set_qdata_full (G_OBJECT(model), changes_quark, changes, free_changes);
- g_signal_connect (model, "items-changed", G_CALLBACK (items_changed), changes);
-
- return model;
-}
-
-static void
-test_append (void)
-{
- GListStore *store = new_store (1, 3);
- GtkConcatModel *concat = new_model ();
-
- gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
- assert_model (concat, "1 2 3");
- assert_changes (concat, "0+3");
-
- g_object_unref (store);
- g_object_unref (concat);
-}
-
-static void
-test_append_and_add (void)
-{
- GListStore *store = new_empty_store ();
- GtkConcatModel *concat = new_model ();
-
- gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
- add (store, 1);
- add (store, 2);
- add (store, 3);
- assert_model (concat, "1 2 3");
- assert_changes (concat, "+0, +1, +2");
-
- g_object_unref (store);
- g_object_unref (concat);
-}
-
-static void
-test_append_and_remove (void)
-{
- GListStore *store = new_store (1, 3);
- GtkConcatModel *concat = new_model ();
-
- gtk_concat_model_append (concat, G_LIST_MODEL (store));
- gtk_concat_model_remove (concat, G_LIST_MODEL (store));
-
- assert_model (concat, "");
- assert_changes (concat, "0+3, 0-3");
-
- /* Check that all signal handlers are gone */
- g_list_store_remove_all (store);
-
- g_object_unref (store);
- g_object_unref (concat);
-}
-
-static void
-test_append_and_remove_items (void)
-{
- GListStore *store = new_empty_store ();
- GtkConcatModel *concat = new_model ();
-
- gtk_concat_model_append (concat, G_LIST_MODEL (store));
-
- add (store, 1);
- add (store, 2);
- add (store, 3);
- remove (store, 0);
- remove (store, 1);
- remove (store, 0);
-
- assert_model (concat, "");
- assert_changes (concat, "+0, +1, +2, -0, -1, -0");
-
- g_object_unref (store);
- g_object_unref (concat);
-}
-
-static void
-test_append_many (void)
-{
- GListStore *store[5] = { new_store (1, 3), new_store (4, 4), new_store (5, 10), new_empty_store (), new_store (11, 20) };
- GtkConcatModel *concat = new_model ();
- guint i;
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
-
- assert_model (concat, "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20");
- assert_changes (concat, "0+3, +3, 4+6, 10+10");
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- g_object_unref (store[i]);
- g_object_unref (concat);
-}
-
-static void
-test_append_many_and_add (void)
-{
- GListStore *store[3];
- GtkConcatModel *concat = new_model ();
- guint i, j;
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- {
- store[i] = new_empty_store ();
- gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
- }
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- {
- for (j = 0; j < G_N_ELEMENTS (store); j++)
- {
- add (store[(i + j) % G_N_ELEMENTS (store)], i * 3 + j + 1);
- }
- }
-
- assert_model (concat, "1 6 8 2 4 9 3 5 7");
- assert_changes (concat, "+0, +1, +2, +2, +4, +1, +6, +2, +5");
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- g_object_unref (store[i]);
- g_object_unref (concat);
-}
-
-static void
-test_append_many_and_remove (void)
-{
- GListStore *store[5];
- GtkConcatModel *concat = new_model ();
- guint i;
-
- store[0] = new_empty_store ();
- gtk_concat_model_append (concat, G_LIST_MODEL (store[0]));
- for (i = 1; i < G_N_ELEMENTS (store); i++)
- {
- store[i] = new_store (i * (i - 1) / 2 + 1, i * (i + 1) / 2);
- gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
- }
-
- assert_model (concat, "1 2 3 4 5 6 7 8 9 10");
- assert_changes (concat, "+0, 1+2, 3+3, 6+4");
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- {
- gtk_concat_model_remove (concat, G_LIST_MODEL (store[(3 * i) % G_N_ELEMENTS (store)]));
- }
-
- assert_model (concat, "");
- assert_changes (concat, "3-3, -0, 2-4, 0-2");
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- {
- g_list_store_remove_all (store[i]);
- g_object_unref (store[i]);
- }
-
- g_object_unref (concat);
-}
-
-static void
-test_append_many_and_remove_items (void)
-{
- GListStore *store[5];
- GtkConcatModel *concat = new_model ();
- guint i;
-
- store[0] = new_empty_store ();
- gtk_concat_model_append (concat, G_LIST_MODEL (store[0]));
- for (i = 1; i < G_N_ELEMENTS (store); i++)
- {
- store[i] = new_store (i * (i - 1) / 2 + 1, i * (i + 1) / 2);
- gtk_concat_model_append (concat, G_LIST_MODEL (store[i]));
- }
-
- assert_model (concat, "1 2 3 4 5 6 7 8 9 10");
- assert_changes (concat, "+0, 1+2, 3+3, 6+4");
-
- for (i = 1; i < G_N_ELEMENTS (store); i++)
- {
- remove (store[i], 3 % i);
- }
-
- assert_model (concat, "2 5 6 7 8 9");
- assert_changes (concat, "-0, -1, -1, -6");
-
- for (i = 0; i < G_N_ELEMENTS (store); i++)
- g_object_unref (store[i]);
- g_object_unref (concat);
-}
-
-int
-main (int argc, char *argv[])
-{
- g_test_init (&argc, &argv, NULL);
- setlocale (LC_ALL, "C");
- g_test_bug_base ("http://bugzilla.gnome.org/show_bug.cgi?id=%s");
-
- number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released.");
- changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?");
-
- g_test_add_func ("/compatmodel/append", test_append);
- g_test_add_func ("/compatmodel/append_and_add", test_append_and_add);
- g_test_add_func ("/compatmodel/append_and_remove", test_append_and_remove);
- g_test_add_func ("/compatmodel/append_and_remove_items", test_append_and_remove_items);
- g_test_add_func ("/compatmodel/append_many", test_append_many);
- g_test_add_func ("/compatmodel/append_many_and_add", test_append_many_and_add);
- g_test_add_func ("/compatmodel/append_many_and_remove", test_append_many_and_remove);
- g_test_add_func ("/compatmodel/append_many_and_remove_items", test_append_many_and_remove_items);
-
- return g_test_run ();
-}
diff --git a/testsuite/gtk/defaultvalue.c b/testsuite/gtk/defaultvalue.c
index 4222c32b70..ab735dc482 100644
--- a/testsuite/gtk/defaultvalue.c
+++ b/testsuite/gtk/defaultvalue.c
@@ -324,11 +324,6 @@ G_GNUC_END_IGNORE_DEPRECATIONS
if (g_type_is_a (type, GTK_TYPE_SETTINGS))
continue;
- if (g_type_is_a (type, GTK_TYPE_SHORTCUT) &&
- (strcmp (pspec->name, "action") == 0 ||
- strcmp (pspec->name, "trigger") == 0))
- continue;
-
if (g_type_is_a (type, GTK_TYPE_SPIN_BUTTON) &&
(strcmp (pspec->name, "adjustment") == 0))
continue;
diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build
index 15c32cd2a3..983a33ffad 100644
--- a/testsuite/gtk/meson.build
+++ b/testsuite/gtk/meson.build
@@ -17,7 +17,6 @@ tests = [
['builderparser'],
['cellarea'],
['check-icon-names'],
- ['concatmodel', ['../../gtk/gtkconcatmodel.c'], ['-DGTK_COMPILATION', '-UG_ENABLE_DEBUG']],
['constraint-solver', [
'../../gtk/gtkconstraintsolver.c',
'../../gtk/gtkconstraintexpression.c',
@@ -65,6 +64,7 @@ tests = [
['treepath'],
['treeview'],
['typename'],
+ ['window'],
['displayclose'],
['revealer-size'],
['widgetorder'],
@@ -72,10 +72,6 @@ tests = [
# Tests that are expected to fail
xfail = [
- # one of the window resizing tests fails after
- # the GdkToplevel refactoring, and needs a big
- # gtkwindow.c configure request cleanup
- 'window',
]
is_debug = get_option('buildtype').startswith('debug')