unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Using windows keys for Emacs META on w32
@ 2008-01-05 20:48 Lennart Borgman (gmail)
  2008-01-23 16:14 ` Jason Rumney
  0 siblings, 1 reply; 6+ messages in thread
From: Lennart Borgman (gmail) @ 2008-01-05 20:48 UTC (permalink / raw)
  To: Emacs Devel, Juanma Barranquero, Eli Zaretskii

[-- Attachment #1: Type: text/plain, Size: 169 bytes --]

I promised Juanma to make a new patch with the changes I have made to 
allow using the windows left and/or right keys for Emacs meta. Here it 
is, in a bit rough state.

[-- Attachment #2: ll-keyboard.diff --]
[-- Type: text/plain, Size: 30783 bytes --]

Index: src/w32fns.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32fns.c,v
retrieving revision 1.310
diff -u -b -r1.310 w32fns.c
--- src/w32fns.c        29 Dec 2007 19:20:04 -0000      1.310
+++ src/w32fns.c        5 Jan 2008 20:05:42 -0000
@@ -2155,9 +2155,20 @@
 #define EMACS_LMENU    2
 #define EMACS_RMENU    3

-static int modifiers[4];
+/* The keys above are also saved in modifiers[]. To allow
+   w32-pass-lwindow-to-system to be nil the state of the left and
+   right windows keys must also be saved in modifiers[]. This is a bit
+   tricky since Windows does not keep track of the state of those keys
+   when StickyKeys are on.  (Because they are registered as hot
+   keys?) */
+
+#define EMACS_LWIN    4
+#define EMACS_RWIN    5
+
+static int modifiers[6];
 static int modifiers_recorded;
 static int modifier_key_support_tested;
+static BOOL b_menu_pending = FALSE;

 static void
 test_modifier_support (unsigned int wparam)
@@ -2191,10 +2202,25 @@
   if (!modifier_key_support_tested)
     test_modifier_support (wparam);

+  if (VK_LWIN != wparam && VK_RWIN != wparam) {
   if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
     return;
+  } else {
+    if (VK_LWIN == wparam && !NILP(Vw32_pass_lwindow_to_system)) {
+      return;
+    }
+    if (VK_RWIN == wparam && !NILP(Vw32_pass_rwindow_to_system)) {
+      return;
+    }
+  }

-  if (wparam == VK_CONTROL)
+  //printf("record_keydow2 wp=%d lp=%x\n", wparam, lparam); fflush(stdout);
+
+  if (VK_LWIN == wparam) {
+    i = EMACS_LWIN;
+  } else if (VK_RWIN == wparam) {
+    i = EMACS_RWIN;
+  } else if (wparam == VK_CONTROL)
     i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
   else
     i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
@@ -2207,17 +2233,47 @@
 {
   int i;

+  if (VK_LWIN != wparam && VK_RWIN != wparam) {
   if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
     return;
+  } else {
+    if (VK_LWIN == wparam && !NILP(Vw32_pass_lwindow_to_system)) {
+      return;
+    }
+    if (VK_RWIN == wparam && !NILP(Vw32_pass_rwindow_to_system)) {
+      return;
+    }
+  }
+  //printf("record_keyup2  wp=%d lp=%x\n", wparam, lparam); fflush(stdout);

-  if (wparam == VK_CONTROL)
+  if (VK_LWIN == wparam) {
+    i = EMACS_LWIN;
+  } else if (VK_RWIN == wparam) {
+    i = EMACS_RWIN;
+  } else if (wparam == VK_CONTROL)
     i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
   else
     i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;

+  if (EMACS_LWIN == i || EMACS_RWIN == i) {
+    //printf("record_keyup wp=%d, i=%d\n", wparam, i); fflush(stdout);
+  }
   modifiers[i] = 0;
 }

+static void
+set_key_state(int vkey, int state)
+{
+  BYTE keystate[256];
+
+#define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
+
+  GetKeyboardState (keystate);
+  keystate[vkey] = state;
+  SetKeyboardState (keystate);
+}
+
+
 /* Emacs can lose focus while a modifier key has been pressed.  When
    it regains focus, be conservative and clear all modifiers since
    we cannot reconstruct the left and right modifier state.  */
@@ -2230,6 +2286,9 @@
     /* Emacs doesn't have keyboard focus.  Do nothing.  */
     return;

+  //printf("resetting menu_pending 2\n"); fflush(stdout);
+  b_menu_pending = FALSE;
+
   ctrl = GetAsyncKeyState (VK_CONTROL);
   alt = GetAsyncKeyState (VK_MENU);

@@ -2241,6 +2300,15 @@
     /* Clear any recorded alt modifier state.  */
     modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;

+  if (!(GetAsyncKeyState(VK_LWIN) & 0x08000)) {
+    //printf("EMACS_LWIN 1=0\n"); fflush(stdout);
+    modifiers[EMACS_LWIN] = 0;
+  }
+  if (!(GetAsyncKeyState(VK_RWIN) & 0x08000)) {
+    //printf("EMACS_RWIN 1=0\n"); fflush(stdout);
+    modifiers[EMACS_RWIN] = 0;
+  }
+
   /* Update the state of all modifier keys, because modifiers used in
      hot-key combinations can get stuck on if Emacs loses focus as a
      result of a hot-key being pressed.  */
@@ -2279,13 +2347,31 @@

   if (!(GetKeyState (VK_MENU) & 0x8000))
     modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
+
+  if (!(GetKeyState (VK_LWIN) & 0x8000)) {
+    //printf("EMACS_LWIN 2=0\n"); fflush(stdout);
+    modifiers[EMACS_LWIN] = 0;
+  }
+  if (!(GetKeyState (VK_RWIN) & 0x8000)) {
+    //printf("EMACS_RWIN 2=0\n"); fflush(stdout);
+    modifiers[EMACS_RWIN] = 0;
+  }
 }

 static int
 modifier_set (int vkey)
 {
+  //if (vkey) { printf("modifier_set %d\n", vkey); fflush(stdout); }
   if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
     return (GetKeyState (vkey) & 0x1);
+  if (VK_LWIN == vkey && NILP(Vw32_pass_lwindow_to_system)) {
+    //printf("modifier_set L %d, %d\n", vkey, modifiers[EMACS_LWIN]); fflush(stdout);
+    return modifiers[EMACS_LWIN];
+  }
+  if (VK_RWIN == vkey && NILP(Vw32_pass_rwindow_to_system)) {
+    //printf("modifier_set R %d, %d\n", vkey, modifiers[EMACS_RWIN]); fflush(stdout);
+    return modifiers[EMACS_RWIN];
+  }
   if (!modifiers_recorded)
     return (GetKeyState (vkey) & 0x8000);

@@ -2481,6 +2567,13 @@
     }
 }

+int cAccelerators = 0;      // number of accelerators in table
+static HACCEL hAccelDyn = NULL;
+static LPACCEL lpaccelDyn = NULL;
+
+BOOL add_LowLevelKeyboardProc();
+BOOL remove_LowLevelKeyboardProc();
+
 /* Main message dispatch loop. */

 static void
@@ -2489,11 +2582,15 @@
   MSG msg;
   int result;
   HWND focus_window;
+  BOOL bRet;

   msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);

-  while (GetMessage (&msg, NULL, 0, 0))
+  while ( (bRet = GetMessage (&msg, NULL, 0, 0)) != 0)
     {
+      if (-1 == bRet) {
+        // error, handle?
+      } else {
       if (msg.hwnd == NULL)
        {
          switch (msg.message)
@@ -2501,6 +2598,27 @@
            case WM_NULL:
              /* Produced by complete_deferred_msg; just ignore.  */
              break;
+            case WM_QUERYENDSESSION:
+              //case WM_ENDSESSION: default handling
+              /* This is currently not used since Emacs does not
+                 recieve this message (at least not to the windows
+                 thread) but might be if Emacs is restructured. */
+              {
+                W32Msg wmsg;
+                //printf("w32_msg_pump 1: WM_QUERYENDSESSION\n"); fflush(stdout);
+                my_post_msg (&wmsg, 0, WM_EMACS_KILL, 0, 0);
+                break;
+              }
+            case WM_EMACS_KBD_LL:
+              if (msg.wParam) {
+                result = (int) add_LowLevelKeyboardProc();
+              } else {
+                result = (int) remove_LowLevelKeyboardProc();
+              }
+              if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
+                                      result, 0))
+                abort ();
+              break;
            case WM_EMACS_CREATEWINDOW:
               /* Initialize COM for this window. Even though we don't use it,
                  some third party shell extensions can cause it to be used in
@@ -2583,7 +2701,18 @@
        }
       else
        {
-         DispatchMessage (&msg);
+          BOOL bHandled = FALSE;
+          if (hAccelDyn)
+            if (Vw32_pass_alt_to_system) {
+              bHandled = TranslateAccelerator(msg.hwnd, hAccelDyn, &msg);
+              if (bHandled) {
+                //printf("...handled\n"); fflush(stdout);
+              } else {
+               printf("...TA failed: %s\n", w32_strerror(GetLastError())); fflush(stdout);
+              }
+            }
+          if (!bHandled) DispatchMessage (&msg);
+        }
        }

       /* Exit nested loop when our deferred message has completed.  */
@@ -2688,6 +2817,130 @@
   PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
 }

+
+
+LRESULT
+//HOOKPROC
+LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam)
+{
+  if (nCode == HC_ACTION)
+    {
+      KBDLLHOOKSTRUCT *pkbdllhook = (KBDLLHOOKSTRUCT *)lParam;
+      BOOL bHandle = FALSE;
+      UINT transition_state;
+      UINT previous_state = 0;
+      UINT context_code;
+      UINT extended_key;
+      UINT msg;
+      WPARAM wParamMsg;
+      LPARAM lParamMsg;
+
+      switch (wParam)
+        {
+        case WM_KEYUP:
+        case WM_SYSKEYUP:
+          previous_state = 1;
+        case WM_KEYDOWN:  // This was not in the MS example, why??
+        case WM_SYSKEYDOWN:
+          /* Convert the message and send it on.
+          FIX-ME: This code should be moved down to bHandle part after
+          testing. */
+          transition_state = pkbdllhook->flags >> 7 & 1;
+          context_code     = pkbdllhook->flags >> 5 & 1;
+          extended_key     = pkbdllhook->flags & 1;
+          msg = wParam;
+          wParamMsg = pkbdllhook->vkCode;
+          lParamMsg =
+            pkbdllhook->scanCode << 16
+            | transition_state << 31
+            | previous_state << 30
+            | context_code     << 29
+            | extended_key     << 24
+            | 1; // repeat count
+/*           if (0 != GetFocus()) { */
+/*             if (91 == pkbdllhook->vkCode) { */
+/*               printf("ll wp=%d lp=%x, ts=%d, cc=%d, ek=%d\n", wParamMsg, lParamMsg, transition_state, context_code, extended_key); */
+/*               fflush(stdout); */
+/*             } */
+/*           } */
+          switch (pkbdllhook->vkCode)
+            {
+              /* Since Vw32_pass_lwindow_to_system is just a struct
+                 and NILP a comparision with == we do not have to sync
+                 to make this comparision in the windows thread.  The
+                 value might temporarily be wrong, but no crashes can
+                 occor.  (But what about cashing of the value in the
+                 windows thread?) */
+            case VK_LWIN:
+              {
+                bHandle = NILP(Vw32_pass_lwindow_to_system);
+                break;
+              }
+            case VK_RWIN:
+              {
+                bHandle = NILP(Vw32_pass_rwindow_to_system);
+                break;
+              }
+            case VK_CAPITAL:
+              {
+                bHandle = NILP(Vw32_enable_caps_lock);
+                break;
+              }
+            case VK_NUMLOCK:
+              {
+                bHandle = NILP(Vw32_enable_num_lock);
+                break;
+              }
+            }
+        }
+      if (bHandle) {
+        // Just to be sure check we are in the right thread
+        if (GetCurrentThreadId() == dwWindowsThreadId) {
+          // Do we have keyboard focus?
+          HWND hwnd = GetFocus();
+          if (0 != hwnd) {
+            //printf("ll SendMessage(hwnd, msg, %x, %x)\n", wParamMsg, lParamMsg); fflush(stdout);
+            SendMessage (hwnd, msg, wParamMsg, lParamMsg);
+            return TRUE;
+          }
+        }
+      }
+
+
+
+    }
+  HHOOK hhook; return CallNextHookEx(hhook, nCode, wParam, lParam);
+}
+
+static HHOOK hLowKBhookW = NULL;
+
+BOOL
+add_LowLevelKeyboardProc()
+{
+  if (NULL != hLowKBhookW) return TRUE;
+  if (GetCurrentThreadId() == dwWindowsThreadId) {
+    hLowKBhookW = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC) LowLevelKeyboardProc, (HINSTANCE) GetModuleHandle(NULL), 0);
+    if (NULL == hLowKBhookW) {
+      printf("SetWindowsHookEx error: %s\n", w32_strerror(GetLastError())); fflush(stdout);
+      return FALSE;
+    }
+  } else {
+    printf("add_LowLevelKeyboardProc called from other thread then windows thread\n"); fflush(stdout);
+    abort();
+  }
+  return TRUE;
+}
+BOOL
+remove_LowLevelKeyboardProc()
+{
+  if (NULL == hLowKBhookW) return TRUE;
+  if (!UnhookWindowsHookEx(hLowKBhookW)) {
+    printf("UnhookWindowsHookEx error: %s\n", w32_strerror(GetLastError())); fflush(stdout);
+  }
+  hLowKBhookW = NULL;
+}
+
+
 DWORD WINAPI
 w32_msg_worker (void *arg)
 {
@@ -2707,8 +2960,33 @@

   /* This is the inital message loop which should only exit when the
      application quits.  */
+
+  /* Below is some test code if someone would like to use it.  The
+     code is written after an example from MS but it does not work ;-)
+  */
+/*   cAccelerators = 1;      // number of accelerators in table */
+/*   lpaccelDyn = (LPACCEL) LocalAlloc(LPTR, cAccelerators * sizeof(ACCEL)); */
+/*   if (!lpaccelDyn) {  */
+/*     printf("LocalAlloc error: %s\n", w32_strerror(GetLastError())); fflush(stdout); */
+/*   } else { */
+/*     printf("LocalAlloc ok: %s\n", w32_strerror(GetLastError())); fflush(stdout); */
+/*   } */
+/*   lpaccelDyn[0].fVirt = FVIRTKEY; */
+/*   lpaccelDyn[0].key   = VK_F4; */
+/*   lpaccelDyn[0].cmd   = 0; //SC_CLOSE; */
+/*   hAccelDyn = CreateAcceleratorTable(lpaccelDyn, cAccelerators); */
+/*   if (!hAccelDyn) { */
+/*     printf("CreateAcceleratorTable error: %s\n", w32_strerror(GetLastError())); fflush(stdout); */
+/*   } else { */
+/*     printf("CreateAcceleratorTable ok: %s\n", w32_strerror(GetLastError())); fflush(stdout); */
+/*   } */
+
   w32_msg_pump (&dummy_buf);

+  if (lpaccelDyn) {
+    LocalFree(lpaccelDyn);
+  }
+
   return 0;
 }

@@ -2731,17 +3009,25 @@


 static void
-post_character_message (hwnd, msg, wParam, lParam, modifiers)
+post_character_message (hwnd, msg, wParam, lParam, dwmodifiers)
      HWND hwnd;
      UINT msg;
      WPARAM wParam;
      LPARAM lParam;
-     DWORD  modifiers;
+     DWORD  dwmodifiers;

 {
   W32Msg wmsg;

-  wmsg.dwModifiers = modifiers;
+  //printf("post_char, msg=%d, wp=%x, lp=%x, mod=%x\n", msg, wParam, lParam, dwmodifiers); fflush(stdout);
+  // Clear LWIN here to be able to handle it for StickyKeys
+  modifiers[EMACS_LWIN] = modifiers[EMACS_RWIN] = 0;
+
+  // Never post alt_modifier here if system should have ALT
+  if (!NILP (Vw32_pass_alt_to_system)) {
+    dwmodifiers = (dwmodifiers | alt_modifier) ^ alt_modifier;
+  }
+  wmsg.dwModifiers = dwmodifiers;

   /* Detect quit_char and set quit-flag directly.  Note that we
      still need to post a message to ensure the main thread will be
@@ -2803,6 +3089,17 @@
      WPARAM wParam;
      LPARAM lParam;
 {
+  //printf("w32_wnd_proc(hwnd, %d, %x, %x)\n", msg, wParam, lParam); fflush(stdout);
+  BOOL bStickyKeysOn = FALSE;
+  STICKYKEYS stick;
+  /* Bit 24 should be "extended key" for key messages. However
+     it seems to have some other functions too when StickyKeys are
+     on. */
+  BOOL bit24  = FALSE;
+  /* Bit 29 is context code for key messages (Alt pressed or not) */
+  //BOOL bit29  = FALSE;
+  static BOOL b_was_menu_pending = FALSE;
+
   struct frame *f;
   struct w32_display_info *dpyinfo = &one_w32_display_info;
   W32Msg wmsg;
@@ -2942,13 +3239,136 @@
       PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
       return (0);

-    case WM_KEYUP:
+    case WM_SYSCOMMAND:
+      //printf("WM_SYSCOMMAND, wpar=%x, lpar=%x\n", wParam, lParam); fflush(stdout);
+      goto dflt;
     case WM_SYSKEYUP:
+    case WM_KEYUP:
+/*       b_was_menu_pending = b_menu_pending; */
+/*           if (b_was_menu_pending) { */
+/*             HWND hwndIn = hwnd; */
+/*             UINT msgIn  = msg; */
+/*             WPARAM wParamIn = wParam; */
+/*             LPARAM lParamIn = lParam; */
+/*             //b_menu_pending = FALSE; */
+/*             printf("sending WM_SYSCOMMAND, hwnd=%d, menu=%d\n", hwnd, GetMenu(hwnd)); fflush(stdout); */
+/*             SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); */
+/*             PostMessage (hwndIn, msgIn, wParamIn, lParamIn); */
+/*             return 0; */
+/*           } */
+
+      stick.cbSize = sizeof(STICKYKEYS);
+      if (!SystemParametersInfo(SPI_GETSTICKYKEYS, stick.cbSize, &stick, 0)) {
+        printf("error in spi: %s\n", w32_strerror(GetLastError)); fflush(stdout);
+      } else {
+        bStickyKeysOn = stick.dwFlags & SKF_STICKYKEYSON;
+      }
+      if (lParam >> 24 & 1)  bit24  = TRUE;
+/*       { */
+/*         BOOL vkmenu  = FALSE; */
+/*         BOOL vklmenu = FALSE; */
+/*         BOOL vkrmenu = FALSE; */
+/*         BOOL vklwin = FALSE; */
+/*         BOOL vkrwin = FALSE; */
+/*         BOOL vklwset = FALSE; */
+/*         BOOL vkrwset = FALSE; */
+/*         switch (wParam) { */
+/*         case VK_MENU: */
+/*           vkmenu = TRUE; */
+/*           break; */
+/*         case VK_RMENU: */
+/*           vkrmenu = TRUE; */
+/*           break; */
+/*         case VK_LMENU: */
+/*           vklmenu = TRUE; */
+/*           break; */
+/*         case VK_LWIN: */
+/*           vklwin = TRUE; */
+/*           break; */
+/*         case VK_RWIN: */
+/*           vkrwin = TRUE; */
+/*           break; */
+/*         } */
+/*         vklwset = modifier_set(VK_LWIN); */
+/*         vkrwset = modifier_set(VK_RWIN); */
+/*         //if (91 == wParam) */
+/*         //printf("WM_KUP, m=%d wp=%d lp=%x VK_M=%x VK_LM=%x VK_RM=%x VK_LW=%x 24=%x st=%d,%d\n", */
+/*         printf("  WM_KUP, m=%d wp=%d lp=%8x VK_LW=%x,%x VK_RW=%x,%x 24=%x st=%d,%d\n", */
+/*                //msg, wParam, lParam, vkmenu, vklmenu, vkrmenu, vklwin, */
+/*                msg, wParam, lParam, vklwin, vklwset, vkrwin, vkrwset, */
+/*                bit24,  */
+/*                GetKeyState(wParam), GetAsyncKeyState(wParam) */
+/*                ); fflush(stdout); */
+/*         if (wParam==8) { printf("\n"); fflush(stdout); } */
+/*       } */
+
+      /* If StickyKeys is on we need to record VK_LWIN and VK_RWIN
+         when the system sends the special key up message when
+         pressing next key. */
+      /* FIX-ME: Key state toggling works only with VK_LWIN!  The code
+         below tries to make the use of LWIN and RWIN work in Emacs
+         both when using StickyKeys and not.  When using StickyKeys
+         the keys should be "toggleable". Bit 24 seems to be useful
+         for toggling LWIN, but not for RWIN. For some reason the
+         messages sent in Windows are not the same for LWIN and RWIN.
+         I do not believe that the use of bit 24 this way is
+         documented so this part of the code might break.  In that
+         case the version without bit 24 could be used.  The only
+         thing that is lost is the possibility to toggle the state of
+         LWIN.  From a user perspective this can always be done by
+         pressing C-g since M-C-g is never bound (I hope!). */
+      //if (!((VK_LWIN == wParam || VK_RWIN ==wParam) && bStickyKeysOn))
+      if (!(((VK_LWIN == wParam && 0 == bit24) || VK_RWIN == wParam) && bStickyKeysOn))
       record_keyup (wParam, lParam);
       goto dflt;

-    case WM_KEYDOWN:
     case WM_SYSKEYDOWN:
+    case WM_KEYDOWN:
+      stick.cbSize = sizeof(STICKYKEYS);
+      if (!SystemParametersInfo(SPI_GETSTICKYKEYS, stick.cbSize, &stick, 0)) {
+        printf("error in spi: %s\n", w32_strerror(GetLastError)); fflush(stdout);
+      } else {
+        bStickyKeysOn = stick.dwFlags & SKF_STICKYKEYSON;
+      }
+      if (lParam >> 24 & 1)  bit24  = TRUE;
+
+/*       { */
+/*         BOOL vkmenu  = FALSE; */
+/*         BOOL vklmenu = FALSE; */
+/*         BOOL vkrmenu = FALSE; */
+/*         BOOL vklwin = FALSE; */
+/*         BOOL vkrwin = FALSE; */
+/*         BOOL vklwset = FALSE; */
+/*         BOOL vkrwset = FALSE; */
+/*         switch (wParam) { */
+/*         case VK_MENU: */
+/*           vkmenu = TRUE; */
+/*           break; */
+/*         case VK_RMENU: */
+/*           vkrmenu = TRUE; */
+/*           break; */
+/*         case VK_LMENU: */
+/*           vklmenu = TRUE; */
+/*           break; */
+/*         case VK_LWIN: */
+/*           vklwin = TRUE; */
+/*           break; */
+/*         case VK_RWIN: */
+/*           vkrwin = TRUE; */
+/*           break; */
+/*         } */
+/*         vklwset = modifier_set(VK_LWIN); */
+/*         vkrwset = modifier_set(VK_RWIN); */
+/*         if (lParam >> 24 & 1)  bit24  = TRUE; */
+/*         //if (91 == wParam) */
+/*         //printf("WM_DWN m=%d w=%d lp=%x VK_M=%x VK_LM=%x VK_RM=%x VK_LW=%x B24=%x 29=%d BS=%x, s=%d,%d sy=%d\n", */
+/*         printf("WM_DWN, m=%d wp=%d lp=%10x VK_LW=%x,%x VK_RW=%x,%x 24=%x st=%d,%d\n", */
+/*                msg, wParam, lParam, vklwin, vklwset, vkrwin, vkrwset, */
+/*                bit24,  */
+/*                GetKeyState(wParam), GetAsyncKeyState(wParam) */
+/*                ); fflush(stdout); */
+/*       } */
+
       /* Ignore keystrokes we fake ourself; see below.  */
       if (dpyinfo->faked_key == wParam)
        {
@@ -2957,7 +3377,7 @@
             they don't produce WM_CHAR messages).  This ensures that
             indicator lights are toggled promptly on Windows 9x, for
             example.  */
-         if (wParam < 256 && lispy_function_keys[wParam])
+          if (lispy_function_keys[wParam] != 0)
            {
              windows_translate = 1;
              goto translate;
@@ -2966,6 +3386,8 @@
        }

       /* Synchronize modifiers with current keystroke.  */
+      b_was_menu_pending = b_menu_pending;
+      b_menu_pending = FALSE;
       sync_modifiers ();
       record_keydown (wParam, lParam);
       wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
@@ -2975,11 +3397,13 @@
       switch (wParam)
        {
        case VK_LWIN:
+          if (NULL == hLowKBhookW) {
          if (NILP (Vw32_pass_lwindow_to_system))
            {
              /* Prevent system from acting on keyup (which opens the
                 Start menu if no other key was pressed) by simulating a
                 press of Space which we will ignore.  */
+                //printf("Sending 255 to prevent\n"); fflush(stdout);
              if (GetAsyncKeyState (wParam) & 1)
                {
                  if (NUMBERP (Vw32_phantom_key_code))
@@ -2990,10 +3414,13 @@
                  keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
                }
            }
-         if (!NILP (Vw32_lwindow_modifier))
-           return 0;
+          } else {
+            //printf("Avoided sending 255 to prevent\n"); fflush(stdout);
+          }
+          if (!NILP (Vw32_lwindow_modifier)) return 0;
          break;
        case VK_RWIN:
+          if (NULL == hLowKBhookW) {
          if (NILP (Vw32_pass_rwindow_to_system))
            {
              if (GetAsyncKeyState (wParam) & 1)
@@ -3006,8 +3433,8 @@
                  keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
                }
            }
-         if (!NILP (Vw32_rwindow_modifier))
-           return 0;
+          }
+          if (!NILP (Vw32_rwindow_modifier)) return 0;
          break;
        case VK_APPS:
          if (!NILP (Vw32_apps_modifier))
@@ -3018,6 +3445,11 @@
            /* Prevent DefWindowProc from activating the menu bar if an
                Alt key is pressed and released by itself.  */
            return 0;
+          /* By not testing for StickyKeysOn here we get the advantage
+             that holding down Alt and then typing a letter can open
+             the menu. This seems to be the way other apps behave on
+             w32. */
+          b_menu_pending = TRUE;
          windows_translate = 1;
          break;
        case VK_CAPITAL:
@@ -3078,8 +3510,26 @@
            wParam = VK_NUMLOCK;
          break;
        default:
+          if (b_was_menu_pending) {
+            /* FIX-ME: Where should this go? Should it go to the
+               WM_CHAR section where the translated WM_KEY... returns?
+               (Remember to move b_was_menu_pending too!) */
+            HWND hwndIn = hwnd;
+            UINT msgIn  = msg;
+            WPARAM wParamIn = wParam;
+            LPARAM lParamIn = lParam;
+            b_menu_pending = FALSE;
+
+            if(!(modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))) {
+              //printf("sending WM_SYSCOMMAND, hwnd=%d, menu=%d\n", hwnd, GetMenu(hwnd)); fflush(stdout);
+              SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, wParam);
+              return 0;
+            } else {
+              //printf("... no menu, was AltGr...\n"); fflush(stdout);
+            }
+          }
          /* If not defined as a function key, change it to a WM_CHAR message. */
-         if (wParam > 255 || !lispy_function_keys[wParam])
+          if (lispy_function_keys[wParam] == 0)
            {
              DWORD modifiers = construct_console_modifiers ();

@@ -3441,6 +3891,9 @@
       goto dflt;

     case WM_INITMENU:
+      //printf("WM_INITMENU in w32fns.c, hwnd=%d, wParam=%d\n", hwnd, wParam); fflush(stdout);
+      //printf("resetting menu_pending 1\n"); fflush(stdout);
+      b_menu_pending = FALSE;
       button_state = 0;
       ReleaseCapture ();
       /* We must ensure menu bar is fully constructed and up to date
@@ -3478,9 +3931,25 @@
        if (find_deferred_msg (hwnd, msg) != NULL)
          abort ();

+        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+        {
+          MSG msg;
+          /* Use PeekMessage to avoid blocking infinitely. 2 sec max
+             (this an arbitrary choice). 40 ms is choosen to be as
+             long as possible but still short enough to be
+             "invisible". */
+          // FIX-ME: maybe check for C-g in the loop!
+          int i;
+          for (i = 1; i < 50; i++) {
+            if (PeekMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE, PM_REMOVE)) break;
+            Sleep(40);
+          }
+        }
         menubar_in_use = 1;

-       return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
+        //return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
+
+        return 0;
       }

     case WM_EXITMENULOOP:
@@ -3669,10 +4138,21 @@
       return 0;

     case WM_CLOSE:
+      //printf("w32_wnd_proc WM_CLOSE\n"); fflush(stdout);
       wmsg.dwModifiers = w32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       return 0;

+    case WM_QUERYENDSESSION:
+      //case WM_ENDSESSION:
+      // I do not think this should happen but I am not sure.
+      {
+        W32Msg wmsg;
+        //printf("w32_wnd_proc: WM_QUERYENDSESSION\n"); fflush(stdout);
+        my_post_msg (&wmsg, 0, WM_EMACS_KILL, 0, 0);
+      }
+      return 0;
+
     case WM_WINDOWPOSCHANGING:
       /* Don't restrict the sizing of tip frames.  */
       if (hwnd == tip_window)
@@ -3726,15 +4206,17 @@
                   However for top/left sizing we will need to fix the X
                   and Y positions as well.  */

+
+                if (wp.showCmd != SW_SHOWMAXIMIZED
+                    && (lppos->flags & SWP_NOMOVE) == 0)
+                  {
+/*                     lppos->cx -= wdiff; */
+/*                     lppos->cy -= hdiff; */
                int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK);
                int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK);

                lppos->cx = max (lppos->cx - wdiff, cx_mintrack);
                lppos->cy = max (lppos->cy - hdiff, cy_mintrack);
-
-               if (wp.showCmd != SW_SHOWMAXIMIZED
-                   && (lppos->flags & SWP_NOMOVE) == 0)
-                 {
                    if (lppos->x != wr.left || lppos->y != wr.top)
                      {
                        lppos->x += wdiff;
@@ -3810,9 +4292,15 @@
     case WM_EMACS_SETWINDOWPOS:
       {
        WINDOWPOS * pos = (WINDOWPOS *) wParam;
+        if (IsZoomed(hwnd)) {
+          return SetWindowPos (hwnd, pos->hwndInsertAfter,
+                               pos->x, pos->y, pos->cx, pos->cy,
+                               pos->flags | SWP_NOMOVE | SWP_NOSIZE);
+        } else {
        return SetWindowPos (hwnd, pos->hwndInsertAfter,
                             pos->x, pos->y, pos->cx, pos->cy, pos->flags);
       }
+      }

     case WM_EMACS_DESTROYWINDOW:
       DragAcceptFiles ((HWND) wParam, FALSE);
@@ -8242,6 +8730,42 @@
   return HOTKEY (vk_code, w32_modifiers);
 }

+DEFUN ("w32-wh-keyboard-ll", Fw32_wh_keyboard_ll,
+       Sw32_wh_keyboard_ll, 1, 1, 0,
+       doc: /* Activate/deactivate Emacs low level keyboard hook.
+A low level Windows keyboard hook must be used to trap keys that other
+applications have registered as hot keys.  If ON is non-nil Emacs low
+level keyboard hook is activated, if ON is nil it is deactivated.
+
+The keys that can be trapped are the left and right windows
+keys. Beware that these are not present on all keyboards.  If
+`w32-pass-lwindow-to-system' and `w32-pass-rwindow-to-system' are nil
+these keys will not be sent to the application that has registered
+them as hot keys if Emacs low level keyboard hook as active.
+
+You should normally not call this function directly.  Use
+`w32-meta-style' instead.  */)
+  (on)
+     Lisp_Object on;
+{
+/*   if (EQ (Vwindow_system, intern ("w32"))) */
+/*   if (EQ (Vwindow_system_version, intern ("w32"))) */
+/*     { */
+      DWORD wp = 1;
+      MSG msg;
+      if (NILP(on)) wp = 0;
+      if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_KBD_LL, (WPARAM) wp, 0))
+        abort();
+      GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
+      if (msg.wParam == 0) return Qnil;
+      return Qt;
+/*     } */
+/*   else */
+/*     { */
+/*       return Qnil; */
+/*     } */
+}
+
 DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
        Sw32_register_hot_key, 1, 1, 0,
        doc: /* Register KEY as a hot-key combination.
@@ -9050,6 +9574,7 @@
   defsubr (&Sw32_load_color_file);
   defsubr (&Sw32_send_sys_command);
   defsubr (&Sw32_shell_execute);
+  defsubr (&Sw32_wh_keyboard_ll);
   defsubr (&Sw32_register_hot_key);
   defsubr (&Sw32_unregister_hot_key);
   defsubr (&Sw32_registered_hot_keys);
Index: src/w32menu.c
===================================================================
RCS file: /sources/emacs/emacs/src/w32menu.c,v
retrieving revision 1.94
diff -u -b -r1.94 w32menu.c
--- src/w32menu.c       17 Oct 2007 23:43:50 -0000      1.94
+++ src/w32menu.c       4 Jan 2008 23:56:04 -0000
@@ -2291,8 +2291,7 @@
           /* With UTF-8, & cannot be part of a multibyte character.  */
           for (p = out_string; *p; p++)
             {
-              if (*p == '&')
-                nlen++;
+              // if (*p == '&') nlen++;
             }
         }
       else
Index: src/w32term.h
===================================================================
RCS file: /sources/emacs/emacs/src/w32term.h,v
retrieving revision 1.75
diff -u -b -r1.75 w32term.h
--- src/w32term.h       30 Nov 2007 13:57:46 -0000      1.75
+++ src/w32term.h       5 Jan 2008 19:59:46 -0000
@@ -641,7 +641,8 @@
 #define WM_EMACS_SHOW_CARET            (WM_EMACS_START + 17)
 #define WM_EMACS_HIDE_CARET            (WM_EMACS_START + 18)
 #define WM_EMACS_SETCURSOR             (WM_EMACS_START + 19)
-#define WM_EMACS_END                   (WM_EMACS_START + 20)
+#define WM_EMACS_KBD_LL                (WM_EMACS_START + 20)
+#define WM_EMACS_END                   (WM_EMACS_START + 21)

 #define WND_FONTWIDTH_INDEX    (0)
 #define WND_LINEHEIGHT_INDEX   (4)

[-- Attachment #3: w32-meta.el --]
[-- Type: text/plain, Size: 5024 bytes --]

;;; w32-meta.el --- Handling of Alt and Windows keys

;; Copyright (C) 2005, 2006, 2007 by Lennart Borgman

;; Author:     Lennart Borgman <lennart DOT borgman DOT 073 AT student DOT lu DOT se>
;; Created: 2005-07-30
;; Version: 0.50
;; Last-Updated: Tue Oct 30 18:29:33 2007 (3600 +0100)
;; Keywords: w32 keyboard


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;;
;; This files requires that Emacs has the function
;; `w32-wh-keyboard-ll'. This is not yet part of Emacs but is included
;; in the patched Emacs available on EmacsW32 home page.
;;
;; This file makes it simple to setup the left and right windows keys
;; for use as meta and the Alt key for use by the menus.
;; For more info see `w32-meta-style'.
;;
;; Usage:
;;
;;    (require 'w32-meta)


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; History:
;;


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This file is not part of Emacs
;;
;; 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, 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.
;;
;; To find out more about the GNU General Public License you can visit
;; Free Software Foundation's website http://www.fsf.org/.  Or, write
;; to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:


(defun w32-meta-set-w32-style (lwindow-meta rwindow-meta)
  "Setup Emacs to feel more familiar to an MS Windows user.
Alt will be used for the menus.  If LWINDOW-META is non-nil then
the left Windows keyboard key will not be passed to MS Windows.
Instead it will be used as Meta in Emacs.  The same applies to
RWINDOW-META.

You can set this through custom with the variable
`w32-meta-style'.  See also `w32-meta-set-emacs-style'.

This is an high level interface to `w32-wh-keyboard-ll',
`w32-pass-lwindow-to-system', `w32-pass-rwindow-to-system',
`w32-pass-alt-to-system' and `w32-alt-is-meta'.

The `w32-wh-keyboard-ll' is not called unless `window-system' is
'w32."
  (interactive (list (y-or-n-p "Use left Windows key (lwindow) as Meta? ")
                     (y-or-n-p "Use right Windows key (rwindow) as Meta? ")))
  (and (eq window-system 'w32)
       (or lwindow-meta
           rwindow-meta)
       (unless (w32-wh-keyboard-ll t)
         (error "w32-wh-keyboard-ll failed add")))
  (when lwindow-meta
    ;;(global-set-key [(lwindow)] 'ESC-prefix)
    (setq w32-lwindow-modifier 'meta)
    (setq w32-pass-lwindow-to-system nil))
  (when rwindow-meta
    ;;(global-set-key [(rwindow)] 'ESC-prefix)
    (setq w32-rwindow-modifier 'meta)
    (setq w32-pass-rwindow-to-system nil))
  (setq w32-pass-alt-to-system t)
  (setq w32-alt-is-meta nil))

(defun w32-meta-set-emacs-style ()
  "Setup Emacs to be more familiar to a non MS Windows user.
Alt will be used for Emacs Meta.  <lwindow> and <rwindow> will be
passed to MS Windows.

See also `w32-meta-set-w32-style'."
  (interactive)
  (when (eq window-system 'w32)
    (unless (w32-wh-keyboard-ll nil)
      (error "w32-wh-keyboard-ll failed remove")))
  (global-set-key [(lwindow)] 'ignore)
  (global-set-key [(rwindow)] 'ignore)
  (setq w32-pass-lwindow-to-system t)
  (setq w32-pass-rwindow-to-system t)
  (setq w32-lwindow-modifier nil)
  (setq w32-rwindow-modifier nil)
  (setq w32-pass-alt-to-system nil)
  (setq w32-alt-is-meta t))


(defcustom w32-meta-style 'emacs
  "Defines how Emacs treats Alt, left and right Windows keys.
For more info see function `w32-meta-set-w32-style'."
  :group 'w32
  :type '(choice
          (const :tag "Emacs default Alt handling+Windows keys default handling" emacs)
          (const :tag "MS Windows default Alt handling+left and right Windows key as Meta" w32-lr)
          (const :tag "MS Windows default Alt handling+left Windows key as Meta" w32-l)
          (const :tag "MS Windows default Alt handling+right Windows key as Meta" w32-r)
          (const :tag "MS Windows default Alt handling" w32))
  :set (lambda (symbol value)
         (unless (memq value '(emacs w32-lr w32-l w32-r w32))
           (error "Bad value to w32-meta-style"))
         (set-default symbol value)
         (cond
           ((eq value 'emacs) (w32-meta-set-emacs-style))
           ((eq value 'w32-lr) (w32-meta-set-w32-style t t))
           ((eq value 'w32-l)  (w32-meta-set-w32-style t nil))
           ((eq value 'w32-r)  (w32-meta-set-w32-style nil t))
           ((eq value 'w32)    (w32-meta-set-w32-style nil nil)))))


;;(w32-meta-set-w32-style t nil)

(provide 'w32-meta)

;;; w32-meta.el ends here

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using windows keys for Emacs META on w32
  2008-01-05 20:48 Using windows keys for Emacs META on w32 Lennart Borgman (gmail)
@ 2008-01-23 16:14 ` Jason Rumney
  2008-01-23 16:37   ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 6+ messages in thread
From: Jason Rumney @ 2008-01-23 16:14 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Emacs Devel

Lennart Borgman (gmail) wrote:
> I promised Juanma to make a new patch with the changes I have made to 
> allow using the windows left and/or right keys for Emacs meta. Here it 
> is, in a bit rough state.

This arrived when I was on holiday, so I did not comment at the time, 
but if you want us to review your patch, you should first fix the "rough 
state".

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using windows keys for Emacs META on w32
  2008-01-23 16:14 ` Jason Rumney
@ 2008-01-23 16:37   ` Lennart Borgman (gmail)
  2008-01-23 21:06     ` Juanma Barranquero
  0 siblings, 1 reply; 6+ messages in thread
From: Lennart Borgman (gmail) @ 2008-01-23 16:37 UTC (permalink / raw)
  To: Jason Rumney; +Cc: Emacs Devel

Jason Rumney wrote:
> Lennart Borgman (gmail) wrote:
>> I promised Juanma to make a new patch with the changes I have made to 
>> allow using the windows left and/or right keys for Emacs meta. Here it 
>> is, in a bit rough state.
> 
> This arrived when I was on holiday, so I did not comment at the time, 
> but if you want us to review your patch, you should first fix the "rough 
> state".

I will try to. In fact there was a bug in the patch I sent, but since no 
one has said something about it I guess no one has tested it.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using windows keys for Emacs META on w32
  2008-01-23 16:37   ` Lennart Borgman (gmail)
@ 2008-01-23 21:06     ` Juanma Barranquero
  2008-01-23 21:48       ` Jason Rumney
  2008-01-23 22:10       ` Lennart Borgman (gmail)
  0 siblings, 2 replies; 6+ messages in thread
From: Juanma Barranquero @ 2008-01-23 21:06 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Emacs Devel, Jason Rumney

On Jan 23, 2008 5:37 PM, Lennart Borgman (gmail)
<lennart.borgman@gmail.com> wrote:

> I will try to. In fact there was a bug in the patch I sent, but since no
> one has said something about it I guess no one has tested it.

I was planning to do it, but I agree that fixing the "rough state" is
a good idea.

I must say, though, that it seems too complicate a patch for such a
small benefit. Or I don't understand what you're trying to do (that's
another distinct possibility :)

             Juanma

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using windows keys for Emacs META on w32
  2008-01-23 21:06     ` Juanma Barranquero
@ 2008-01-23 21:48       ` Jason Rumney
  2008-01-23 22:10       ` Lennart Borgman (gmail)
  1 sibling, 0 replies; 6+ messages in thread
From: Jason Rumney @ 2008-01-23 21:48 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: Lennart Borgman (gmail), Emacs Devel

Juanma Barranquero wrote:
> I must say, though, that it seems too complicate a patch for such a
> small benefit. Or I don't understand what you're trying to do (that's
> another distinct possibility :)
>   

That was a previous objection when we were preparing to release Emacs 
22.1. Now we have time to sort out any breakage that complexity might 
bring, so I'm not so worried about that. The complexity is necessary 
because Windows makes it hard to wrestle back control over a few 
keybindings from Windows itself. The current patch may look more complex 
than it really is because of the "rough state", which consists of 
commented out debugging code, much of which seems unrelated to the 
keyboard changes.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Using windows keys for Emacs META on w32
  2008-01-23 21:06     ` Juanma Barranquero
  2008-01-23 21:48       ` Jason Rumney
@ 2008-01-23 22:10       ` Lennart Borgman (gmail)
  1 sibling, 0 replies; 6+ messages in thread
From: Lennart Borgman (gmail) @ 2008-01-23 22:10 UTC (permalink / raw)
  To: Juanma Barranquero; +Cc: Emacs Devel, Jason Rumney

Juanma Barranquero wrote:
> On Jan 23, 2008 5:37 PM, Lennart Borgman (gmail)
> <lennart.borgman@gmail.com> wrote:
> 
>> I will try to. In fact there was a bug in the patch I sent, but since no
>> one has said something about it I guess no one has tested it.
> 
> I was planning to do it, but I agree that fixing the "rough state" is
> a good idea.

Thanks anyway.

> I must say, though, that it seems too complicate a patch for such a
> small benefit. Or I don't understand what you're trying to do (that's
> another distinct possibility :)


I do not know if it is complicated by itself. The low level keyboard 
hook, which is the heart of the patch, is very straight forward. Then I 
tried to follow the same structure as was used before in the w32 message 
handling. (BTW that really made me wish that the different threads, GUI 
and main, were marked in the source.)

But after that I discovered that there was a bug in the menu handling 
that could result in what you typed to open a menu could go to the 
buffer instead. You do not notice that bug unless you let windows handle 
the Alt key completely.

After this there was the bug in accessibility sticky keys handling.

The patch also makes the handling of caps/num lock a little bit better 
(though I do not know the consequences of this).

But the main gains are of course:

- Beeing able to use the Alt for menus (required by some accessibility 
guidelines if I remember correctly).
- Using M-Tab for completion

Can't remember if it was anything more now. Eh, yes, I remember one 
little thing more: Beeing able to have a meta key at all if you want to 
use Alt for the menus - and you use Viper ...

I also have a little file to easily change the setting of META (lwindow, 
rwindow or alt).

What I want to is get rid of the patches. It is unnecessary work to have 
them outside of core Emacs and they would be useful IMO in Emacs.

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-01-23 22:10 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-05 20:48 Using windows keys for Emacs META on w32 Lennart Borgman (gmail)
2008-01-23 16:14 ` Jason Rumney
2008-01-23 16:37   ` Lennart Borgman (gmail)
2008-01-23 21:06     ` Juanma Barranquero
2008-01-23 21:48       ` Jason Rumney
2008-01-23 22:10       ` Lennart Borgman (gmail)

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).