gnome-commander r1677 - in trunk: . po src



Author: epiotr
Date: Mon Mar 31 22:42:16 2008
New Revision: 1677
URL: http://svn.gnome.org/viewvc/gnome-commander?rev=1677&view=rev

Log:
Added libegg cell renderer and accelerators

Added:
   trunk/src/eggaccelerators.cc
   trunk/src/eggaccelerators.h
   trunk/src/eggcellrendererkeys.cc
   trunk/src/eggcellrendererkeys.h
Modified:
   trunk/ChangeLog
   trunk/po/POTFILES.in
   trunk/src/Makefile.am

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Mon Mar 31 22:42:16 2008
@@ -8,6 +8,7 @@
 plugins/fileroller/file-roller-plugin.c
 plugins/test/test-plugin.c
 src/dirlist.cc
+src/eggcellrendererkeys.cc
 src/gnome-cmd-about-plugin.cc
 src/gnome-cmd-advrename-dialog.cc
 src/gnome-cmd-bookmark-dialog.cc

Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am	(original)
+++ trunk/src/Makefile.am	Mon Mar 31 22:42:16 2008
@@ -17,6 +17,8 @@
 	cap.cc cap.h \
 	dict.h \
 	dirlist.h dirlist.cc \
+	eggaccelerators.h eggaccelerators.cc \
+	eggcellrendererkeys.h eggcellrendererkeys.cc \
 	filter.h filter.cc \
 	gnome-cmd-about-plugin.h gnome-cmd-about-plugin.cc \
 	gnome-cmd-advrename-dialog.h gnome-cmd-advrename-dialog.cc \

Added: trunk/src/eggaccelerators.cc
==============================================================================
--- (empty file)
+++ trunk/src/eggaccelerators.cc	Mon Mar 31 22:42:16 2008
@@ -0,0 +1,610 @@
+/*
+    GNOME Commander - A GNOME based file manager
+    Copyright (C) 2001-2006 Marcus Bjurman
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* eggaccelerators.c
+ * Copyright (C) 2002  Red Hat, Inc.; Copyright 1998, 2001 Tim Janik
+ * Developed by Havoc Pennington, Tim Janik
+ *
+ * This file is part of gnome-terminal.
+ *
+ * Gnome-terminal is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Gnome-terminal 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "eggaccelerators.h"
+
+#include <string.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+
+enum
+{
+    EGG_MODMAP_ENTRY_SHIFT   = 0,
+    EGG_MODMAP_ENTRY_LOCK    = 1,
+    EGG_MODMAP_ENTRY_CONTROL = 2,
+    EGG_MODMAP_ENTRY_MOD1    = 3,
+    EGG_MODMAP_ENTRY_MOD2    = 4,
+    EGG_MODMAP_ENTRY_MOD3    = 5,
+    EGG_MODMAP_ENTRY_MOD4    = 6,
+    EGG_MODMAP_ENTRY_MOD5    = 7,
+    EGG_MODMAP_ENTRY_LAST    = 8
+};
+
+#define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x))
+
+typedef struct
+{
+  EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST];
+
+} EggModmap;
+
+
+const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap);
+
+
+inline gboolean is_alt (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'a' || string[1] == 'A') &&
+          (string[2] == 'l' || string[2] == 'L') &&
+          (string[3] == 't' || string[3] == 'T') &&
+          (string[4] == '>'));
+}
+
+
+inline gboolean is_ctl (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'c' || string[1] == 'C') &&
+          (string[2] == 't' || string[2] == 'T') &&
+          (string[3] == 'l' || string[3] == 'L') &&
+          (string[4] == '>'));
+}
+
+
+inline gboolean is_modx (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'm' || string[1] == 'M') &&
+          (string[2] == 'o' || string[2] == 'O') &&
+          (string[3] == 'd' || string[3] == 'D') &&
+          (string[4] >= '1' && string[4] <= '5') &&
+          (string[5] == '>'));
+}
+
+
+inline gboolean is_ctrl (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'c' || string[1] == 'C') &&
+          (string[2] == 't' || string[2] == 'T') &&
+          (string[3] == 'r' || string[3] == 'R') &&
+          (string[4] == 'l' || string[4] == 'L') &&
+          (string[5] == '>'));
+}
+
+
+inline gboolean is_shft (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 's' || string[1] == 'S') &&
+          (string[2] == 'h' || string[2] == 'H') &&
+          (string[3] == 'f' || string[3] == 'F') &&
+          (string[4] == 't' || string[4] == 'T') &&
+          (string[5] == '>'));
+}
+
+
+inline gboolean is_shift (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 's' || string[1] == 'S') &&
+          (string[2] == 'h' || string[2] == 'H') &&
+          (string[3] == 'i' || string[3] == 'I') &&
+          (string[4] == 'f' || string[4] == 'F') &&
+          (string[5] == 't' || string[5] == 'T') &&
+          (string[6] == '>'));
+}
+
+
+inline gboolean is_control (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'c' || string[1] == 'C') &&
+          (string[2] == 'o' || string[2] == 'O') &&
+          (string[3] == 'n' || string[3] == 'N') &&
+          (string[4] == 't' || string[4] == 'T') &&
+          (string[5] == 'r' || string[5] == 'R') &&
+          (string[6] == 'o' || string[6] == 'O') &&
+          (string[7] == 'l' || string[7] == 'L') &&
+          (string[8] == '>'));
+}
+
+
+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] == '>'));
+}
+
+
+inline gboolean is_meta (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'm' || string[1] == 'M') &&
+          (string[2] == 'e' || string[2] == 'E') &&
+          (string[3] == 't' || string[3] == 'T') &&
+          (string[4] == 'a' || string[4] == 'A') &&
+          (string[5] == '>'));
+}
+
+
+static inline gboolean is_super (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 's' || string[1] == 'S') &&
+          (string[2] == 'u' || string[2] == 'U') &&
+          (string[3] == 'p' || string[3] == 'P') &&
+          (string[4] == 'e' || string[4] == 'E') &&
+          (string[5] == 'r' || string[5] == 'R') &&
+          (string[6] == '>'));
+}
+
+
+inline gboolean is_hyper (const gchar *string)
+{
+  return ((string[0] == '<') &&
+          (string[1] == 'h' || string[1] == 'H') &&
+          (string[2] == 'y' || string[2] == 'Y') &&
+          (string[3] == 'p' || string[3] == 'P') &&
+          (string[4] == 'e' || string[4] == 'E') &&
+          (string[5] == 'r' || string[5] == 'R') &&
+          (string[6] == '>'));
+}
+
+
+/**
+ * egg_accelerator_parse_virtual:
+ * @accelerator:      string representing an accelerator
+ * @accelerator_key:  return location for accelerator keyval
+ * @accelerator_mods: return location for accelerator modifier mask
+ *
+ * Parses a string representing a virtual accelerator. The format
+ * looks like "&lt;Control&gt;a" or "&lt;Shift&gt;&lt;Alt&gt;F1" or
+ * "&lt;Release&gt;z" (the last one is for key release).  The parser
+ * is fairly liberal and allows lower or upper case, and also
+ * abbreviations such as "&lt;Ctl&gt;" and "&lt;Ctrl&gt;".
+ *
+ * If the parse fails, @accelerator_key and @accelerator_mods will
+ * be set to 0 (zero) and %FALSE will be returned. If the string contains
+ * only modifiers, @accelerator_key will be set to 0 but %TRUE will be
+ * returned.
+ *
+ * The virtual vs. concrete accelerator distinction is a relic of
+ * how the X Window System works; there are modifiers Mod2-Mod5 that
+ * can represent various keyboard keys (numlock, meta, hyper, etc.),
+ * the virtual modifier represents the keyboard key, the concrete
+ * modifier the actual Mod2-Mod5 bits in the key press event.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean egg_accelerator_parse_virtual (const gchar *accelerator, guint *accelerator_key, EggVirtualModifierType *accelerator_mods)
+{
+    g_return_val_if_fail (accelerator != NULL, FALSE);
+
+    if (accelerator_key)
+        *accelerator_key = 0;
+
+    if (accelerator_mods)
+        *accelerator_mods = (EggVirtualModifierType) 0;
+
+    gboolean bad_keyval = FALSE;
+
+    guint keyval = 0;
+    guint mods = 0;
+    gint len = strlen (accelerator);
+
+    while (len)
+    {
+        if (*accelerator == '<')
+        {
+          if (len >= 9 && is_release (accelerator))
+            {
+              accelerator += 9;
+              len -= 9;
+              mods |= EGG_VIRTUAL_RELEASE_MASK;
+            }
+          else if (len >= 9 && is_control (accelerator))
+            {
+              accelerator += 9;
+              len -= 9;
+              mods |= EGG_VIRTUAL_CONTROL_MASK;
+            }
+          else if (len >= 7 && is_shift (accelerator))
+            {
+              accelerator += 7;
+              len -= 7;
+              mods |= EGG_VIRTUAL_SHIFT_MASK;
+            }
+          else if (len >= 6 && is_shft (accelerator))
+            {
+              accelerator += 6;
+              len -= 6;
+              mods |= EGG_VIRTUAL_SHIFT_MASK;
+            }
+          else if (len >= 6 && is_ctrl (accelerator))
+            {
+              accelerator += 6;
+              len -= 6;
+              mods |= EGG_VIRTUAL_CONTROL_MASK;
+            }
+          else if (len >= 6 && is_modx (accelerator))
+            {
+              static const guint mod_vals[] = {
+                EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK,
+                EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK
+              };
+
+              len -= 6;
+              accelerator += 4;
+              mods |= mod_vals[*accelerator - '1'];
+              accelerator += 2;
+            }
+          else if (len >= 5 && is_ctl (accelerator))
+            {
+              accelerator += 5;
+              len -= 5;
+              mods |= EGG_VIRTUAL_CONTROL_MASK;
+            }
+          else if (len >= 5 && is_alt (accelerator))
+            {
+              accelerator += 5;
+              len -= 5;
+              mods |= EGG_VIRTUAL_ALT_MASK;
+            }
+          else if (len >= 6 && is_meta (accelerator))
+            {
+              accelerator += 6;
+              len -= 6;
+              mods |= EGG_VIRTUAL_META_MASK;
+            }
+          else if (len >= 7 && is_hyper (accelerator))
+            {
+              accelerator += 7;
+              len -= 7;
+              mods |= EGG_VIRTUAL_HYPER_MASK;
+            }
+          else if (len >= 7 && is_super (accelerator))
+            {
+              accelerator += 7;
+              len -= 7;
+              mods |= EGG_VIRTUAL_SUPER_MASK;
+            }
+          else
+            {
+              gchar last_ch;
+
+              last_ch = *accelerator;
+              while (last_ch && last_ch != '>')
+                {
+                  last_ch = *accelerator;
+                  accelerator += 1;
+                  len -= 1;
+                }
+            }
+        }
+        else
+        {
+          keyval = gdk_keyval_from_name (accelerator);
+
+          if (keyval == 0)
+            bad_keyval = TRUE;
+
+          accelerator += len;
+          len -= len;
+        }
+    }
+
+    if (accelerator_key)
+        *accelerator_key = gdk_keyval_to_lower (keyval);
+
+    if (accelerator_mods)
+        *accelerator_mods = (EggVirtualModifierType) mods;
+
+    return !bad_keyval;
+}
+
+
+/**
+ * egg_virtual_accelerator_name:
+ * @accelerator_key:  accelerator keyval
+ * @accelerator_mods: accelerator modifier mask
+ * @returns:          a newly-allocated accelerator name
+ *
+ * Converts an accelerator keyval and modifier mask
+ * into a string parseable by egg_accelerator_parse_virtual().
+ * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK,
+ * this function returns "&lt;Control&gt;q".
+ *
+ * The caller of this function must free the returned string.
+ */
+gchar *egg_virtual_accelerator_name (guint accelerator_key, EggVirtualModifierType accelerator_mods)
+{
+    static const gchar text_release[] = "<Release>";
+    static const gchar text_shift[] = "<Shift>";
+    static const gchar text_control[] = "<Control>";
+    static const gchar text_mod1[] = "<Alt>";
+    static const gchar text_mod2[] = "<Mod2>";
+    static const gchar text_mod3[] = "<Mod3>";
+    static const gchar text_mod4[] = "<Mod4>";
+    static const gchar text_mod5[] = "<Mod5>";
+    static const gchar text_meta[] = "<Meta>";
+    static const gchar text_super[] = "<Super>";
+    static const gchar text_hyper[] = "<Hyper>";
+
+    (guint &) accelerator_mods &= EGG_VIRTUAL_MODIFIER_MASK;
+
+    gchar *keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
+    if (!keyval_name)
+        keyval_name = "";
+
+    guint l = 0;
+
+    if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK)
+        l += sizeof (text_release)-1;
+    if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK)
+        l += sizeof (text_shift)-1;
+    if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK)
+        l += sizeof (text_control)-1;
+    if (accelerator_mods & EGG_VIRTUAL_ALT_MASK)
+        l += sizeof (text_mod1)-1;
+    if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK)
+        l += sizeof (text_mod2)-1;
+    if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK)
+        l += sizeof (text_mod3)-1;
+    if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK)
+        l += sizeof (text_mod4)-1;
+    if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK)
+        l += sizeof (text_mod5)-1;
+    if (accelerator_mods & EGG_VIRTUAL_META_MASK)
+        l += sizeof (text_meta)-1;
+    if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK)
+        l += sizeof (text_hyper)-1;
+    if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK)
+        l += sizeof (text_super)-1;
+
+    l += strlen (keyval_name);
+
+    gchar *accelerator = g_new (gchar, l+1);
+
+    l = 0;
+    accelerator[l] = 0;
+
+    if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK)
+    {
+      strcpy (accelerator + l, text_release);
+      l += sizeof (text_release) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK)
+    {
+      strcpy (accelerator + l, text_shift);
+      l += sizeof (text_shift) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK)
+    {
+      strcpy (accelerator + l, text_control);
+      l += sizeof (text_control) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_ALT_MASK)
+    {
+      strcpy (accelerator + l, text_mod1);
+      l += sizeof (text_mod1) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK)
+    {
+      strcpy (accelerator + l, text_mod2);
+      l += sizeof (text_mod2) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK)
+    {
+      strcpy (accelerator + l, text_mod3);
+      l += sizeof (text_mod3) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK)
+    {
+      strcpy (accelerator + l, text_mod4);
+      l += sizeof (text_mod4) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK)
+    {
+      strcpy (accelerator + l, text_mod5);
+      l += sizeof (text_mod5) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_META_MASK)
+    {
+      strcpy (accelerator + l, text_meta);
+      l += sizeof (text_meta) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK)
+    {
+      strcpy (accelerator + l, text_hyper);
+      l += sizeof (text_hyper) - 1;
+    }
+    if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK)
+    {
+      strcpy (accelerator + l, text_super);
+      l += sizeof (text_super) - 1;
+    }
+
+    strcpy (accelerator + l, keyval_name);
+
+    return accelerator;
+}
+
+
+void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, EggVirtualModifierType virtual_mods, GdkModifierType *concrete_mods)
+{
+    g_return_if_fail (GDK_IS_KEYMAP (keymap));
+    g_return_if_fail (concrete_mods != NULL);
+
+    guint concrete = 0;
+    const EggModmap *modmap = egg_keymap_get_modmap (keymap);
+
+    // Not so sure about this algorithm
+
+    for (gint i = 0; i<EGG_MODMAP_ENTRY_LAST; ++i)
+        if (modmap->mapping[i] & virtual_mods)
+            concrete |= (1 << i);
+
+    *concrete_mods = (GdkModifierType) concrete;
+}
+
+
+void egg_keymap_virtualize_modifiers (GdkKeymap *keymap, GdkModifierType concrete_mods, EggVirtualModifierType *virtual_mods)
+{
+    g_return_if_fail (GDK_IS_KEYMAP (keymap));
+    g_return_if_fail (virtual_mods != NULL);
+
+    const EggModmap *modmap = egg_keymap_get_modmap (keymap);
+
+    guint virtual_mod = 0;
+
+    // Not so sure about this algorithm
+
+    for (int i=0; i < EGG_MODMAP_ENTRY_LAST; ++i)
+        if ((1 << i) & concrete_mods)
+        {
+            guint cleaned;
+
+            cleaned = modmap->mapping[i] & ~(EGG_VIRTUAL_MOD2_MASK |
+                                             EGG_VIRTUAL_MOD3_MASK |
+                                             EGG_VIRTUAL_MOD4_MASK |
+                                             EGG_VIRTUAL_MOD5_MASK);
+            if (cleaned != 0)
+                virtual_mod |= cleaned;
+            else
+                virtual_mod |= modmap->mapping[i];      // Rather than dropping mod2->mod5 if not bound, go ahead and use the concrete names
+        }
+
+  *virtual_mods = (EggVirtualModifierType) virtual_mod;
+}
+
+
+inline void reload_modmap (GdkKeymap *keymap, EggModmap *modmap)
+{
+    /* FIXME multihead */
+    XModifierKeymap *xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ());
+
+    memset (modmap->mapping, 0, sizeof (modmap->mapping));
+
+    // there are 8 modifiers, and the first 3 are shift, shift lock and control
+    int map_size = 8 * xmodmap->max_keypermod;
+    int i = 3 * xmodmap->max_keypermod;
+
+    while (i < map_size)
+    {
+      /* get the key code at this point in the map,
+       * see if its keysym is one we're interested in
+       */
+      int keycode = xmodmap->modifiermap[i];
+
+      GdkKeymapKey *keys = NULL;
+      guint *keyvals = NULL;
+      int n_entries = 0;
+
+      gdk_keymap_get_entries_for_keycode (keymap, keycode, &keys, &keyvals, &n_entries);
+
+      guint mask = (EggVirtualModifierType) 0;  // EggVirtualModifierType
+
+      for (gint j=0; j<n_entries; ++j)
+        if (keyvals[j] == GDK_Num_Lock)
+            mask |= EGG_VIRTUAL_NUM_LOCK_MASK;
+        else if (keyvals[j] == GDK_Scroll_Lock)
+            mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK;
+        else if (keyvals[j] == GDK_Meta_L || keyvals[j] == GDK_Meta_R)
+            mask |= EGG_VIRTUAL_META_MASK;
+        else if (keyvals[j] == GDK_Hyper_L || keyvals[j] == GDK_Hyper_R)
+            mask |= EGG_VIRTUAL_HYPER_MASK;
+        else if (keyvals[j] == GDK_Super_L || keyvals[j] == GDK_Super_R)
+            mask |= EGG_VIRTUAL_SUPER_MASK;
+        else if (keyvals[j] == GDK_Mode_switch)
+            mask |= EGG_VIRTUAL_MODE_SWITCH_MASK;
+
+        // Mod1Mask is 1 << 3 for example, i.e. the fourth modifier, i / keyspermod is the modifier index
+
+        (guint &) modmap->mapping[i/xmodmap->max_keypermod] |= mask;
+
+        g_free (keyvals);
+        g_free (keys);
+
+        ++i;
+    }
+
+    /* Add in the not-really-virtual fixed entries */
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK;
+    (guint &) modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK;
+
+    XFreeModifiermap (xmodmap);
+}
+
+
+const EggModmap *egg_keymap_get_modmap (GdkKeymap *keymap)
+{
+    //This is all a hack, much simpler when we can just modify GDK directly.
+
+    EggModmap *modmap = (EggModmap *) g_object_get_data (G_OBJECT (keymap), "egg-modmap");
+
+    if (!modmap)
+    {
+        modmap = g_new0 (EggModmap, 1);
+
+        // FIXME modify keymap change events with an event filter and force a reload if we get one
+
+        reload_modmap (keymap, modmap);
+
+        g_object_set_data_full (G_OBJECT (keymap), "egg-modmap", modmap, g_free);
+    }
+
+    g_assert (modmap != NULL);
+
+    return modmap;
+}

Added: trunk/src/eggaccelerators.h
==============================================================================
--- (empty file)
+++ trunk/src/eggaccelerators.h	Mon Mar 31 22:42:16 2008
@@ -0,0 +1,92 @@
+/*
+    GNOME Commander - A GNOME based file manager
+    Copyright (C) 2001-2006 Marcus Bjurman
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* eggaccelerators.h
+ * Copyright (C) 2002  Red Hat, Inc.
+ * Developed by Havoc Pennington
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_ACCELERATORS_H__
+#define __EGG_ACCELERATORS_H__
+
+#include <gtk/gtkaccelgroup.h>
+#include <gdk/gdk.h>
+
+// Where a value is also in GdkModifierType we coincide, otherwise we don't overlap.
+typedef enum
+{
+    EGG_VIRTUAL_SHIFT_MASK    = 1 << 0,
+    EGG_VIRTUAL_LOCK_MASK     = 1 << 1,
+    EGG_VIRTUAL_CONTROL_MASK  = 1 << 2,
+
+    EGG_VIRTUAL_ALT_MASK      = 1 << 3, // fixed as MOD1
+
+    EGG_VIRTUAL_MOD2_MASK     = 1 << 4,
+    EGG_VIRTUAL_MOD3_MASK     = 1 << 5,
+    EGG_VIRTUAL_MOD4_MASK     = 1 << 6,
+    EGG_VIRTUAL_MOD5_MASK     = 1 << 7,
+
+#if 0
+    GDK_BUTTON1_MASK          = 1 << 8,
+    GDK_BUTTON2_MASK          = 1 << 9,
+    GDK_BUTTON3_MASK          = 1 << 10,
+    GDK_BUTTON4_MASK          = 1 << 11,
+    GDK_BUTTON5_MASK          = 1 << 12,
+    /* 13, 14 are used by Xkb for the keyboard group */
+#endif
+
+    EGG_VIRTUAL_META_MASK     = 1 << 24,
+    EGG_VIRTUAL_SUPER_MASK    = 1 << 25,
+    EGG_VIRTUAL_HYPER_MASK    = 1 << 26,
+    EGG_VIRTUAL_MODE_SWITCH_MASK = 1 << 27,
+    EGG_VIRTUAL_NUM_LOCK_MASK = 1 << 28,
+    EGG_VIRTUAL_SCROLL_LOCK_MASK = 1 << 29,
+
+    /* Also in GdkModifierType */
+    EGG_VIRTUAL_RELEASE_MASK  = 1 << 30,
+
+    // 28-31 24-27 20-23 16-19 12-15 8-11 4-7 0-3
+    //   7     f     0     0     0    0    f   f
+
+    EGG_VIRTUAL_MODIFIER_MASK = 0x7f0000ff
+
+} EggVirtualModifierType;
+
+gboolean egg_accelerator_parse_virtual (const gchar *accelerator, guint *accelerator_key, EggVirtualModifierType *accelerator_mods);
+void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, EggVirtualModifierType virtual_mods, GdkModifierType *concrete_mods);
+void egg_keymap_virtualize_modifiers (GdkKeymap *keymap, GdkModifierType concrete_mods, EggVirtualModifierType *virtual_mods);
+
+gchar *egg_virtual_accelerator_name (guint accelerator_key, EggVirtualModifierType accelerator_mods);
+
+#endif // __EGG_ACCELERATORS_H__

Added: trunk/src/eggcellrendererkeys.cc
==============================================================================
--- (empty file)
+++ trunk/src/eggcellrendererkeys.cc	Mon Mar 31 22:42:16 2008
@@ -0,0 +1,605 @@
+/*
+    GNOME Commander - A GNOME based file manager
+    Copyright (C) 2001-2006 Marcus Bjurman
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/*
+ * This file is part of gnome-terminal.
+ *
+ * Gnome-terminal is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Gnome-terminal 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <libintl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include "eggcellrendererkeys.h"
+#include "eggaccelerators.h"
+#include "gnome-cmd-includes.h"
+
+#define EGG_CELL_RENDERER_TEXT_PATH "egg-cell-renderer-text"
+
+static void             egg_cell_renderer_keys_finalize      (GObject             *object);
+static void             egg_cell_renderer_keys_init          (EggCellRendererKeys *cell_keys);
+static void             egg_cell_renderer_keys_class_init    (EggCellRendererKeysClass *cell_keys_class);
+static GtkCellEditable *egg_cell_renderer_keys_start_editing (GtkCellRenderer          *cell,
+                                                              GdkEvent                 *event,
+                                                              GtkWidget                *widget,
+                                                              const gchar              *path,
+                                                              GdkRectangle             *background_area,
+                                                              GdkRectangle             *cell_area,
+                                                              GtkCellRendererState      flags);
+
+
+static void egg_cell_renderer_keys_get_property (GObject         *object,
+                                                 guint            param_id,
+                                                 GValue          *value,
+                                                 GParamSpec      *pspec);
+static void egg_cell_renderer_keys_set_property (GObject         *object,
+                                                 guint            param_id,
+                                                 const GValue    *value,
+                                                 GParamSpec      *pspec);
+static void egg_cell_renderer_keys_get_size     (GtkCellRenderer *cell,
+                                                 GtkWidget       *widget,
+                                                 GdkRectangle    *cell_area,
+                                                 gint            *x_offset,
+                                                 gint            *y_offset,
+                                                 gint            *width,
+                                                 gint            *height);
+
+
+enum
+{
+    PROP_0,
+
+    PROP_ACCEL_KEY,
+    PROP_ACCEL_MASK,
+    PROP_ACCEL_MODE
+};
+
+static GtkCellRendererTextClass *parent_class = NULL;
+
+
+GType egg_cell_renderer_keys_get_type (void)
+{
+    static GType cell_keys_type = 0;
+
+    if (!cell_keys_type)
+    {
+        static const GTypeInfo cell_keys_info =
+        {
+            sizeof (EggCellRendererKeysClass),
+            NULL,                /* base_init */
+            NULL,                /* base_finalize */
+            (GClassInitFunc)egg_cell_renderer_keys_class_init,
+            NULL,                /* class_finalize */
+            NULL,                /* class_data */
+            sizeof (EggCellRendererKeys),
+            0,              /* n_preallocs */
+            (GInstanceInitFunc) egg_cell_renderer_keys_init
+        };
+
+        cell_keys_type = g_type_register_static (GTK_TYPE_CELL_RENDERER_TEXT, "EggCellRendererKeys", &cell_keys_info, GTypeFlags(0));
+    }
+
+    return cell_keys_type;
+}
+
+
+static void egg_cell_renderer_keys_init (EggCellRendererKeys *cell_keys)
+{
+    cell_keys->accel_mode = EGG_CELL_RENDERER_KEYS_MODE_GTK;
+}
+
+/* FIXME setup stuff to generate this */
+/* VOID:STRING,UINT,FLAGS,UINT */
+static void
+marshal_VOID__STRING_UINT_FLAGS_UINT (GClosure     *closure,
+                                      GValue       *return_value,
+                                      guint         n_param_values,
+                                      const GValue *param_values,
+                                      gpointer      invocation_hint,
+                                      gpointer      marshal_data)
+{
+    g_return_if_fail (n_param_values == 5);
+
+    typedef void (*GMarshalFunc_VOID__STRING_UINT_FLAGS_UINT) (gpointer     data1,
+                                                               const char  *arg_1,
+                                                               guint        arg_2,
+                                                               int          arg_3,
+                                                               guint        arg_4,
+                                                               gpointer     data2);
+    register GMarshalFunc_VOID__STRING_UINT_FLAGS_UINT callback;
+    register GCClosure *cc = (GCClosure*) closure;
+    register gpointer data1, data2;
+
+    if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+        data1 = closure->data;
+        data2 = g_value_peek_pointer (param_values + 0);
+    }
+    else
+    {
+        data1 = g_value_peek_pointer (param_values + 0);
+        data2 = closure->data;
+    }
+
+    callback = (GMarshalFunc_VOID__STRING_UINT_FLAGS_UINT) (marshal_data ? marshal_data : cc->callback);
+
+    callback (data1,
+              g_value_get_string (param_values + 1),
+              g_value_get_uint (param_values + 2),
+              g_value_get_flags (param_values + 3),
+              g_value_get_uint (param_values + 4),
+              data2);
+}
+
+
+static void egg_cell_renderer_keys_class_init (EggCellRendererKeysClass *cell_keys_class)
+{
+    GObjectClass *object_class = G_OBJECT_CLASS (cell_keys_class);
+    GtkCellRendererClass *cell_renderer_class = GTK_CELL_RENDERER_CLASS (cell_keys_class);
+
+    parent_class = (GtkCellRendererTextClass *) g_type_class_peek_parent (object_class);
+
+    GTK_CELL_RENDERER_CLASS (cell_keys_class)->start_editing = egg_cell_renderer_keys_start_editing;
+
+    object_class->get_property = egg_cell_renderer_keys_get_property;
+    object_class->set_property = egg_cell_renderer_keys_set_property;
+    cell_renderer_class->get_size = egg_cell_renderer_keys_get_size;
+
+    object_class->finalize = egg_cell_renderer_keys_finalize;
+
+    // FIXME if this gets moved to a real library, rename the properties to match whatever the GTK convention is
+
+    g_object_class_install_property (object_class,
+                                     PROP_ACCEL_KEY,
+                                     g_param_spec_uint ("accel_key",
+                                                       _("Accelerator key"),
+                                                       _("Accelerator key"),
+                                                        0,
+                                                        G_MAXINT,
+                                                        0,
+                                                        GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+    g_object_class_install_property (object_class,
+                                     PROP_ACCEL_MASK,
+                                     g_param_spec_flags ("accel_mask",
+                                                         _("Accelerator modifiers"),
+                                                         _("Accelerator modifiers"),
+                                                         GDK_TYPE_MODIFIER_TYPE,
+                                                         0,
+                                                        GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+    /* FIXME: Register the enum when moving to GTK+ */
+    g_object_class_install_property (object_class,
+                                     PROP_ACCEL_MODE,
+                                     g_param_spec_int ("accel_mode",
+                                                       _("Accelerator Mode"),
+                                                       _("The type of accelerator."),
+                                                       0,
+                                                       2,
+                                                       0,
+                                                        GParamFlags(G_PARAM_READABLE | G_PARAM_WRITABLE)));
+
+    g_signal_new ("keys_edited",
+                  EGG_TYPE_CELL_RENDERER_KEYS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (EggCellRendererKeysClass, keys_edited),
+                  NULL, NULL,
+                  marshal_VOID__STRING_UINT_FLAGS_UINT,
+                  G_TYPE_NONE, 4,
+                  G_TYPE_STRING,
+                  G_TYPE_UINT,
+                  GDK_TYPE_MODIFIER_TYPE,
+                  G_TYPE_UINT);
+}
+
+
+GtkCellRenderer *egg_cell_renderer_keys_new (void)
+{
+    return GTK_CELL_RENDERER (g_object_new (EGG_TYPE_CELL_RENDERER_KEYS, NULL));
+}
+
+
+static void egg_cell_renderer_keys_finalize (GObject *object)
+{
+    (* G_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+
+static gchar *convert_keysym_state_to_string (guint keysym, EggVirtualModifierType mask)
+{
+    return keysym == 0 ? g_strdup (_("Disabled")) : egg_virtual_accelerator_name (keysym, mask);
+}
+
+
+static void egg_cell_renderer_keys_get_property  (GObject *object, guint param_id, GValue *value, GParamSpec *pspec)
+{
+    g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (object));
+
+    EggCellRendererKeys *keys = EGG_CELL_RENDERER_KEYS (object);
+
+    switch (param_id)
+    {
+        case PROP_ACCEL_KEY:
+            g_value_set_uint (value, keys->accel_key);
+            break;
+
+        case PROP_ACCEL_MASK:
+            g_value_set_flags (value, keys->accel_mask);
+            break;
+
+        case PROP_ACCEL_MODE:
+            g_value_set_int (value, keys->accel_mode);
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+
+static void egg_cell_renderer_keys_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec)
+{
+    g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (object));
+
+    EggCellRendererKeys *keys = EGG_CELL_RENDERER_KEYS (object);
+
+    switch (param_id)
+    {
+        case PROP_ACCEL_KEY:
+            egg_cell_renderer_keys_set_accelerator (keys, g_value_get_uint (value), keys->accel_mask);
+            break;
+
+        case PROP_ACCEL_MASK:
+            egg_cell_renderer_keys_set_accelerator (keys, keys->accel_key, (EggVirtualModifierType) g_value_get_flags (value));
+            break;
+
+        case PROP_ACCEL_MODE:
+            egg_cell_renderer_keys_set_accel_mode (keys, (EggCellRendererKeysMode) g_value_get_int (value));
+            break;
+
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+    }
+}
+
+
+inline gboolean is_modifier (guint keycode)
+{
+    gboolean retval = FALSE;
+
+    XModifierKeymap *mod_keymap = XGetModifierMapping (gdk_display);
+
+    gint map_size = 8 * mod_keymap->max_keypermod;
+
+    for (gint i=0; i<map_size;  ++i)
+        if (keycode == mod_keymap->modifiermap[i])
+        {
+            retval = TRUE;
+            break;
+        }
+
+    XFreeModifiermap (mod_keymap);
+
+    return retval;
+}
+
+
+void egg_cell_renderer_keys_get_size (GtkCellRenderer *cell,
+                                      GtkWidget       *widget,
+                                      GdkRectangle    *cell_area,
+                                      gint            *x_offset,
+                                      gint            *y_offset,
+                                      gint            *width,
+                                      gint            *height)
+{
+    EggCellRendererKeys *keys = (EggCellRendererKeys *) cell;
+    GtkRequisition requisition;
+
+    if (keys->sizing_label == NULL)
+        keys->sizing_label = gtk_label_new (_("Type a new accelerator, or press Backspace to clear"));
+
+    gtk_widget_size_request (keys->sizing_label, &requisition);
+    (* GTK_CELL_RENDERER_CLASS (parent_class)->get_size) (cell, widget, cell_area, x_offset, y_offset, width, height);
+
+    /* FIXME: need to take the cell_area et al. into account */
+    if (width)
+        *width = MAX (*width, requisition.width);
+    if (height)
+        *height = MAX (*height, requisition.height);
+}
+
+
+// FIXME: Currently we don't differentiate between a 'bogus' key (like tab in GTK mode) and a removed key.
+static gboolean grab_key_callback (GtkWidget *widget, GdkEventKey *event, void *data)
+{
+    char *path;
+    guint upper;
+    GdkModifierType ignored_modifiers;
+
+    EggCellRendererKeys *keys = EGG_CELL_RENDERER_KEYS (data);
+    guint accel_mods = 0;
+
+    if (is_modifier (event->hardware_keycode))
+        return TRUE;
+
+    gboolean edited = FALSE;
+    guint consumed_modifiers = 0;
+
+    gdk_keymap_translate_keyboard_state (gdk_keymap_get_default (),
+                                         event->hardware_keycode,
+                                         (GdkModifierType) event->state,
+                                         event->group,
+                                         NULL, NULL, NULL, (GdkModifierType *) &consumed_modifiers);
+
+    upper = event->keyval;
+    guint accel_keyval = gdk_keyval_to_lower (upper);
+    if (accel_keyval == GDK_ISO_Left_Tab)
+        accel_keyval = GDK_Tab;
+
+
+
+    // Put shift back if it changed the case of the key, not otherwise.
+    if (upper != accel_keyval && (consumed_modifiers & GDK_SHIFT_MASK))
+        consumed_modifiers &= ~(GDK_SHIFT_MASK);
+
+    egg_keymap_resolve_virtual_modifiers (gdk_keymap_get_default (),
+                                          EggVirtualModifierType (EGG_VIRTUAL_NUM_LOCK_MASK | EGG_VIRTUAL_SCROLL_LOCK_MASK),
+                                          &ignored_modifiers);
+
+  /* filter consumed/ignored modifiers */
+
+    if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK)
+        accel_mods = event->state & ~(consumed_modifiers | ignored_modifiers);
+    else if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_X)
+        accel_mods = event->state & ~(ignored_modifiers);
+    else
+        g_assert_not_reached ();
+
+    if (accel_mods == 0 && accel_keyval == GDK_Escape)
+        goto out; /* cancel */
+
+    /* clear the accelerator on Backspace */
+    if (keys->edit_key!=0 && accel_mods==0 && accel_keyval==GDK_BackSpace)
+        accel_keyval = 0;
+
+    if (keys->accel_mode == EGG_CELL_RENDERER_KEYS_MODE_GTK)
+    {
+        if (!gtk_accelerator_valid (accel_keyval, (GdkModifierType) accel_mods))
+        {
+            accel_keyval = 0;
+            accel_mods = 0;
+        }
+
+        /* Remove modifiers like super and hyper, as GTK+ ignores them. */
+        accel_mods &= GDK_MODIFIER_MASK;
+    }
+
+    edited = TRUE;
+
+ out:
+    path = g_strdup ((gchar *) g_object_get_data (G_OBJECT (keys->edit_widget), EGG_CELL_RENDERER_TEXT_PATH));
+
+    gdk_keyboard_ungrab (event->time);
+    gdk_pointer_ungrab (event->time);
+
+    gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (keys->edit_widget));
+    gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (keys->edit_widget));
+    keys->edit_widget = NULL;
+    keys->grab_widget = NULL;
+
+    if (edited)
+        g_signal_emit_by_name (G_OBJECT (keys), "keys_edited", path, accel_keyval, accel_mods, event->hardware_keycode);
+
+    g_free (path);
+
+    return TRUE;
+}
+
+
+static void ungrab_stuff (GtkWidget *widget, gpointer data)
+{
+    EggCellRendererKeys *keys = EGG_CELL_RENDERER_KEYS (data);
+
+    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
+    gdk_pointer_ungrab (GDK_CURRENT_TIME);
+
+    g_signal_handlers_disconnect_by_func (G_OBJECT (keys->grab_widget), (gpointer) G_CALLBACK (grab_key_callback), data);
+}
+
+
+static void pointless_eventbox_start_editing (GtkCellEditable *cell_editable, GdkEvent *event)
+{
+    /* do nothing, because we are pointless */
+}
+
+
+static void pointless_eventbox_cell_editable_init (GtkCellEditableIface *iface)
+{
+    iface->start_editing = pointless_eventbox_start_editing;
+}
+
+
+static GType pointless_eventbox_subclass_get_type (void)
+{
+  static GType eventbox_type = 0;
+
+  if (!eventbox_type)
+    {
+      static const GTypeInfo eventbox_info =
+      {
+        sizeof (GtkEventBoxClass),
+        NULL,               /* base_init */
+        NULL,               /* base_finalize */
+        NULL,
+        NULL,               /* class_finalize */
+        NULL,               /* class_data */
+        sizeof (GtkEventBox),
+        0,                  /* n_preallocs */
+        (GInstanceInitFunc) NULL,
+      };
+
+      static const GInterfaceInfo cell_editable_info = { (GInterfaceInitFunc) pointless_eventbox_cell_editable_init, NULL, NULL };
+
+      eventbox_type = g_type_register_static (GTK_TYPE_EVENT_BOX, "EggCellEditableEventBox", &eventbox_info, GTypeFlags(0));
+
+      g_type_add_interface_static (eventbox_type,
+                                   GTK_TYPE_CELL_EDITABLE,
+                                   &cell_editable_info);
+    }
+
+  return eventbox_type;
+}
+
+
+static GtkCellEditable *
+egg_cell_renderer_keys_start_editing (GtkCellRenderer      *cell,
+                                      GdkEvent             *event,
+                                      GtkWidget            *widget,
+                                      const gchar          *path,
+                                      GdkRectangle         *background_area,
+                                      GdkRectangle         *cell_area,
+                                      GtkCellRendererState  flags)
+{
+    g_return_val_if_fail (widget->window != NULL, NULL);
+
+    GtkWidget *label;
+    GtkWidget *eventbox;
+
+    GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
+    EggCellRendererKeys *keys = EGG_CELL_RENDERER_KEYS (cell);
+
+    // If the cell isn't editable we return NULL
+    if (celltext->editable == FALSE)
+        return NULL;
+
+    if (gdk_keyboard_grab (widget->window, FALSE, gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
+        return NULL;
+
+    if (gdk_pointer_grab (widget->window, FALSE,
+                          GDK_BUTTON_PRESS_MASK,
+                          NULL, NULL,
+                          gdk_event_get_time (event)) != GDK_GRAB_SUCCESS)
+    {
+        gdk_keyboard_ungrab (gdk_event_get_time (event));
+        return NULL;
+    }
+
+    keys->grab_widget = widget;
+
+    g_signal_connect (G_OBJECT (widget), "key_press_event", G_CALLBACK (grab_key_callback), keys);
+
+    eventbox = (GtkWidget *) g_object_new (pointless_eventbox_subclass_get_type (), NULL);
+    keys->edit_widget = eventbox;
+    g_object_add_weak_pointer (G_OBJECT (keys->edit_widget), (void**) &keys->edit_widget);
+
+    label = gtk_label_new (NULL);
+    gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+    gtk_widget_modify_bg (eventbox, GTK_STATE_NORMAL, &widget->style->bg[GTK_STATE_SELECTED]);
+
+    gtk_widget_modify_fg (label, GTK_STATE_NORMAL, &widget->style->fg[GTK_STATE_SELECTED]);
+
+    if (keys->accel_key != 0)
+        gtk_label_set_text (GTK_LABEL (label), _("Type a new accelerator, or press Backspace to clear"));
+    else
+        gtk_label_set_text (GTK_LABEL (label), _("Type a new accelerator"));
+
+    gtk_container_add (GTK_CONTAINER (eventbox), label);
+
+    g_object_set_data_full (G_OBJECT (keys->edit_widget), EGG_CELL_RENDERER_TEXT_PATH, g_strdup (path), g_free);
+
+    gtk_widget_show_all (keys->edit_widget);
+
+    g_signal_connect (G_OBJECT (keys->edit_widget), "unrealize", G_CALLBACK (ungrab_stuff), keys);
+
+    keys->edit_key = keys->accel_key;
+
+    return GTK_CELL_EDITABLE (keys->edit_widget);
+}
+
+
+void egg_cell_renderer_keys_set_accelerator (EggCellRendererKeys *keys, guint keyval, EggVirtualModifierType mask)
+{
+    g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (keys));
+
+    g_object_freeze_notify (G_OBJECT (keys));
+
+    gboolean changed = FALSE;
+
+    if (keyval != keys->accel_key)
+    {
+        keys->accel_key = keyval;
+        g_object_notify (G_OBJECT (keys), "accel_key");
+        changed = TRUE;
+    }
+
+    if (mask != keys->accel_mask)
+    {
+        keys->accel_mask = mask;
+
+        g_object_notify (G_OBJECT (keys), "accel_mask");
+        changed = TRUE;
+    }
+
+    g_object_thaw_notify (G_OBJECT (keys));
+
+    if (changed)
+    {
+        /* sync string to the key values */
+        GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (keys);
+        char *text = convert_keysym_state_to_string (keys->accel_key, keys->accel_mask);
+        g_object_set (keys, "text", text, NULL);
+        g_free (text);
+    }
+
+}
+
+
+void egg_cell_renderer_keys_get_accelerator (EggCellRendererKeys *keys, guint *keyval, EggVirtualModifierType *mask)
+{
+    g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (keys));
+
+    if (keyval)
+        *keyval = keys->accel_key;
+
+    if (mask)
+        *mask = keys->accel_mask;
+}
+
+
+void egg_cell_renderer_keys_set_accel_mode (EggCellRendererKeys *keys, EggCellRendererKeysMode accel_mode)
+{
+    g_return_if_fail (EGG_IS_CELL_RENDERER_KEYS (keys));
+
+    keys->accel_mode = accel_mode;
+    g_object_notify (G_OBJECT (keys), "accel_mode");
+}

Added: trunk/src/eggcellrendererkeys.h
==============================================================================
--- (empty file)
+++ trunk/src/eggcellrendererkeys.h	Mon Mar 31 22:42:16 2008
@@ -0,0 +1,93 @@
+/*
+    GNOME Commander - A GNOME based file manager
+    Copyright (C) 2001-2006 Marcus Bjurman
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+/* gtkcellrendererkeybinding.h
+ * Copyright (C) 2000  Red Hat, Inc.,  Jonathan Blandford <jrb redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_CELL_RENDERER_KEYS_H__
+#define __EGG_CELL_RENDERER_KEYS_H__
+
+#include <gtk/gtkcellrenderertext.h>
+#include "eggaccelerators.h"
+
+#define EGG_TYPE_CELL_RENDERER_KEYS             (egg_cell_renderer_keys_get_type ())
+#define EGG_CELL_RENDERER_KEYS(obj)             (GTK_CHECK_CAST ((obj), EGG_TYPE_CELL_RENDERER_KEYS, EggCellRendererKeys))
+#define EGG_CELL_RENDERER_KEYS_CLASS(klass)     (GTK_CHECK_CLASS_CAST ((klass), EGG_TYPE_CELL_RENDERER_KEYS, EggCellRendererKeysClass))
+#define EGG_IS_CELL_RENDERER_KEYS(obj)          (GTK_CHECK_TYPE ((obj), EGG_TYPE_CELL_RENDERER_KEYS))
+#define EGG_IS_CELL_RENDERER_KEYS_CLASS(klass)  (GTK_CHECK_CLASS_TYPE ((klass), EGG_TYPE_CELL_RENDERER_KEYS))
+#define EGG_CELL_RENDERER_KEYS_GET_CLASS(obj)   (GTK_CHECK_GET_CLASS ((obj), EGG_TYPE_CELL_RENDERER_KEYS, EggCellRendererKeysClass))
+
+typedef struct _EggCellRendererKeys      EggCellRendererKeys;
+typedef struct _EggCellRendererKeysClass EggCellRendererKeysClass;
+
+
+typedef enum
+{
+    EGG_CELL_RENDERER_KEYS_MODE_GTK,
+    EGG_CELL_RENDERER_KEYS_MODE_X,
+} EggCellRendererKeysMode;
+
+
+struct _EggCellRendererKeys
+{
+    GtkCellRendererText parent;
+    guint accel_key;
+    EggVirtualModifierType accel_mask;
+    GtkWidget *edit_widget;
+    GtkWidget *grab_widget;
+    guint edit_key;
+    GtkWidget *sizing_label;
+    EggCellRendererKeysMode accel_mode;
+};
+
+struct _EggCellRendererKeysClass
+{
+  GtkCellRendererTextClass parent_class;
+
+  void (* keys_edited) (EggCellRendererKeys    *keys,
+                        const char             *path_string,
+                        guint                   keyval,
+                        EggVirtualModifierType  mask,
+                        guint                   hardware_keycode);
+};
+
+GType egg_cell_renderer_keys_get_type (void);
+GtkCellRenderer *egg_cell_renderer_keys_new (void);
+
+void  egg_cell_renderer_keys_set_accelerator (EggCellRendererKeys *keys, guint keyval, EggVirtualModifierType mask);
+void  egg_cell_renderer_keys_get_accelerator (EggCellRendererKeys *keys, guint *keyval, EggVirtualModifierType *mask);
+void  egg_cell_renderer_keys_set_accel_mode (EggCellRendererKeys *keys, EggCellRendererKeysMode accel_mode);
+
+#endif // __GTK_CELL_RENDERER_KEYS_H__



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]