Code

Add handling of focus tabbing for GdlDockItem + various DockItem focus
authorgustav_b <gustav_b@users.sourceforge.net>
Sun, 16 Sep 2007 15:30:50 +0000 (15:30 +0000)
committergustav_b <gustav_b@users.sourceforge.net>
Sun, 16 Sep 2007 15:30:50 +0000 (15:30 +0000)
fixes.

src/libgdl/gdl-dock-item-grip.c
src/libgdl/gdl-dock-item.c
src/libgdl/gdl-dock-item.h
src/libgdl/libgdlmarshal.c
src/libgdl/libgdlmarshal.h
src/libgdl/libgdlmarshal.list
src/ui/widget/dock-item.cpp

index d1ba2372c19b20a62744a14724e7592b3de9708e..86e7bc14c3d59fe0163ae0ce2906d69e470ae8b5 100644 (file)
@@ -135,14 +135,17 @@ gdl_dock_item_grip_expose (GtkWidget      *widget,
     gint             layout_height;
     gint             text_x;
     gint             text_y;
+    gboolean         item_or_child_has_focus;
 
     grip = GDL_DOCK_ITEM_GRIP (widget);
     gdl_dock_item_grip_get_title_area (grip, &title_area);
 
-    /* draw background, highlight it if the dock item has focus */
-    bg_style = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (grip->item)) ? 
-                gtk_widget_get_style (widget)->mid_gc[widget->state] :
-                gtk_widget_get_style (widget)->dark_gc[widget->state]);
+    /* draw background, highlight it if the dock item or any of its
+     * descendants have focus */
+    bg_style = (gdl_dock_item_or_child_has_focus (grip->item) ?
+                gtk_widget_get_style (widget)->dark_gc[widget->state] :
+                gtk_widget_get_style (widget)->mid_gc[widget->state]);
+
     gdk_draw_rectangle (GDK_DRAWABLE (widget->window), bg_style, TRUE,
                         1, 0, widget->allocation.width - 1, widget->allocation.height);
 
index 87fbb41a08474779f71ded6b803a787d499ab471..3be8dd3e2a216c0b48e6235c74e2f1e08a14f192 100644 (file)
@@ -81,6 +81,10 @@ static void  gdl_dock_item_forall        (GtkContainer *container,
                                           gpointer      callback_data);
 static GtkType gdl_dock_item_child_type  (GtkContainer *container);
 
+static void  gdl_dock_item_set_focus_child (GtkContainer *container,
+                                            GtkWidget    *widget,
+                                            gpointer      callback_data);
+
 static void  gdl_dock_item_size_request  (GtkWidget *widget,
                                           GtkRequisition *requisition);
 static void  gdl_dock_item_size_allocate (GtkWidget *widget,
@@ -93,6 +97,9 @@ static void  gdl_dock_item_style_set     (GtkWidget *widget,
 static gint  gdl_dock_item_expose        (GtkWidget *widget,
                                           GdkEventExpose *event);
 
+static void  gdl_dock_item_move_focus_child (GdlDockItem      *item,
+                                             GtkDirectionType  dir);
+
 static gint  gdl_dock_item_button_changed (GtkWidget *widget,
                                            GdkEventButton *event);
 static gint  gdl_dock_item_motion         (GtkWidget *widget,
@@ -157,6 +164,7 @@ enum {
     DOCK_DRAG_BEGIN,
     DOCK_DRAG_MOTION,
     DOCK_DRAG_END,
+    MOVE_FOCUS_CHILD,
     LAST_SIGNAL
 };
 
@@ -191,6 +199,40 @@ struct _GdlDockItemPrivate {
 
 GDL_CLASS_BOILERPLATE (GdlDockItem, gdl_dock_item, GdlDockObject, GDL_TYPE_DOCK_OBJECT);
 
+static void
+add_tab_bindings (GtkBindingSet    *binding_set,
+                 GdkModifierType   modifiers,
+                 GtkDirectionType  direction)
+{
+    gtk_binding_entry_add_signal (binding_set, GDK_Tab, modifiers,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
+static void
+add_arrow_bindings (GtkBindingSet    *binding_set,
+                   guint             keysym,
+                   GtkDirectionType  direction)
+{
+    guint keypad_keysym = keysym - GDK_Left + GDK_KP_Left;
+
+    gtk_binding_entry_add_signal (binding_set, keysym, 0,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+    gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
+                                  "move_focus_child", 1,
+                                  GTK_TYPE_DIRECTION_TYPE, direction);
+}
+
 static void
 gdl_dock_item_class_init (GdlDockItemClass *klass)
 {
@@ -201,6 +243,7 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
     GtkWidgetClass     *widget_class;
     GtkContainerClass  *container_class;
     GdlDockObjectClass *object_class;
+    GtkBindingSet      *binding_set;
     
     g_object_class = G_OBJECT_CLASS (klass);
     gtk_object_class = GTK_OBJECT_CLASS (klass);
@@ -230,6 +273,7 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
     container_class->remove = gdl_dock_item_remove;
     container_class->forall = gdl_dock_item_forall;
     container_class->child_type = gdl_dock_item_child_type;
+    container_class->set_focus_child = gdl_dock_item_set_focus_child;
     
     object_class->is_compound = FALSE;
 
@@ -332,10 +376,38 @@ gdl_dock_item_class_init (GdlDockItemClass *klass)
                       1,
                       G_TYPE_BOOLEAN);
 
+    gdl_dock_item_signals [MOVE_FOCUS_CHILD] =
+        g_signal_new ("move_focus_child",
+                      G_TYPE_FROM_CLASS (klass),
+                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                      G_STRUCT_OFFSET (GdlDockItemClass, move_focus_child),
+                      NULL, /* accumulator */
+                      NULL, /* accu_data */
+                      gdl_marshal_VOID__ENUM,
+                      G_TYPE_NONE,
+                      1,
+                      GTK_TYPE_DIRECTION_TYPE);
+
+
+    /* key bindings */
+
+    binding_set = gtk_binding_set_by_class (klass);
+
+    add_arrow_bindings (binding_set, GDK_Up, GTK_DIR_UP);
+    add_arrow_bindings (binding_set, GDK_Down, GTK_DIR_DOWN);
+    add_arrow_bindings (binding_set, GDK_Left, GTK_DIR_LEFT);
+    add_arrow_bindings (binding_set, GDK_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);
+
     klass->has_grip = TRUE;
     klass->dock_drag_begin = NULL;
     klass->dock_drag_motion = NULL;
     klass->dock_drag_end = NULL;
+    klass->move_focus_child = gdl_dock_item_move_focus_child;
     klass->set_orientation = gdl_dock_item_real_set_orientation;
 
     if (!style_initialized)
@@ -623,6 +695,19 @@ gdl_dock_item_child_type (GtkContainer *container)
         return G_TYPE_NONE;
 }
 
+static void
+gdl_dock_item_set_focus_child (GtkContainer *container,
+                               GtkWidget    *child,
+                               gpointer      callback_data)
+{
+    g_return_if_fail (GDL_IS_DOCK_ITEM (container));
+    
+    if (GTK_CONTAINER_CLASS (parent_class)->set_focus_child)
+        (* GTK_CONTAINER_CLASS (parent_class)->set_focus_child) (container, child);
+
+    gdl_dock_item_showhide_grip (GDL_DOCK_ITEM (container));
+}
+
 static void
 gdl_dock_item_size_request (GtkWidget      *widget,
                             GtkRequisition *requisition)
@@ -879,6 +964,14 @@ gdl_dock_item_expose (GtkWidget      *widget,
     return FALSE;
 }
 
+static void
+gdl_dock_item_move_focus_child (GdlDockItem      *item,
+                                GtkDirectionType  dir)
+{
+    g_return_if_fail (GDL_IS_DOCK_ITEM (item));
+    gtk_widget_child_focus (GTK_WIDGET (item->child), dir);
+}
+
 #define EVENT_IN_GRIP_EVENT_WINDOW(ev,gr) \
     ((gr) != NULL && (ev)->window == GDL_DOCK_ITEM_GRIP (gr)->title_window)
 
@@ -923,6 +1016,10 @@ gdl_dock_item_button_changed (GtkWidget      *widget,
 
     /* Left mousebutton click on dockitem. */
     if (!locked && event->button == 1 && event->type == GDK_BUTTON_PRESS) {
+
+        if (!gdl_dock_item_or_child_has_focus (item))
+            gtk_widget_grab_focus (GTK_WIDGET (item));
+            
         /* Set in_drag flag, grab pointer and call begin drag operation. */      
         if (in_handle) {
             item->_priv->start_x = event->x;
@@ -943,6 +1040,7 @@ gdl_dock_item_button_changed (GtkWidget      *widget,
         if (GDL_DOCK_ITEM_IN_DRAG (item)) {
             /* User dropped widget somewhere. */
             gdl_dock_item_drag_end (item, FALSE);
+            gtk_widget_grab_focus (GTK_WIDGET (item));
             event_handled = TRUE;
         }
         else if (GDL_DOCK_ITEM_IN_PREDRAG (item)) {
@@ -1348,6 +1446,8 @@ gdl_dock_item_dock (GdlDockObject    *object,
     gdl_dock_object_thaw (new_parent);
     if (parent)
         gdl_dock_object_thaw (parent);
+
+
 }
 
 static void
@@ -1917,6 +2017,26 @@ gdl_dock_item_preferred_size (GdlDockItem    *item,
 }
 
 
+gboolean
+gdl_dock_item_or_child_has_focus (GdlDockItem *item)
+{
+    GtkWidget *item_child;
+    gboolean item_or_child_has_focus;
+
+    g_return_val_if_fail (GDL_IS_DOCK_ITEM (item), FALSE);
+
+    for (item_child = GTK_CONTAINER (item)->focus_child;
+         item_child && GTK_IS_CONTAINER (item_child) && GTK_CONTAINER (item_child)->focus_child;
+         item_child = GTK_CONTAINER (item_child)->focus_child) ;
+    
+    item_or_child_has_focus =
+        (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (item)) || 
+         (GTK_IS_WIDGET (item_child) && GTK_WIDGET_HAS_FOCUS (item_child)));
+    
+    return item_or_child_has_focus;
+}
+
+
 /* ----- gtk orientation type exporter/importer ----- */
 
 static void 
index 6eec28aeba55a76351c9dd6737a29f06219a4bab..17484ad04f2b0188115bced3c70328ea49c3308f 100644 (file)
@@ -93,15 +93,17 @@ struct _GdlDockItemClass {
     gboolean            has_grip;
     
     /* virtuals */
-    void     (* dock_drag_begin)  (GdlDockItem    *item);
-    void     (* dock_drag_motion) (GdlDockItem    *item,
-                                   gint            x,
-                                   gint            y);
-    void     (* dock_drag_end)    (GdlDockItem    *item,
-                                   gboolean        cancelled);
+    void     (* dock_drag_begin)  (GdlDockItem      *item);
+    void     (* dock_drag_motion) (GdlDockItem      *item,
+                                   gint              x,
+                                   gint              y);
+    void     (* dock_drag_end)    (GdlDockItem      *item,
+                                   gboolean          cancelled);
+    void     (* move_focus_child) (GdlDockItem      *item,
+                                   GtkDirectionType  direction);
                                    
-    void     (* set_orientation)  (GdlDockItem    *item,
-                                   GtkOrientation  orientation);
+    void     (* set_orientation)  (GdlDockItem      *item,
+                                   GtkOrientation    orientation);
 };
 
 /* additional macros */
@@ -186,6 +188,8 @@ void        gdl_dock_item_set_default_position (GdlDockItem      *item,
 void        gdl_dock_item_preferred_size       (GdlDockItem      *item,
                                                 GtkRequisition   *req);
 
+gboolean    gdl_dock_item_or_child_has_focus  (GdlDockItem      *item);
+
 G_END_DECLS
 
 #endif
index 06a4e759692d72530c5af97c0af57e8c53a313a1..764f6fed07276a4d00a2942c3eefe081a77d0361 100644 (file)
@@ -1,4 +1,3 @@
-#include "libgdlmarshal.h"
 
 #include       <glib-object.h>
 
@@ -50,7 +49,9 @@
 
 /* VOID:VOID (./libgdlmarshal.list:1) */
 
-/* VOID:INT,INT (./libgdlmarshal.list:2) */
+/* VOID:ENUM (./libgdlmarshal.list:2) */
+
+/* VOID:INT,INT (./libgdlmarshal.list:3) */
 void
 gdl_marshal_VOID__INT_INT (GClosure     *closure,
                            GValue       *return_value,
@@ -87,7 +88,7 @@ gdl_marshal_VOID__INT_INT (GClosure     *closure,
             data2);
 }
 
-/* VOID:UINT,UINT (./libgdlmarshal.list:3) */
+/* VOID:UINT,UINT (./libgdlmarshal.list:4) */
 void
 gdl_marshal_VOID__UINT_UINT (GClosure     *closure,
                              GValue       *return_value,
@@ -124,9 +125,9 @@ gdl_marshal_VOID__UINT_UINT (GClosure     *closure,
             data2);
 }
 
-/* VOID:BOOLEAN (./libgdlmarshal.list:4) */
+/* VOID:BOOLEAN (./libgdlmarshal.list:5) */
 
-/* VOID:OBJECT,ENUM,BOXED (./libgdlmarshal.list:5) */
+/* VOID:OBJECT,ENUM,BOXED (./libgdlmarshal.list:6) */
 void
 gdl_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
                                      GValue       *return_value,
@@ -165,5 +166,5 @@ gdl_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
             data2);
 }
 
-/* VOID:BOXED (./libgdlmarshal.list:6) */
+/* VOID:BOXED (./libgdlmarshal.list:7) */
 
index 3e0116e1a7f37e1dc07e59be2851a26b9cb13911..2d6bc800fd8bea019bd7bd3782defd3cb01d4942 100644 (file)
@@ -9,7 +9,10 @@ G_BEGIN_DECLS
 /* VOID:VOID (./libgdlmarshal.list:1) */
 #define gdl_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
 
-/* VOID:INT,INT (./libgdlmarshal.list:2) */
+/* VOID:ENUM (./libgdlmarshal.list:2) */
+#define gdl_marshal_VOID__ENUM g_cclosure_marshal_VOID__ENUM
+
+/* VOID:INT,INT (./libgdlmarshal.list:3) */
 extern void gdl_marshal_VOID__INT_INT (GClosure     *closure,
                                        GValue       *return_value,
                                        guint         n_param_values,
@@ -17,7 +20,7 @@ extern void gdl_marshal_VOID__INT_INT (GClosure     *closure,
                                        gpointer      invocation_hint,
                                        gpointer      marshal_data);
 
-/* VOID:UINT,UINT (./libgdlmarshal.list:3) */
+/* VOID:UINT,UINT (./libgdlmarshal.list:4) */
 extern void gdl_marshal_VOID__UINT_UINT (GClosure     *closure,
                                          GValue       *return_value,
                                          guint         n_param_values,
@@ -25,10 +28,10 @@ extern void gdl_marshal_VOID__UINT_UINT (GClosure     *closure,
                                          gpointer      invocation_hint,
                                          gpointer      marshal_data);
 
-/* VOID:BOOLEAN (./libgdlmarshal.list:4) */
+/* VOID:BOOLEAN (./libgdlmarshal.list:5) */
 #define gdl_marshal_VOID__BOOLEAN      g_cclosure_marshal_VOID__BOOLEAN
 
-/* VOID:OBJECT,ENUM,BOXED (./libgdlmarshal.list:5) */
+/* VOID:OBJECT,ENUM,BOXED (./libgdlmarshal.list:6) */
 extern void gdl_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
                                                  GValue       *return_value,
                                                  guint         n_param_values,
@@ -36,7 +39,7 @@ extern void gdl_marshal_VOID__OBJECT_ENUM_BOXED (GClosure     *closure,
                                                  gpointer      invocation_hint,
                                                  gpointer      marshal_data);
 
-/* VOID:BOXED (./libgdlmarshal.list:6) */
+/* VOID:BOXED (./libgdlmarshal.list:7) */
 #define gdl_marshal_VOID__BOXED        g_cclosure_marshal_VOID__BOXED
 
 G_END_DECLS
index f3200d6d2429e168901dcdc90122e05038040dce..750989abcc5340aa22b1b061a48e8195214280b9 100644 (file)
@@ -1,4 +1,5 @@
 VOID:VOID
+VOID:ENUM
 VOID:INT,INT
 VOID:UINT,UINT
 VOID:BOOLEAN
index d615de1ffacfc35753fd2cfd161f162deb1cb58a..372fe5d9d99acd7de286b7192c77f94a396eb951 100644 (file)
@@ -291,10 +291,19 @@ DockItem::present()
 void
 DockItem::grab_focus()
 {
-    if (GTK_WIDGET_REALIZED (_gdl_dock_item))
+    if (GTK_WIDGET_REALIZED (_gdl_dock_item)) {
+
+        // make sure the window we're in is present
+        Gtk::Widget *toplevel = getWidget().get_toplevel();
+        if (Gtk::Window *window = dynamic_cast<Gtk::Window *>(toplevel)) {
+            window->present();
+        }
+
         gtk_widget_grab_focus (_gdl_dock_item);
-    else
+
+    } else {
         _grab_focus_on_realize = true;
+    }
 }