Browse Source

Add directional focus option, and focus next window on session close.

Signed-off-by: Bradley Smith <brad@brad-smith.co.uk>
Bradley Smith 11 years ago
parent
commit
84dcff873c
6 changed files with 126 additions and 32 deletions
  1. 11 0
      mssh.schemas
  2. 38 20
      src/mssh-gconf.c
  3. 3 0
      src/mssh-gconf.h
  4. 24 0
      src/mssh-pref.c
  5. 48 12
      src/mssh-window.c
  6. 2 0
      src/mssh-window.h

+ 11 - 0
mssh.schemas

@@ -78,6 +78,17 @@
             </locale>
         </schema>
         <schema>
+            <key>/schemas/apps/mssh/dir_focus</key>
+            <applyto>/apps/mssh/dir_focus</applyto>
+            <owner>mssh</owner>
+            <type>bool</type>
+            <default>true</default>
+            <locale name="C">
+                <short>Use directional focus</short>
+                <long>Uses directional focus rather than linear focus</long>
+            </locale>
+        </schema>
+        <schema>
             <key>/schemas/apps/mssh/modifier</key>
             <applyto>/apps/mssh/modifier</applyto>
             <owner>mssh</owner>

+ 38 - 20
src/mssh-gconf.c

@@ -161,6 +161,18 @@ void mssh_gconf_notify_quit_all_ended(GConfClient *client, guint cnxn_id,
     window->exit_on_all_closed = gconf_value_get_bool(value);
 }
 
+void mssh_gconf_notify_dir_focus(GConfClient *client, guint cnxn_id,
+    GConfEntry *entry, gpointer data)
+{
+    GConfValue *value;
+
+    MSSHWindow *window = MSSH_WINDOW(data);
+
+    value = gconf_entry_get_value(entry);
+
+    window->dir_focus = gconf_value_get_bool(value);
+}
+
 void mssh_gconf_notify_modifier(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data)
 {
@@ -170,27 +182,33 @@ void mssh_gconf_notify_modifier(GConfClient *client, guint cnxn_id,
 
     value = gconf_entry_get_value(entry);
 
-    gtk_accel_group_disconnect_key(window->accel, GDK_Up,
-        window->modifier);
-    gtk_accel_group_disconnect_key(window->accel, GDK_Down,
-        window->modifier);
-    gtk_accel_group_disconnect_key(window->accel, GDK_Left,
-        window->modifier);
-    gtk_accel_group_disconnect_key(window->accel, GDK_Right,
-        window->modifier);
+    if(window->accel)
+    {
+        gtk_accel_group_disconnect_key(window->accel, GDK_Up,
+            window->modifier);
+        gtk_accel_group_disconnect_key(window->accel, GDK_Down,
+            window->modifier);
+        gtk_accel_group_disconnect_key(window->accel, GDK_Left,
+            window->modifier);
+        gtk_accel_group_disconnect_key(window->accel, GDK_Right,
+            window->modifier);
+    }
 
     window->modifier = gconf_value_get_int(value);
 
-    gtk_accel_group_connect(window->accel, GDK_Up, window->modifier,
-        GTK_ACCEL_VISIBLE, g_cclosure_new(
-        G_CALLBACK(mssh_window_focus), window, NULL));
-    gtk_accel_group_connect(window->accel, GDK_Down, window->modifier,
-        GTK_ACCEL_VISIBLE, g_cclosure_new(
-        G_CALLBACK(mssh_window_focus), window, NULL));
-    gtk_accel_group_connect(window->accel, GDK_Left, window->modifier,
-        GTK_ACCEL_VISIBLE, g_cclosure_new(
-        G_CALLBACK(mssh_window_focus), window, NULL));
-    gtk_accel_group_connect(window->accel, GDK_Right, window->modifier,
-        GTK_ACCEL_VISIBLE, g_cclosure_new(
-        G_CALLBACK(mssh_window_focus), window, NULL));
+    if(window->accel)
+    {
+        gtk_accel_group_connect(window->accel, GDK_Up, window->modifier,
+            GTK_ACCEL_VISIBLE, g_cclosure_new(
+            G_CALLBACK(mssh_window_focus), window, NULL));
+        gtk_accel_group_connect(window->accel, GDK_Down, window->modifier,
+            GTK_ACCEL_VISIBLE, g_cclosure_new(
+            G_CALLBACK(mssh_window_focus), window, NULL));
+        gtk_accel_group_connect(window->accel, GDK_Left, window->modifier,
+            GTK_ACCEL_VISIBLE, g_cclosure_new(
+            G_CALLBACK(mssh_window_focus), window, NULL));
+        gtk_accel_group_connect(window->accel, GDK_Right, window->modifier,
+            GTK_ACCEL_VISIBLE, g_cclosure_new(
+            G_CALLBACK(mssh_window_focus), window, NULL));
+    }
 }

+ 3 - 0
src/mssh-gconf.h

@@ -12,6 +12,7 @@
 #define MSSH_GCONF_KEY_CLOSE_ENDED      MSSH_GCONF_PATH"/close_ended"
 #define MSSH_GCONF_KEY_QUIT_ALL_ENDED   MSSH_GCONF_PATH"/quit_all_ended"
 #define MSSH_GCONF_KEY_MODIFIER         MSSH_GCONF_PATH"/modifier"
+#define MSSH_GCONF_KEY_DIR_FOCUS        MSSH_GCONF_PATH"/dir_focus"
 
 void mssh_gconf_notify_font(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data);
@@ -29,5 +30,7 @@ void mssh_gconf_notify_quit_all_ended(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data);
 void mssh_gconf_notify_modifier(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data);
+void mssh_gconf_notify_dir_focus(GConfClient *client, guint cnxn_id,
+    GConfEntry *entry, gpointer data);
 
 #endif

+ 24 - 0
src/mssh-pref.c

@@ -112,6 +112,18 @@ static void mssh_pref_exit_check(GtkWidget *widget, gpointer data)
         NULL);
 }
 
+static void mssh_pref_dir_focus_check(GtkWidget *widget, gpointer data)
+{
+    GConfClient *client;
+    gboolean focus;
+
+    client = gconf_client_get_default();
+
+    focus = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+
+    gconf_client_set_bool(client, MSSH_GCONF_KEY_DIR_FOCUS, focus, NULL);
+}
+
 static void mssh_pref_modifier_check(GtkWidget *widget, gpointer data)
 {
     GConfClient *client;
@@ -185,6 +197,9 @@ static void mssh_pref_init(MSSHPref* pref)
     GtkWidget *close_hbox = gtk_hbox_new(FALSE, 0);
     GtkWidget *close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
 
+    GtkWidget *dir_focus_check = gtk_check_button_new_with_label(
+        "Use directional focus");
+
     pref->ctrl = mod_ctrl_check;
     pref->shift = mod_shift_check;
     pref->alt = mod_alt_check;
@@ -209,6 +224,7 @@ static void mssh_pref_init(MSSHPref* pref)
 
     gtk_box_pack_start(GTK_BOX(content), exit_check, FALSE, TRUE, 0);
     gtk_box_pack_start(GTK_BOX(content), close_check, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(content), dir_focus_check, FALSE, TRUE, 0);
 
     gtk_box_pack_start(GTK_BOX(timeout_hbox), timeout_label1, FALSE,
         TRUE, 0);
@@ -260,6 +276,8 @@ static void mssh_pref_init(MSSHPref* pref)
         G_CALLBACK(mssh_pref_close_check), NULL);
     g_signal_connect(G_OBJECT(exit_check), "toggled",
         G_CALLBACK(mssh_pref_exit_check), NULL);
+     g_signal_connect(G_OBJECT(dir_focus_check), "toggled",
+        G_CALLBACK(mssh_pref_dir_focus_check), NULL);
     g_signal_connect(G_OBJECT(mod_ctrl_check), "toggled",
         G_CALLBACK(mssh_pref_modifier_check), pref);
     g_signal_connect(G_OBJECT(mod_alt_check), "toggled",
@@ -319,6 +337,12 @@ static void mssh_pref_init(MSSHPref* pref)
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(exit_check),
         gconf_value_get_bool(value));
 
+    entry = gconf_client_get_entry(client, MSSH_GCONF_KEY_DIR_FOCUS,
+            NULL, TRUE, NULL);
+    value = gconf_entry_get_value(entry);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dir_focus_check),
+        gconf_value_get_bool(value));
+
     entry = gconf_client_get_entry(client, MSSH_GCONF_KEY_MODIFIER,
             NULL, TRUE, NULL);
     value = gconf_entry_get_value(entry);

+ 48 - 12
src/mssh-window.c

@@ -136,35 +136,46 @@ gboolean mssh_window_focus(GtkWidget *widget, GObject *acceleratable,
         }
     }
 
-    if(focus == window->global_entry && keyval == GDK_Down)
+    if(focus == window->global_entry && keyval == GDK_Down &&
+        window->dir_focus)
         idx = 0;
-    else if(idx == -1)
-        return FALSE;
+    else if(idx == -1 && window->dir_focus)
+        return TRUE;
     else
     {
         switch(keyval)
         {
         case GDK_Up:
-            idx = idx - cols;
+            if(window->dir_focus)
+                idx = idx - cols;
             break;
         case GDK_Down:
-            if((idx + cols >= len) && (idx < len -
-                (len % cols) ? (len % cols) : cols))
-                idx = len - 1;
-            else
-                idx = idx + cols;
+            if(window->dir_focus)
+            {
+                if((idx + cols >= len) && (idx < len -
+                    (len % cols) ? (len % cols) : cols))
+                    idx = len - 1;
+                else
+                    idx = idx + cols;
+            }
             break;
         case GDK_Left:
-            if(idx % cols != 0)
+            if(idx % cols != 0 || !window->dir_focus)
                 idx = idx - 1;
             break;
         case GDK_Right:
-            if(idx % cols != cols - 1)
+            if(idx % cols != cols - 1 || !window->dir_focus)
                 idx = idx + 1;
             break;
         }
     }
 
+    if(idx >= len && !window->dir_focus)
+        focus = window->global_entry;
+
+    if(idx < -1 && !window->dir_focus)
+        idx = len - 1;
+
     if(idx < 0)
         focus = window->global_entry;
     else if(idx < len)
@@ -194,6 +205,8 @@ static gboolean mssh_window_session_close(gpointer data)
         }
     }
 
+    data_pair->window->last_closed = idx;
+
     if(idx == -1)
     {
         fprintf(stderr,
@@ -267,7 +280,23 @@ void mssh_window_relayout(MSSHWindow *window)
     focus = gtk_window_get_focus(GTK_WINDOW(window));
 
     if(!focus)
-        focus = window->global_entry;
+    {
+        if(window->last_closed < 0)
+            window->last_closed = 0;
+
+        if(len == 0)
+            focus = window->global_entry;
+        else if(window->last_closed < len)
+        {
+            focus = GTK_WIDGET(g_array_index(window->terminals,
+                MSSHTerminal*, window->last_closed));
+        }
+        else
+        {
+            focus = GTK_WIDGET(g_array_index(window->terminals,
+                MSSHTerminal*, 0));
+        }
+    }
 
     for(i = 0; i < len; i++)
     {
@@ -360,10 +389,14 @@ static void mssh_window_init(MSSHWindow* window)
 
     GtkAccelGroup *accel = gtk_accel_group_new();
 
+    window->accel = NULL;
+
     window->server_menu = gtk_menu_new();
 
     window->global_entry = entry;
 
+    window->last_closed = -1;
+
     window->terminals = g_array_new(FALSE, TRUE, sizeof(MSSHTerminal*));
 
     gtk_menu_item_set_submenu(GTK_MENU_ITEM(file_item), file_menu);
@@ -423,6 +456,8 @@ static void mssh_window_init(MSSHWindow* window)
         mssh_gconf_notify_close_ended, window, NULL, NULL);
     gconf_client_notify_add(client, MSSH_GCONF_KEY_QUIT_ALL_ENDED,
         mssh_gconf_notify_quit_all_ended, window, NULL, NULL);
+    gconf_client_notify_add(client, MSSH_GCONF_KEY_DIR_FOCUS,
+        mssh_gconf_notify_dir_focus, window, NULL, NULL);
     gconf_client_notify_add(client, MSSH_GCONF_KEY_MODIFIER,
         mssh_gconf_notify_modifier, window, NULL, NULL);
 
@@ -430,6 +465,7 @@ static void mssh_window_init(MSSHWindow* window)
     gconf_client_notify(client, MSSH_GCONF_KEY_TIMEOUT);
     gconf_client_notify(client, MSSH_GCONF_KEY_CLOSE_ENDED);
     gconf_client_notify(client, MSSH_GCONF_KEY_QUIT_ALL_ENDED);
+    gconf_client_notify(client, MSSH_GCONF_KEY_DIR_FOCUS);
     gconf_client_notify(client, MSSH_GCONF_KEY_MODIFIER);
 
     gtk_accel_group_connect(accel, GDK_Up, window->modifier,

+ 2 - 0
src/mssh-window.h

@@ -33,6 +33,8 @@ typedef struct
     gboolean close_ended_sessions;
     gboolean exit_on_all_closed;
     gint modifier;
+    gint dir_focus;
+    gint last_closed;
 } MSSHWindow;
 
 typedef struct