Code

response to bug #167290; add another undoc option to support alt-key tracking for...
authorspeare <speare@users.sourceforge.net>
Mon, 16 Mar 2009 21:43:07 +0000 (21:43 +0000)
committerspeare <speare@users.sourceforge.net>
Mon, 16 Mar 2009 21:43:07 +0000 (21:43 +0000)
src/inkscape-private.h
src/inkscape.cpp
src/main.cpp

index 676fff8a46cba0a2f08b89e05d9e2dd47b0cecce..cb7f98729aa5ef23fdc57414f5035524b6a8a175 100644 (file)
@@ -32,6 +32,9 @@ void inkscape_unref (void);
 guint inkscape_mapalt();
 void inkscape_mapalt(guint);
 
+guint inkscape_trackalt();
+void inkscape_trackalt(guint);
+
 /*
  * These are meant solely for desktop, document etc. implementations
  */
index b497367cc999714f4283782aa93782a4bb57c3b7..25b3cc5a96ecf21e5655374b7b759c281935ee17 100644 (file)
@@ -110,6 +110,7 @@ struct Inkscape::Application {
     gboolean use_gui;         // may want to consider a virtual function
                               // for overriding things like the warning dlg's
     guint mapalt;
+    guint trackalt;
 };
 
 struct Inkscape::ApplicationClass {
@@ -462,7 +463,8 @@ inkscape_init (SPObject * object)
     inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL);
     inkscape->desktops = NULL;
     inkscape->dialogs_toggle = TRUE;
-    inkscape->mapalt=GDK_MOD1_MASK;
+    inkscape->mapalt = GDK_MOD1_MASK;
+    inkscape->trackalt = FALSE;
 }
 
 static void
@@ -520,6 +522,17 @@ void inkscape_mapalt(guint maskvalue)
     }
 }
 
+guint
+inkscape_trackalt() {
+    return inkscape->trackalt;
+}
+
+void inkscape_trackalt(guint trackvalue)
+{
+       inkscape->trackalt = trackvalue;
+}
+
+
 static void
 inkscape_activate_desktop_private (Inkscape::Application */*inkscape*/, SPDesktop *desktop)
 {
@@ -775,9 +788,10 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
     }
 
     /* Check for global remapping of Alt key */
-    if(use_gui)
+    if (use_gui)
     {
         inkscape_mapalt(guint(prefs->getInt("/options/mapalt/value", 0)));
+        inkscape_trackalt(guint(prefs->getInt("/options/trackalt/value", 0)));
     }
 
     /* Initialize the extensions */
index 991a95adda6554cdfb1eee20e3f3145480c661f1..b5ace5405a74fce9f2554446ae427f9f85edefa1 100644 (file)
@@ -801,7 +801,7 @@ int sp_common_main( int argc, char const **argv, GSList **flDest )
 
 static void
 snooper(GdkEvent *event, gpointer /*data*/) {
-    if(inkscape_mapalt())  /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
+    if (inkscape_mapalt())  /* returns the map of the keyboard modifier to map to Alt, zero if no mapping */
     {
         GdkModifierType mapping=(GdkModifierType)inkscape_mapalt();
         switch (event->type) {
@@ -824,6 +824,56 @@ snooper(GdkEvent *event, gpointer /*data*/) {
             break;
         }
     }
+
+    if (inkscape_trackalt()) {
+        // MacOS X with X11 has some problem with the default
+        // xmodmapping.  A ~/.xmodmap solution does not work reliably due
+        // to the way we package our executable in a .app that can launch
+        // X11 or use an already-running X11.  The same problem has been
+        // reported on Linux but there is no .app/X11 to get in the way
+        // of ~/.xmodmap fixes.  So we make this a preference.
+        //
+        // For some reason, Gdk senses changes in Alt (Mod1) state for
+        // many message types, but not for keystrokes!  So this ugly hack
+        // tracks what the state of Alt-pressing is, and ensures
+        // GDK_MOD1_MASK is in the event->key.state as appropriate.
+        //
+        static gboolean altL_pressed = FALSE;
+        static gboolean altR_pressed = FALSE;
+        static gboolean alt_pressed = FALSE;
+        guint get_group0_keyval(GdkEventKey* event);
+        guint keyval = 0;
+        switch (event->type) {
+        case GDK_MOTION_NOTIFY:
+            alt_pressed = TRUE && (event->motion.state & GDK_MOD1_MASK);
+            break;
+        case GDK_BUTTON_PRESS:
+            alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK);
+            break;
+        case GDK_KEY_PRESS:
+            keyval = get_group0_keyval(&event->key);
+            if (keyval == GDK_Alt_L) altL_pressed = TRUE;
+            if (keyval == GDK_Alt_R) altR_pressed = TRUE;
+            alt_pressed = alt_pressed || altL_pressed || altR_pressed;
+            alt_pressed = alt_pressed || (event->button.state & GDK_MOD1_MASK);
+            if (alt_pressed)
+                event->key.state |= GDK_MOD1_MASK;
+            else
+                event->key.state &= ~GDK_MOD1_MASK;
+            break;
+        case GDK_KEY_RELEASE:
+            keyval = get_group0_keyval(&event->key);
+            if (keyval == GDK_Alt_L) altL_pressed = FALSE;
+            if (keyval == GDK_Alt_R) altR_pressed = FALSE;
+            if (!altL_pressed && !altR_pressed)
+                alt_pressed = FALSE;
+            break;
+        default:
+            break;
+        }
+        //printf("alt_pressed: %s\n", alt_pressed? "+" : "-");
+    }
+
     gtk_main_do_event (event);
 }