From cad8aef3241efa0873fb0c003b563cf31a4c0f2e Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 23 Sep 2015 20:34:22 +0200 Subject: [PATCH] Continue gfilenotify.c implementation of missing parts * lisp/filenotify.el (file-notify-add-watch): Append `flags' to `gfile-add-watch' call. (file-notify-rm-watch): Modify `file-notify-descriptors' only after calling the low level functions. * src/gfilenotify.c (dir_monitor_callback): Check, whether event_type is expected. (Fgfile_add_watch): Allow also `change'and `attribute-change' for FLAGS. (Fgfile_rm_watch): Fix typo. (syms_of_gfilenotify): Declare Qchange and Qattribute_change. --- lisp/filenotify.el | 34 ++++++++++++-------------- src/gfilenotify.c | 61 +++++++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/lisp/filenotify.el b/lisp/filenotify.el index e2c0af0d1b7..d48d3f94bc6 100644 --- a/lisp/filenotify.el +++ b/lisp/filenotify.el @@ -291,7 +291,7 @@ FILE is the name of the file whose event is being reported." ;; Determine respective flags. (if (eq file-notify--library 'gfilenotify) - (setq l-flags '(watch-mounts send-moved)) + (setq l-flags (append '(watch-mounts send-moved) flags)) (when (memq 'change flags) (setq l-flags @@ -330,7 +330,21 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." handler registered) (when (stringp dir) + ;; Call low-level function. (setq handler (find-file-name-handler dir 'file-notify-rm-watch)) + (condition-case nil + (if handler + ;; A file name handler could exist even if there is no + ;; local file notification support. + (funcall handler 'file-notify-rm-watch desc) + + (funcall + (cond + ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) + ((eq file-notify--library 'inotify) 'inotify-rm-watch) + ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) + desc)) + (file-notify-error nil)) ;; Modify `file-notify-descriptors'. (if (not file) @@ -341,23 +355,7 @@ DESCRIPTOR should be an object returned by `file-notify-add-watch'." (delete (assoc file (cdr registered)) (cdr registered))) (if (null (cdr registered)) (remhash desc file-notify-descriptors) - (puthash desc registered file-notify-descriptors))) - - ;; Call low-level function. - (when (null (cdr registered)) - (condition-case nil - (if handler - ;; A file name handler could exist even if there is no local - ;; file notification support. - (funcall handler 'file-notify-rm-watch desc) - - (funcall - (cond - ((eq file-notify--library 'gfilenotify) 'gfile-rm-watch) - ((eq file-notify--library 'inotify) 'inotify-rm-watch) - ((eq file-notify--library 'w32notify) 'w32notify-rm-watch)) - desc)) - (file-notify-error nil)))))) + (puthash desc registered file-notify-descriptors)))))) (defun file-notify-valid-p (descriptor) "Check a watch specified by its DESCRIPTOR. diff --git a/src/gfilenotify.c b/src/gfilenotify.c index 1439666f5f8..b5baa30d7a4 100644 --- a/src/gfilenotify.c +++ b/src/gfilenotify.c @@ -29,7 +29,7 @@ along with GNU Emacs. If not, see . */ #include "process.h" -/* This is a list, elements are triples (DESCRIPTOR FILE CALLBACK) */ +/* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */ static Lisp_Object watch_list; /* This is the callback function for arriving signals from @@ -42,7 +42,7 @@ dir_monitor_callback (GFileMonitor *monitor, GFileMonitorEvent event_type, gpointer user_data) { - Lisp_Object symbol, monitor_object, watch_object; + Lisp_Object symbol, monitor_object, watch_object, flags; char *name = g_file_get_parse_name (file); char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; @@ -84,26 +84,35 @@ dir_monitor_callback (GFileMonitor *monitor, if (CONSP (watch_object)) { - /* Construct an event. */ struct input_event event; Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil; - EVENT_INIT (event); - event.kind = FILE_NOTIFY_EVENT; - event.frame_or_window = Qnil; - event.arg = list2 (Fcons (monitor_object, - Fcons (symbol, - Fcons (build_string (name), - otail))), - XCAR (XCDR (XCDR (watch_object)))); - - /* Store it into the input event queue. */ - kbd_buffer_store_event (&event); + + /* Check, whether event_type is expected. */ + flags = XCAR (XCDR (XCDR (watch_object))); + if ((!NILP (Fmember (Qchange, flags)) && + !NILP (Fmember (symbol, list5 (Qchanged, Qchanges_done_hint, + Qdeleted, Qcreated, Qmoved)))) || + (!NILP (Fmember (Qattribute_change, flags)) && + ((EQ (symbol, Qattribute_changed))))) + { + /* Construct an event. */ + EVENT_INIT (event); + event.kind = FILE_NOTIFY_EVENT; + event.frame_or_window = Qnil; + event.arg = list2 (Fcons (monitor_object, + Fcons (symbol, + Fcons (build_string (name), + otail))), + XCAR (XCDR (XCDR (XCDR (watch_object))))); + + /* Store it into the input event queue. */ + kbd_buffer_store_event (&event); + // XD_DEBUG_MESSAGE ("%s", XD_OBJECT_TO_STRING (event.arg)); + } /* Cancel monitor if file or directory is deleted. */ - if (((event_type == G_FILE_MONITOR_EVENT_DELETED) || - (event_type == G_FILE_MONITOR_EVENT_MOVED)) && - (strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0) && - (!g_file_monitor_is_cancelled (monitor))) + if (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved))) && + !g_file_monitor_is_cancelled (monitor)) g_file_monitor_cancel (monitor); } @@ -127,9 +136,13 @@ watched for some reason, this function signals a `file-notify-error' error. FLAGS is a list of conditions to set what will be watched for. It can include the following symbols: - `watch-mounts' -- watch for mount events - `send-moved' -- pair `deleted' and `created' events caused by file - renames and send a single `renamed' event instead + `change' -- watch for file changes + `attribute-change' -- watch for file attributes changes, like + permissions or modification time + `watch-mounts' -- watch for mount events + `send-moved' -- pair `deleted' and `created' events caused by + file renames and send a single `renamed' event + instead When any event happens, Emacs will call the CALLBACK function passing it a single argument EVENT, which is of the form @@ -206,13 +219,13 @@ will be reported only in case of the `moved' event. */) (GCallback) dir_monitor_callback, NULL); /* Store watch object in watch list. */ - watch_object = list3 (watch_descriptor, file, callback); + watch_object = list4 (watch_descriptor, file, flags, callback); watch_list = Fcons (watch_object, watch_list); return watch_descriptor; } -DEFUN ("gfile-rm-watc", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, +DEFUN ("gfile-rm-watch", Fgfile_rm_watch, Sgfile_rm_watch, 1, 1, 0, doc: /* Remove an existing WATCH-DESCRIPTOR. WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'. */) @@ -279,6 +292,8 @@ syms_of_gfilenotify (void) defsubr (&Sgfile_valid_p); /* Filter objects. */ + DEFSYM (Qchange, "change"); + DEFSYM (Qattribute_change, "attribute-change"); DEFSYM (Qwatch_mounts, "watch-mounts"); /* G_FILE_MONITOR_WATCH_MOUNTS */ DEFSYM (Qsend_moved, "send-moved"); /* G_FILE_MONITOR_SEND_MOVED */ -- 2.39.2