summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Natterer <mitch@imendio.com>2007-06-04 15:00:22 +0000
committerMichael Natterer <mitch@src.gnome.org>2007-06-04 15:00:22 +0000
commite631aef88191c44f199cb54ee6b75304b63193db (patch)
tree90b35c10c557ac55992c95dbdaffd3688c809d94
parent17df875136d184f15d4601fe38c82e98b830be45 (diff)
downloadgdk-pixbuf-e631aef88191c44f199cb54ee6b75304b63193db.tar.gz
Move "move-focus" signals from several widgets to GtkWidget to enable more
2007-06-04 Michael Natterer <mitch@imendio.com> Move "move-focus" signals from several widgets to GtkWidget to enable more flexible costomization of keyboard navigation via bindings. Fixes bug #414947. * gtk/gtkwidget.c: add "move-focus" binding signal, default to calling the toplevel GtkWindow's "move-focus" vfunc. * gtk/gtktextview.[ch] * gtk/gtkwindow.[ch]: remove "move-focus" signals and add compat code that makes sure that both emitting the signal on the widget and overriding the virtual functions keeps working as before. * gtk/gtktoolbar.c: remove "move-focus" signal here too and use GtkWidget's signal. This change slightly changes keyboard navigation in toolbars. I'll fix the behavior if somebody can explain me if and how exactly the new behavior is broken. svn path=/trunk/; revision=18025
-rw-r--r--ChangeLog19
-rw-r--r--gtk/gtktextview.c88
-rw-r--r--gtk/gtktextview.h10
-rw-r--r--gtk/gtktoolbar.c50
-rw-r--r--gtk/gtkwidget.c27
-rw-r--r--gtk/gtkwindow.c12
-rw-r--r--gtk/gtkwindow.h5
7 files changed, 141 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 66dde2dc0..3285c4ec4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-06-04 Michael Natterer <mitch@imendio.com>
+
+ Move "move-focus" signals from several widgets to GtkWidget to
+ enable more flexible costomization of keyboard navigation via
+ bindings. Fixes bug #414947.
+
+ * gtk/gtkwidget.c: add "move-focus" binding signal, default to
+ calling the toplevel GtkWindow's "move-focus" vfunc.
+
+ * gtk/gtktextview.[ch]
+ * gtk/gtkwindow.[ch]: remove "move-focus" signals and add compat
+ code that makes sure that both emitting the signal on the widget
+ and overriding the virtual functions keeps working as before.
+
+ * gtk/gtktoolbar.c: remove "move-focus" signal here too and use
+ GtkWidget's signal. This change slightly changes keyboard
+ navigation in toolbars. I'll fix the behavior if somebody can
+ explain me if and how exactly the new behavior is broken.
+
2007-06-04 Matthias Clasen <mclasen@redhat.com>
* gtk/gtkmarshalers.list:
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index 6c7f68482..f37a04de8 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -133,7 +133,6 @@ enum
COPY_CLIPBOARD,
PASTE_CLIPBOARD,
TOGGLE_OVERWRITE,
- MOVE_FOCUS,
MOVE_VIEWPORT,
SELECT_ALL,
TOGGLE_CURSOR_VISIBLE,
@@ -206,6 +205,8 @@ static gint gtk_text_view_expose_event (GtkWidget *widget,
static void gtk_text_view_draw_focus (GtkWidget *widget);
static gboolean gtk_text_view_focus (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_text_view_move_focus (GtkWidget *widget,
+ GtkDirectionType direction_type);
static void gtk_text_view_select_all (GtkWidget *widget,
gboolean select);
@@ -278,7 +279,7 @@ static void gtk_text_view_copy_clipboard (GtkTextView *text_view);
static void gtk_text_view_paste_clipboard (GtkTextView *text_view);
static void gtk_text_view_toggle_overwrite (GtkTextView *text_view);
static void gtk_text_view_toggle_cursor_visible (GtkTextView *text_view);
-static void gtk_text_view_move_focus (GtkTextView *text_view,
+static void gtk_text_view_compat_move_focus(GtkTextView *text_view,
GtkDirectionType direction_type);
static void gtk_text_view_unselect (GtkTextView *text_view);
@@ -490,7 +491,16 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
widget_class->motion_notify_event = gtk_text_view_motion_event;
widget_class->expose_event = gtk_text_view_expose_event;
widget_class->focus = gtk_text_view_focus;
-
+
+ /* need to override the base class function via override_class_closure,
+ * because the signal slot is not available in GtkWidgetCLass
+ */
+ g_signal_override_class_closure (g_signal_lookup ("move-focus",
+ GTK_TYPE_WIDGET),
+ GTK_TYPE_TEXT_VIEW,
+ g_cclosure_new (G_CALLBACK (gtk_text_view_move_focus),
+ NULL, NULL));
+
widget_class->drag_begin = gtk_text_view_drag_begin;
widget_class->drag_end = gtk_text_view_drag_end;
widget_class->drag_data_get = gtk_text_view_drag_data_get;
@@ -517,7 +527,7 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
klass->copy_clipboard = gtk_text_view_copy_clipboard;
klass->paste_clipboard = gtk_text_view_paste_clipboard;
klass->toggle_overwrite = gtk_text_view_toggle_overwrite;
- klass->move_focus = gtk_text_view_move_focus;
+ klass->move_focus = gtk_text_view_compat_move_focus;
klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;
/*
@@ -787,16 +797,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
_gtk_marshal_VOID__VOID,
G_TYPE_NONE, 0);
- signals[MOVE_FOCUS] =
- g_signal_new (I_("move_focus"),
- G_OBJECT_CLASS_TYPE (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkTextViewClass, move_focus),
- NULL, NULL,
- _gtk_marshal_VOID__ENUM,
- G_TYPE_NONE, 1,
- GTK_TYPE_DIRECTION_TYPE);
-
signals[SET_SCROLL_ADJUSTMENTS] =
g_signal_new (I_("set_scroll_adjustments"),
G_OBJECT_CLASS_TYPE (gobject_class),
@@ -3927,9 +3927,9 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
obscure = TRUE;
}
else
- gtk_text_view_move_focus (text_view,
- (event->state & GDK_SHIFT_MASK) ?
- GTK_DIR_TAB_BACKWARD: GTK_DIR_TAB_FORWARD);
+ g_signal_emit_by_name (text_view, "move-focus",
+ (event->state & GDK_SHIFT_MASK) ?
+ GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD);
retval = TRUE;
}
@@ -4384,6 +4384,17 @@ gtk_text_view_focus (GtkWidget *widget,
}
}
+static void
+gtk_text_view_move_focus (GtkWidget *widget,
+ GtkDirectionType direction_type)
+{
+ GtkTextView *text_view = GTK_TEXT_VIEW (widget);
+
+ if (GTK_TEXT_VIEW_GET_CLASS (text_view)->move_focus)
+ GTK_TEXT_VIEW_GET_CLASS (text_view)->move_focus (text_view,
+ direction_type);
+}
+
/*
* Container
*/
@@ -4894,7 +4905,7 @@ gtk_text_view_move_cursor_internal (GtkTextView *text_view,
if (!gtk_widget_keynav_failed (GTK_WIDGET (text_view),
leave_direction))
{
- gtk_text_view_move_focus (text_view, leave_direction);
+ g_signal_emit_by_name (text_view, "move-focus", leave_direction);
}
}
else
@@ -5508,16 +5519,43 @@ gtk_text_view_get_accepts_tab (GtkTextView *text_view)
}
static void
-gtk_text_view_move_focus (GtkTextView *text_view,
- GtkDirectionType direction_type)
+gtk_text_view_compat_move_focus (GtkTextView *text_view,
+ GtkDirectionType direction_type)
{
- GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (text_view));
+ GSignalInvocationHint *hint = g_signal_get_invocation_hint (text_view);
- if (!GTK_WIDGET_TOPLEVEL (toplevel))
- return;
+ /* as of GTK+ 2.12, the "move-focus" signal has been moved to GtkWidget,
+ * the evil code below makes sure that both emitting the signal and
+ * calling the virtual function directly continue to work as expetcted
+ */
+
+ if (hint->signal_id == g_signal_lookup ("move-focus", GTK_TYPE_WIDGET))
+ {
+ /* if this is a signal emission, chain up */
+
+ GValue instance_and_params[2] = { { 0, }, { 0, } };
+ GValue return_value = { 0, };
+
+ g_value_init (&instance_and_params[0], GTK_TYPE_WIDGET);
+ g_value_set_object (&instance_and_params[0], text_view);
+
+ g_value_init (&instance_and_params[1], GTK_TYPE_DIRECTION_TYPE);
+ g_value_set_enum (&instance_and_params[1], direction_type);
- /* Propagate to toplevel */
- g_signal_emit_by_name (toplevel, "move_focus", direction_type);
+ g_signal_chain_from_overridden (instance_and_params, &return_value);
+
+ g_value_unset (&instance_and_params[0]);
+ g_value_unset (&instance_and_params[1]);
+ g_value_unset (&return_value);
+ }
+ else
+ {
+ /* otherwise emit the signal, since somebody called the virtual
+ * function directly
+ */
+
+ g_signal_emit_by_name (text_view, "move-focus", direction_type);
+ }
}
/*
diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h
index 906293533..d5223118e 100644
--- a/gtk/gtktextview.h
+++ b/gtk/gtktextview.h
@@ -195,11 +195,13 @@ struct _GtkTextViewClass
/* overwrite */
void (* toggle_overwrite) (GtkTextView *text_view);
- /* propagates to GtkWindow move_focus */
+ /* as of GTK+ 2.12 the "move-focus" signal has been moved to GtkWidget,
+ * so this is merley a virtual function now. Overriding it in subclasses
+ * continues to work though.
+ */
void (* move_focus) (GtkTextView *text_view,
- GtkDirectionType direction);
-
-
+ GtkDirectionType direction);
+
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
diff --git a/gtk/gtktoolbar.c b/gtk/gtktoolbar.c
index 7f19352e6..8230c1149 100644
--- a/gtk/gtktoolbar.c
+++ b/gtk/gtktoolbar.c
@@ -103,7 +103,6 @@ enum {
ORIENTATION_CHANGED,
STYLE_CHANGED,
POPUP_CONTEXT_MENU,
- MOVE_FOCUS,
FOCUS_HOME_OR_END,
LAST_SIGNAL
};
@@ -173,6 +172,8 @@ static void gtk_toolbar_style_set (GtkWidget *widget,
GtkStyle *prev_style);
static gboolean gtk_toolbar_focus (GtkWidget *widget,
GtkDirectionType dir);
+static void gtk_toolbar_move_focus (GtkWidget *widget,
+ GtkDirectionType dir);
static void gtk_toolbar_screen_changed (GtkWidget *widget,
GdkScreen *previous_screen);
static void gtk_toolbar_map (GtkWidget *widget);
@@ -203,8 +204,6 @@ static void gtk_toolbar_orientation_changed (GtkToolbar *toolbar
GtkOrientation orientation);
static void gtk_toolbar_real_style_changed (GtkToolbar *toolbar,
GtkToolbarStyle style);
-static gboolean gtk_toolbar_move_focus (GtkToolbar *toolbar,
- GtkDirectionType dir);
static gboolean gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
gboolean focus_home);
static gboolean gtk_toolbar_button_press (GtkWidget *toolbar,
@@ -359,6 +358,16 @@ gtk_toolbar_class_init (GtkToolbarClass *klass)
widget_class->size_allocate = gtk_toolbar_size_allocate;
widget_class->style_set = gtk_toolbar_style_set;
widget_class->focus = gtk_toolbar_focus;
+
+ /* need to override the base class function via override_class_closure,
+ * because the signal slot is not available in GtkWidgetClass
+ */
+ g_signal_override_class_closure (g_signal_lookup ("move_focus",
+ GTK_TYPE_WIDGET),
+ GTK_TYPE_TOOLBAR,
+ g_cclosure_new (G_CALLBACK (gtk_toolbar_move_focus),
+ NULL, NULL));
+
widget_class->screen_changed = gtk_toolbar_screen_changed;
widget_class->realize = gtk_toolbar_realize;
widget_class->unrealize = gtk_toolbar_unrealize;
@@ -438,25 +447,7 @@ gtk_toolbar_class_init (GtkToolbarClass *klass)
G_TYPE_BOOLEAN, 3,
G_TYPE_INT, G_TYPE_INT,
G_TYPE_INT);
- /**
- * GtkToolbar::move-focus:
- * @toolbar: the #GtkToolbar which emitted the signal
- * @dir: a #GtkDirection
- *
- * A keybinding signal used internally by GTK+. This signal can't
- * be used in application code.
- *
- * Return value: %TRUE if the signal was handled, %FALSE if not
- */
- toolbar_signals[MOVE_FOCUS] =
- _gtk_binding_signal_new (I_("move_focus"),
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_CALLBACK (gtk_toolbar_move_focus),
- NULL, NULL,
- _gtk_marshal_BOOLEAN__ENUM,
- G_TYPE_BOOLEAN, 1,
- GTK_TYPE_DIRECTION_TYPE);
+
/**
* GtkToolbar::focus-home-or-end:
* @toolbar: the #GtkToolbar which emitted the signal
@@ -1921,19 +1912,22 @@ gtk_toolbar_focus_home_or_end (GtkToolbar *toolbar,
/* Keybinding handler. This function is called when the user presses
* Ctrl TAB or an arrow key.
*/
-static gboolean
-gtk_toolbar_move_focus (GtkToolbar *toolbar,
+static void
+gtk_toolbar_move_focus (GtkWidget *widget,
GtkDirectionType dir)
{
+ GtkToolbar *toolbar = GTK_TOOLBAR (widget);
+ GtkContainer *container = GTK_CONTAINER (toolbar);
GList *list;
gboolean try_focus = FALSE;
GList *children;
- GtkContainer *container = GTK_CONTAINER (toolbar);
-
+
+ g_printerr ("%s (dir = %d)\n", G_STRFUNC, dir);
+
if (container->focus_child &&
gtk_widget_child_focus (container->focus_child, dir))
{
- return TRUE;
+ return;
}
children = gtk_toolbar_list_children_in_focus_order (toolbar, dir);
@@ -1950,8 +1944,6 @@ gtk_toolbar_move_focus (GtkToolbar *toolbar,
}
g_list_free (children);
-
- return FALSE;
}
/* The focus handler for the toolbar. It called when the user presses
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 0ac93d79c..59e91f81a 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -77,6 +77,7 @@ enum {
MNEMONIC_ACTIVATE,
GRAB_FOCUS,
FOCUS,
+ MOVE_FOCUS,
EVENT,
EVENT_AFTER,
BUTTON_PRESS_EVENT,
@@ -214,6 +215,8 @@ static gboolean gtk_widget_real_focus_out_event (GtkWidget *widget,
GdkEventFocus *event);
static gboolean gtk_widget_real_focus (GtkWidget *widget,
GtkDirectionType direction);
+static void gtk_widget_real_move_focus (GtkWidget *widget,
+ GtkDirectionType direction);
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction);
static PangoContext* gtk_widget_peek_pango_context (GtkWidget *widget);
@@ -830,6 +833,16 @@ gtk_widget_class_init (GtkWidgetClass *klass)
_gtk_marshal_BOOLEAN__ENUM,
G_TYPE_BOOLEAN, 1,
GTK_TYPE_DIRECTION_TYPE);
+ widget_signals[MOVE_FOCUS] =
+ _gtk_binding_signal_new (I_("move_focus"),
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+ G_CALLBACK (gtk_widget_real_move_focus),
+ NULL, NULL,
+ _gtk_marshal_VOID__ENUM,
+ G_TYPE_NONE,
+ 1,
+ GTK_TYPE_DIRECTION_TYPE);
widget_signals[EVENT] =
g_signal_new (I_("event"),
G_TYPE_FROM_CLASS (gobject_class),
@@ -4618,6 +4631,20 @@ gtk_widget_real_focus (GtkWidget *widget,
return FALSE;
}
+static void
+gtk_widget_real_move_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
+
+ if (GTK_IS_WINDOW (toplevel) &&
+ GTK_WINDOW_GET_CLASS (toplevel)->move_focus)
+ {
+ GTK_WINDOW_GET_CLASS (toplevel)->move_focus (GTK_WINDOW (toplevel),
+ direction);
+ }
+}
+
static gboolean
gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction)
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index b1943d7ec..a51c00a7c 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -57,7 +57,6 @@ enum {
FRAME_EVENT,
ACTIVATE_FOCUS,
ACTIVATE_DEFAULT,
- MOVE_FOCUS,
KEYS_CHANGED,
LAST_SIGNAL
};
@@ -789,17 +788,6 @@ gtk_window_class_init (GtkWindowClass *klass)
G_TYPE_NONE,
0);
- window_signals[MOVE_FOCUS] =
- g_signal_new (I_("move_focus"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkWindowClass, move_focus),
- NULL, NULL,
- _gtk_marshal_VOID__ENUM,
- G_TYPE_NONE,
- 1,
- GTK_TYPE_DIRECTION_TYPE);
-
window_signals[KEYS_CHANGED] =
g_signal_new (I_("keys_changed"),
G_TYPE_FROM_CLASS (gobject_class),
diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h
index c32dc5946..2f84c497c 100644
--- a/gtk/gtkwindow.h
+++ b/gtk/gtkwindow.h
@@ -125,6 +125,11 @@ struct _GtkWindowClass
void (* activate_focus) (GtkWindow *window);
void (* activate_default) (GtkWindow *window);
+
+ /* as of GTK+ 2.12 the "move-focus" signal has been moved to GtkWidget,
+ * so this is merley a virtual function now. Overriding it in subclasses
+ * continues to work though.
+ */
void (* move_focus) (GtkWindow *window,
GtkDirectionType direction);