]> code.delx.au - gnu-emacs/blobdiff - src/w32inevt.c
Fix an error in Tramp for rsync
[gnu-emacs] / src / w32inevt.c
index 54b0b13f54e0d859efd2b48c1c2ab08f784b2d99..2269d318051c9819725eac2b8cfa768dea0f33f9 100644 (file)
@@ -6,8 +6,8 @@ This file is part of GNU Emacs.
 
 GNU Emacs 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 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -41,6 +41,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "termchar.h"  /* for Mouse_HLInfo, tty_display_info */
 #include "w32term.h"
 #include "w32inevt.h"
+#include "w32common.h"
 
 /* stdin, from w32console.c */
 extern HANDLE keyboard_handle;
@@ -148,10 +149,12 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
       switch (event->wVirtualKeyCode)
        {
        case VK_LWIN:
-         mod_key_state &= ~LEFT_WIN_PRESSED;
+          if (!w32_kbdhook_active)
+            mod_key_state &= ~LEFT_WIN_PRESSED;
          break;
        case VK_RWIN:
-         mod_key_state &= ~RIGHT_WIN_PRESSED;
+          if (!w32_kbdhook_active)
+            mod_key_state &= ~RIGHT_WIN_PRESSED;
          break;
        case VK_APPS:
          mod_key_state &= ~APPS_PRESSED;
@@ -185,7 +188,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
              keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
            }
        }
-      mod_key_state |= LEFT_WIN_PRESSED;
+      if (!w32_kbdhook_active)
+        mod_key_state |= LEFT_WIN_PRESSED;
       if (!NILP (Vw32_lwindow_modifier))
        return 0;
       break;
@@ -201,7 +205,8 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
              keybd_event (faked_key, (BYTE) MapVirtualKey (faked_key, 0), 0, 0);
            }
        }
-      mod_key_state |= RIGHT_WIN_PRESSED;
+      if (!w32_kbdhook_active)
+        mod_key_state |= RIGHT_WIN_PRESSED;
       if (!NILP (Vw32_rwindow_modifier))
        return 0;
       break;
@@ -267,6 +272,13 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 
   /* Recognize state of Windows and Apps keys.  */
   event->dwControlKeyState |= mod_key_state;
+  if (w32_kbdhook_active)
+    {
+      if (check_w32_winkey_state (VK_LWIN))
+        event->dwControlKeyState |= LEFT_WIN_PRESSED;
+      if (check_w32_winkey_state (VK_RWIN))
+        event->dwControlKeyState |= RIGHT_WIN_PRESSED;
+    }
 
   /* Distinguish numeric keypad keys from extended keys.  */
   event->wVirtualKeyCode =
@@ -608,69 +620,89 @@ maybe_generate_resize_event (void)
 int
 handle_file_notifications (struct input_event *hold_quit)
 {
-  BYTE *p = file_notifications;
-  FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
-  const DWORD min_size
-    = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
-  struct input_event inev;
+  struct notifications_set *ns = NULL;
   int nevents = 0;
+  int done = 0;
 
   /* We cannot process notification before Emacs is fully initialized,
      since we need the UTF-16LE coding-system to be set up.  */
   if (!initialized)
     {
-      notification_buffer_in_use = 0;
       return nevents;
     }
 
-  enter_crit ();
-  if (notification_buffer_in_use)
+  while (!done)
     {
-      DWORD info_size = notifications_size;
-      Lisp_Object cs = Qutf_16le;
-      Lisp_Object obj = w32_get_watch_object (notifications_desc);
-
-      /* notifications_size could be zero when the buffer of
-        notifications overflowed on the OS level, or when the
-        directory being watched was itself deleted.  Do nothing in
-        that case.  */
-      if (info_size
-         && !NILP (obj) && CONSP (obj))
-       {
-         Lisp_Object callback = XCDR (obj);
+      ns = NULL;
 
-         EVENT_INIT (inev);
+      /* Find out if there is a record available in the linked list of
+        notifications sets.  If so, unlink te set from the linked list.
+        Use the critical section.  */
+      enter_crit ();
+      if (notifications_set_head->next != notifications_set_head)
+       {
+         ns = notifications_set_head->next;
+         ns->prev->next = ns->next;
+         ns->next->prev = ns->prev;
+       }
+      else
+       done = 1;
+      leave_crit();
 
-         while (info_size >= min_size)
+      if (ns)
+       {
+         BYTE *p = ns->notifications;
+         FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+         const DWORD min_size
+           = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+         struct input_event inev;
+         DWORD info_size = ns->size;
+         Lisp_Object cs = Qutf_16le;
+         Lisp_Object obj = w32_get_watch_object (ns->desc);
+
+         /* notifications size could be zero when the buffer of
+            notifications overflowed on the OS level, or when the
+            directory being watched was itself deleted.  Do nothing in
+            that case.  */
+         if (info_size
+             && !NILP (obj) && CONSP (obj))
            {
-             Lisp_Object utf_16_fn
-               = make_unibyte_string ((char *)fni->FileName,
-                                      fni->FileNameLength);
-             /* Note: mule-conf is preloaded, so utf-16le must
-                already be defined at this point.  */
-             Lisp_Object fname
-               = code_convert_string_norecord (utf_16_fn, cs, 0);
-             Lisp_Object action = lispy_file_action (fni->Action);
-
-             inev.kind = FILE_NOTIFY_EVENT;
-             inev.timestamp = GetTickCount ();
-             inev.modifiers = 0;
-             inev.frame_or_window = callback;
-             inev.arg = Fcons (action, fname);
-             inev.arg = list3 (make_pointer_integer (notifications_desc),
-                               action, fname);
-             kbd_buffer_store_event_hold (&inev, hold_quit);
-
-             if (!fni->NextEntryOffset)
-               break;
-             p += fni->NextEntryOffset;
-             fni = (PFILE_NOTIFY_INFORMATION)p;
-             info_size -= fni->NextEntryOffset;
+             Lisp_Object callback = XCDR (obj);
+
+             EVENT_INIT (inev);
+
+             while (info_size >= min_size)
+               {
+                 Lisp_Object utf_16_fn
+                   = make_unibyte_string ((char *)fni->FileName,
+                                          fni->FileNameLength);
+                 /* Note: mule-conf is preloaded, so utf-16le must
+                    already be defined at this point.  */
+                 Lisp_Object fname
+                   = code_convert_string_norecord (utf_16_fn, cs, 0);
+                 Lisp_Object action = lispy_file_action (fni->Action);
+
+                 inev.kind = FILE_NOTIFY_EVENT;
+                 inev.timestamp = GetTickCount ();
+                 inev.modifiers = 0;
+                 inev.frame_or_window = callback;
+                 inev.arg = Fcons (action, fname);
+                 inev.arg = list3 (make_pointer_integer (ns->desc),
+                                   action, fname);
+                 kbd_buffer_store_event_hold (&inev, hold_quit);
+                 nevents++;
+                 if (!fni->NextEntryOffset)
+                   break;
+                 p += fni->NextEntryOffset;
+                 fni = (PFILE_NOTIFY_INFORMATION)p;
+                 info_size -= fni->NextEntryOffset;
+               }
            }
+         /* Free this notification set.  */
+         free (ns->notifications);
+         free (ns);
        }
-      notification_buffer_in_use = 0;
     }
-  leave_crit ();
   return nevents;
 }
 #else  /* !HAVE_W32NOTIFY */