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 \
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.
/* 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. */
#ifdef WINDOWSNT
syms_of_ntterm ();
+ syms_of_w32notify ();
#endif /* WINDOWSNT */
syms_of_profiler ();
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;
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)
{
#if defined (WINDOWSNT)
DEFSYM (Qlanguage_change, "language-change");
+ DEFSYM (Qfile_notify, "file-notify");
#endif
#ifdef HAVE_DBUS
#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
}
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;
$(BLD)/w32menu.$(O) \
$(BLD)/w32reg.$(O) \
$(BLD)/w32font.$(O) \
+ $(BLD)/w32notify.$(O) \
$(BLD)/w32uniscribe.$(O)
LIBS = $(TLIB0) \
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 \
$(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.
#
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
#endif
static Lisp_Object Qvendor_specific_keysyms;
+static Lisp_Object Qadded, Qremoved, Qmodified;
+static Lisp_Object Qrenamed_from, Qrenamed_to;
\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.
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)
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. */);
#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)
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