Browse Source

Add directional focus.

Signed-off-by: Bradley Smith <[email protected]>
Bradley Smith 14 years ago
parent
commit
a83ce3818f
7 changed files with 176 additions and 1 deletions
  1. 11 1
      mssh.schemas
  2. 12 0
      src/mssh-gconf.c
  3. 3 0
      src/mssh-gconf.h
  4. 59 0
      src/mssh-pref.c
  5. 4 0
      src/mssh-pref.h
  6. 86 0
      src/mssh-window.c
  7. 1 0
      src/mssh-window.h

+ 11 - 1
mssh.schemas

@@ -77,6 +77,16 @@
                 <long>Quit MSSH when all ssh sessions have ended</long>
             </locale>
         </schema>
-
+        <schema>
+            <key>/schemas/apps/mssh/modifier</key>
+            <applyto>/apps/mssh/modifier</applyto>
+            <owner>mssh</owner>
+            <type>int</type>
+            <default>8</default>
+            <locale name="C">
+                <short>Shortcut modifier</short>
+                <long>Modifier used in focus shortcuts</long>
+            </locale>
+        </schema>
     </schemalist>
 </gconfschemafile>

+ 12 - 0
src/mssh-gconf.c

@@ -159,3 +159,15 @@ 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_modifier(GConfClient *client, guint cnxn_id,
+    GConfEntry *entry, gpointer data)
+{
+    GConfValue *value;
+
+    MSSHWindow *window = MSSH_WINDOW(data);
+
+    value = gconf_entry_get_value(entry);
+
+    window->modifier = gconf_value_get_int(value);
+}

+ 3 - 0
src/mssh-gconf.h

@@ -11,6 +11,7 @@
 #define MSSH_GCONF_KEY_TIMEOUT          MSSH_GCONF_PATH"/timeout"
 #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"
 
 void mssh_gconf_notify_font(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data);
@@ -26,5 +27,7 @@ void mssh_gconf_notify_close_ended(GConfClient *client, guint cnxn_id,
     GConfEntry *entry, gpointer data);
 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);
 
 #endif

+ 59 - 0
src/mssh-pref.c

@@ -112,6 +112,26 @@ static void mssh_pref_exit_check(GtkWidget *widget, gpointer data)
         NULL);
 }
 
+static void mssh_pref_modifier_check(GtkWidget *widget, gpointer data)
+{
+    GConfClient *client;
+    gboolean ctrl, alt, shift, super;
+    gint val;
+
+    MSSHPref * pref = MSSH_PREF(data);
+
+    client = gconf_client_get_default();
+
+    ctrl = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->ctrl));
+    shift = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->shift));
+    alt = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->alt));
+    super = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pref->super));
+
+    val = (shift << 0) | (ctrl << 2) | (alt << 3) | (super << 26);
+
+    gconf_client_set_int(client, MSSH_GCONF_KEY_MODIFIER, val, NULL);
+}
+
 static void mssh_pref_init(MSSHPref* pref)
 {
     GConfClient *client;
@@ -155,9 +175,21 @@ static void mssh_pref_init(MSSHPref* pref)
     GtkWidget *columns_select = gtk_spin_button_new(
         GTK_ADJUSTMENT(columns_adj), 1, 0);
 
+    GtkWidget *mod_hbox = gtk_hbox_new(FALSE, 10);
+    GtkWidget *mod_label = gtk_label_new("Modifier:");
+    GtkWidget *mod_ctrl_check = gtk_check_button_new_with_label("Ctrl");
+    GtkWidget *mod_alt_check = gtk_check_button_new_with_label("Alt");
+    GtkWidget *mod_shift_check = gtk_check_button_new_with_label("Shift");
+    GtkWidget *mod_super_check = gtk_check_button_new_with_label("Super");
+
     GtkWidget *close_hbox = gtk_hbox_new(FALSE, 0);
     GtkWidget *close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
 
+    pref->ctrl = mod_ctrl_check;
+    pref->shift = mod_shift_check;
+    pref->alt = mod_alt_check;
+    pref->super = mod_super_check;
+
     gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), content, NULL);
 
@@ -192,6 +224,13 @@ static void mssh_pref_init(MSSHPref* pref)
         TRUE, 0);
     gtk_box_pack_start(GTK_BOX(content), columns_hbox, FALSE, TRUE, 0);
 
+    gtk_box_pack_start(GTK_BOX(mod_hbox), mod_label, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(mod_hbox), mod_ctrl_check, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(mod_hbox), mod_alt_check, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(mod_hbox), mod_shift_check, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(mod_hbox), mod_super_check, FALSE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(content), mod_hbox, FALSE, TRUE, 0);
+
     gtk_box_pack_end(GTK_BOX(close_hbox), close_button, FALSE, TRUE, 0);
 
     gtk_box_pack_start(GTK_BOX(frame), notebook, TRUE, TRUE, 0);
@@ -221,6 +260,14 @@ 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(mod_ctrl_check), "toggled",
+        G_CALLBACK(mssh_pref_modifier_check), pref);
+    g_signal_connect(G_OBJECT(mod_alt_check), "toggled",
+        G_CALLBACK(mssh_pref_modifier_check), pref);
+    g_signal_connect(G_OBJECT(mod_shift_check), "toggled",
+        G_CALLBACK(mssh_pref_modifier_check), pref);
+    g_signal_connect(G_OBJECT(mod_super_check), "toggled",
+        G_CALLBACK(mssh_pref_modifier_check), pref);
 
     client = gconf_client_get_default();
 
@@ -271,6 +318,18 @@ static void mssh_pref_init(MSSHPref* pref)
     value = gconf_entry_get_value(entry);
     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(exit_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);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mod_ctrl_check),
+        (gconf_value_get_int(value) & GDK_CONTROL_MASK) ? 1 : 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mod_shift_check),
+        (gconf_value_get_int(value) & GDK_SHIFT_MASK) ? 1 : 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mod_alt_check),
+        (gconf_value_get_int(value) & GDK_MOD1_MASK) ? 1 : 0);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mod_super_check),
+        (gconf_value_get_int(value) & GDK_SUPER_MASK) ? 1 : 0);
 }
 
 static void mssh_pref_class_init(MSSHPrefClass *klass)

+ 4 - 0
src/mssh-pref.h

@@ -18,6 +18,10 @@ G_BEGIN_DECLS
 typedef struct
 {
     GtkWindow widget;
+    GtkWidget *ctrl;
+    GtkWidget *alt;
+    GtkWidget *shift;
+    GtkWidget *super;
 } MSSHPref;
 
 typedef struct

+ 86 - 0
src/mssh-window.c

@@ -113,6 +113,72 @@ static gboolean mssh_window_entry_focused(GtkWidget *widget,
     return FALSE;
 }
 
+static gboolean mssh_window_focus(GtkWidget *widget,
+    GObject *acceleratable, guint keyval, GdkModifierType modifier,
+    gpointer data)
+{
+    MSSHWindow *window = MSSH_WINDOW(data);
+    GtkWidget *focus;
+
+    int i, idx = -1, len = window->terminals->len;
+    int wcols = window->columns_override ? window->columns_override :
+        window->columns;
+    int cols = (len < wcols) ? len : wcols;
+
+    focus = gtk_window_get_focus(GTK_WINDOW(window));
+
+    for(i = 0; i < len; i++)
+    {
+        if(focus == GTK_WIDGET(g_array_index(window->terminals,
+            MSSHTerminal*, i)))
+        {
+            idx = i;
+            break;
+        }
+    }
+
+    if(focus == window->global_entry && keyval == GDK_Down)
+        idx = 0;
+    else if(idx == -1)
+        return FALSE;
+    else
+    {
+        switch(keyval)
+        {
+        case GDK_Up:
+            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;
+            break;
+        case GDK_Left:
+            if(idx % cols != 0)
+                idx = idx - 1;
+            break;
+        case GDK_Right:
+            if(idx % cols != cols - 1)
+                idx = idx + 1;
+            break;
+        }
+    }
+
+    if(idx < 0)
+        focus = window->global_entry;
+    else if(idx < len)
+    {
+        focus = GTK_WIDGET(g_array_index(window->terminals,
+            MSSHTerminal*, idx));
+    }
+
+    gtk_window_set_focus(GTK_WINDOW(window), focus);
+
+    return TRUE;
+}
+
 static gboolean mssh_window_session_close(gpointer data)
 {
     int i, idx = -1;
@@ -293,6 +359,8 @@ static void mssh_window_init(MSSHWindow* window)
     GtkWidget *edit_pref = gtk_image_menu_item_new_from_stock(
         GTK_STOCK_PREFERENCES, NULL);
 
+    GtkAccelGroup *accel = gtk_accel_group_new();
+
     window->server_menu = gtk_menu_new();
 
     window->global_entry = entry;
@@ -356,11 +424,29 @@ 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_MODIFIER,
+        mssh_gconf_notify_modifier, window, NULL, NULL);
 
     gconf_client_notify(client, MSSH_GCONF_KEY_COLUMNS);
     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_MODIFIER);
+
+    gtk_accel_group_connect(accel, GDK_Up, window->modifier,
+        GTK_ACCEL_VISIBLE, g_cclosure_new(
+        G_CALLBACK(mssh_window_focus), window, NULL));
+    gtk_accel_group_connect(accel, GDK_Down, window->modifier,
+        GTK_ACCEL_VISIBLE, g_cclosure_new(
+        G_CALLBACK(mssh_window_focus), window, NULL));
+    gtk_accel_group_connect(accel, GDK_Left, window->modifier,
+        GTK_ACCEL_VISIBLE, g_cclosure_new(
+        G_CALLBACK(mssh_window_focus), window, NULL));
+    gtk_accel_group_connect(accel, GDK_Right, window->modifier,
+        GTK_ACCEL_VISIBLE, g_cclosure_new(
+        G_CALLBACK(mssh_window_focus), window, NULL));
+
+    gtk_window_add_accel_group(GTK_WINDOW(window), accel);
 }
 
 void mssh_window_start_session(MSSHWindow* window, char **env,

+ 1 - 0
src/mssh-window.h

@@ -31,6 +31,7 @@ typedef struct
     int timeout;
     gboolean close_ended_sessions;
     gboolean exit_on_all_closed;
+    gint modifier;
 } MSSHWindow;
 
 typedef struct