]> code.delx.au - gnu-emacs/commitdiff
Initial version of the w32notify code.
authorEli Zaretskii <eliz@gnu.org>
Sat, 6 Oct 2012 18:02:31 +0000 (20:02 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sat, 6 Oct 2012 18:02:31 +0000 (20:02 +0200)
Adding and removing a watch seems to work: a new thread is launched
when a watch is added and exits when the watch is removed.
But there are no notifications, so it seems.  At least, the Lisp
callback function passed to w32notify-add-watch is not called.

lib-src/makefile.w32-in
lisp/subr.el
src/alloc.c
src/emacs.c
src/keyboard.c
src/lisp.h
src/makefile.w32-in
src/termhooks.h
src/w32term.c
src/w32term.h

index 23ef71de10c49f896aaf7e0cb1f63e1ee2e860ee..d53f768cfa8778c990fae74a06ae0a9f5046dde5 100644 (file)
@@ -126,7 +126,7 @@ obj =   dosfns.o msdos.o \
        fontset.o menu.o \
        w32.o w32console.o w32fns.o w32heap.o w32inevt.o \
        w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
-       font.o w32font.o w32uniscribe.o \
+       font.o w32font.o w32uniscribe.o w32notify.o \
        dispnew.o frame.o scroll.o xdisp.o window.o bidi.o \
        charset.o coding.o category.o ccl.o character.o chartab.o \
        cm.o term.o terminal.o xfaces.o \
index 72bedc69c3cf9e380ce4e304d94586fc6c1a2db4..9b557dcfd208c37adef77b126f1b102a30f8bd77 100644 (file)
@@ -1167,6 +1167,17 @@ The return value has the form (WIDTH . HEIGHT).  POSITION should
 be a list of the form returned by `event-start' and `event-end'."
   (nth 9 position))
 
+(defun w32notify-handle-event (event)
+  "Handle file system monitoring event.
+If EVENT is a file-notification event, then its callback is called.
+Otherwise, a `filewatch-error' is signaled."
+  (interactive "e")
+
+  (if (and (eq (car event) 'file-notify)
+          (= (length event) 3))
+      (funcall (nth 2 event) (nth 1 event))
+    (signal 'filewatch-error (cons "Not a valid file-notify event" event))))
+
 \f
 ;;;; Obsolescent names for functions.
 
index 3ed8cc2d990a44043587f85747735f41657b5254..dd3a93ae019a0e68e59ef9ff28a0af4cee953251 100644 (file)
@@ -376,7 +376,7 @@ struct gcpro *gcprolist;
 /* Addresses of staticpro'd variables.  Initialize it to a nonzero
    value; otherwise some compilers put it into BSS.  */
 
-#define NSTATICS 0x650
+#define NSTATICS 0x660
 static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag};
 
 /* Index of next unused slot in staticvec.  */
index bc54f56b98a2501c77a3859f5850d90488e6ca52..65ee11fb261d57895283f8fa9c4e943f25ad00f3 100644 (file)
@@ -1417,6 +1417,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
 
 #ifdef WINDOWSNT
       syms_of_ntterm ();
+      syms_of_w32notify ();
 #endif /* WINDOWSNT */
 
       syms_of_profiler ();
index d06b02024c59f63c6482c5bc010aa0b9a61f17e9..6597ebd884b5caf017dd1bd8bbb96b2ddca4b3d8 100644 (file)
@@ -314,7 +314,7 @@ static Lisp_Object Qmouse_fixup_help_message;
 static Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
 #if defined (WINDOWSNT)
-Lisp_Object Qlanguage_change;
+Lisp_Object Qlanguage_change, Qfile_notify;
 #endif
 static Lisp_Object Qdrag_n_drop;
 static Lisp_Object Qsave_session;
@@ -3957,6 +3957,16 @@ kbd_buffer_get_event (KBOARD **kbp,
                              make_number (event->modifiers)));
          kbd_fetch_ptr = event + 1;
        }
+      else if (event->kind == FILE_NOTIFY_EVENT)
+       {
+         /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK).  */
+         obj = Fcons (Qfile_notify,
+                      list2 (list3 (event->code,
+                                    XCAR (event->arg),
+                                    CAR_SAFE (XCDR (event->arg))),
+                             event->frame_or_window));
+         kbd_fetch_ptr = event + 1;
+       }
 #endif
       else if (event->kind == SAVE_SESSION_EVENT)
         {
@@ -11396,6 +11406,7 @@ syms_of_keyboard (void)
 
 #if defined (WINDOWSNT)
   DEFSYM (Qlanguage_change, "language-change");
+  DEFSYM (Qfile_notify, "file-notify");
 #endif
 
 #ifdef HAVE_DBUS
@@ -12167,6 +12178,8 @@ keys_of_keyboard (void)
 #if defined (WINDOWSNT)
   initial_define_lispy_key (Vspecial_event_map, "language-change",
                            "ignore");
+  initial_define_lispy_key (Vspecial_event_map, "file-notify",
+                           "w32notify-handlde-event");
 #endif
 }
 
index 2a647e593a858dc48f6ae4adbd94b86c167c572e..7812e58782b146d1c794838d7c5834635ed186ea 100644 (file)
@@ -3497,6 +3497,11 @@ extern void syms_of_fontset (void);
 extern Lisp_Object Qfont_param;
 #endif
 
+#ifdef WINDOWSNT
+/* Defined on w32notify.c.  */
+extern void syms_of_w32notify (void);
+#endif
+
 /* Defined in xfaces.c.  */
 extern Lisp_Object Qdefault, Qtool_bar, Qfringe;
 extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
index c6fbf59fb5aa4e5367d1c1c4d77c477f3d973abc..f051ed6a8a9cff9c9febdf6c945033f37b8ce955 100644 (file)
@@ -134,6 +134,7 @@ OBJ2 =  $(BLD)/sysdep.$(O)          \
        $(BLD)/w32menu.$(O)             \
        $(BLD)/w32reg.$(O)              \
        $(BLD)/w32font.$(O)             \
+       $(BLD)/w32notify.$(O)           \
        $(BLD)/w32uniscribe.$(O)
 
 LIBS =  $(TLIB0)       \
@@ -209,7 +210,7 @@ GLOBAL_SOURCES =   dosfns.c msdos.c \
        fontset.c menu.c dbusbind.c \
        w32.c w32console.c w32fns.c w32heap.c w32inevt.c \
        w32menu.c w32proc.c w32reg.c w32select.c w32term.c w32xfns.c \
-       font.c w32font.c w32uniscribe.c \
+       font.c w32font.c w32uniscribe.c w32notify.c \
        dispnew.c frame.c scroll.c xdisp.c window.c bidi.c \
        charset.c coding.c category.c ccl.c character.c chartab.c \
        cm.c term.c terminal.c xfaces.c \
@@ -1673,6 +1674,17 @@ $(BLD)/w32uniscribe.$(O) : \
        $(W32FONT_H) \
        $(W32TERM_H)
 
+$(BLD)/w32notify.$(O) : \
+       $(SRC)/w32notify.c \
+       $(SRC)/w32heap.h \
+       $(CODING_H) \
+       $(CONFIG_H) \
+       $(FRAME_H) \
+       $(KEYBOARD_H) \
+       $(LISP_H) \
+       $(TERMHOOKS_H) \
+       $(W32TERM_H)
+
 # Each object file depends on stamp_BLD, because in parallel builds we must
 # make sure $(BLD) exists before starting compilations.
 #
index f35bd929af1452760cdac0c7be3d3cf528cc10f1..0afd7d97e7b9732a8b63f5384bb968d64a348f8f 100644 (file)
@@ -201,6 +201,7 @@ enum event_kind
      On X, the window manager seems to grab the keys it wants
      first, so this is not a problem there.  */
   , MULTIMEDIA_KEY_EVENT
+  , FILE_NOTIFY_EVENT
 #endif
 
 #ifdef HAVE_NS
index 1cc8bd2adefb873f8c9fc8d0fb550deb0c88480a..951ce9ef2df5e5a5c6133b32b20731cf86e56717 100644 (file)
@@ -235,6 +235,8 @@ static void x_check_font (struct frame *, struct font *);
 #endif
 
 static Lisp_Object Qvendor_specific_keysyms;
+static Lisp_Object Qadded, Qremoved, Qmodified;
+static Lisp_Object Qrenamed_from, Qrenamed_to;
 
 \f
 /***********************************************************************
@@ -3202,6 +3204,119 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
   return Qnil;
 }
 
+static Lisp_Object
+lispy_file_action (DWORD action)
+{
+  static char unknown_fmt[] = "unknown-action(%d)";
+  Lisp_Object retval;
+
+  switch (action)
+    {
+    case FILE_ACTION_ADDED:
+      retval = Qadded;
+      break;
+    case FILE_ACTION_REMOVED:
+      retval = Qremoved;
+      break;
+    case FILE_ACTION_MODIFIED:
+      retval = Qmodified;
+      break;
+    case FILE_ACTION_RENAMED_OLD_NAME:
+      retval = Qrenamed_from;
+      break;
+    case FILE_ACTION_RENAMED_NEW_NAME:
+      retval = Qrenamed_to;
+      break;
+    default:
+      {
+       char buf[sizeof(unknown_fmt) - 1 + INT_STRLEN_BOUND (DWORD)];
+
+       sprintf (buf, unknown_fmt, action);
+       retval = intern (buf);
+      }
+      break;
+    }
+
+  return retval;
+}
+
+/* Put file notifications into the Emacs input event queue.  This
+   function runs when the WM_EMACS_FILENOTIFY message arrives from a
+   watcher thread.  */
+static void
+queue_notifications (struct input_event *event, W32Msg *msg, struct frame *f,
+                    int *evcount)
+{
+  BYTE *p = file_notifications;
+  FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
+  const DWORD min_size
+    = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
+  Lisp_Object frame;
+
+  /* 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;
+    }
+
+  XSETFRAME (frame, f);
+
+  enter_crit ();
+  if (notification_buffer_in_use)
+    {
+      DWORD info_size = notifications_size;
+
+      /* 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)
+       {
+         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,
+                                               intern ("utf-16le"), 0);
+             Lisp_Object action = lispy_file_action (fni->Action);
+             Lisp_Object obj;
+
+             obj = get_watch_object (make_number (notifications_desc));
+             if (!NILP (obj) && CONSP (obj))
+               {
+                 event->kind = FILE_NOTIFY_EVENT;
+                 event->code = (ptrdiff_t)notifications_desc;
+                 event->timestamp = msg->msg.time;
+                 event->modifiers = 0;
+                 event->frame_or_window = XCDR (obj);
+                 event->arg = Fcons (action, fname);
+                 kbd_buffer_store_event (event);
+                 (*evcount)++;
+               }
+
+             if (!fni->NextEntryOffset)
+               break;
+             p += fni->NextEntryOffset;
+             fni = (PFILE_NOTIFY_INFORMATION)p;
+             info_size -= fni->NextEntryOffset;
+           }
+       }
+      notification_buffer_in_use = 0;
+    }
+  else
+    DebPrint (("We were promised notifications, but in-use flag is zero!\n"));
+  leave_crit ();
+
+  /* We've stuffed all the events ourselves, so w32_read_socket shouldn't.  */
+  event->kind = NO_EVENT;
+}
+
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -4829,6 +4944,12 @@ w32_read_socket (struct terminal *terminal,
          check_visibility = 1;
          break;
 
+       case WM_EMACS_FILENOTIFY:
+         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+         if (f)
+           queue_notifications (&inev, &msg, f, &count);
+         break;
+
        default:
          /* Check for messages registered at runtime.  */
          if (msg.msg.message == msh_mousewheel)
@@ -6494,6 +6615,12 @@ syms_of_w32term (void)
 
   DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
 
+  DEFSYM (Qadded, "added");
+  DEFSYM (Qremoved, "removed");
+  DEFSYM (Qmodified, "modified");
+  DEFSYM (Qrenamed_from, "renamed-from");
+  DEFSYM (Qrenamed_to, "renamed-to");
+
   DEFVAR_INT ("w32-num-mouse-buttons",
              w32_num_mouse_buttons,
              doc: /* Number of physical mouse buttons.  */);
index fcaccc4d624b04b2f41d8983ad968ed1d7edf009..7553745898169467aaa8c0b9089b31073a5a0dff 100644 (file)
@@ -584,7 +584,8 @@ do { \
 #define WM_EMACS_SETCURSOR             (WM_EMACS_START + 19)
 #define WM_EMACS_PAINT                 (WM_EMACS_START + 20)
 #define WM_EMACS_BRINGTOTOP            (WM_EMACS_START + 21)
-#define WM_EMACS_END                   (WM_EMACS_START + 22)
+#define WM_EMACS_FILENOTIFY            (WM_EMACS_START + 22)
+#define WM_EMACS_END                   (WM_EMACS_START + 23)
 
 #define WND_FONTWIDTH_INDEX    (0)
 #define WND_LINEHEIGHT_INDEX   (4)
@@ -642,6 +643,11 @@ extern BOOL parse_button (int, int, int *, int *);
 
 extern void w32_sys_ring_bell (struct frame *f);
 extern void x_delete_display (struct w32_display_info *dpyinfo);
+extern int notification_buffer_in_use;
+extern BYTE file_notifications[16384];
+extern DWORD notifications_size;
+extern HANDLE notifications_desc;
+extern Lisp_Object get_watch_object (Lisp_Object);
 
 /* Keypad command key support.  W32 doesn't have virtual keys defined
    for the function keys on the keypad (they are mapped to the standard