From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michael Albinus Newsgroups: gmane.emacs.devel Subject: Re: Using glib's g_file_monitor_file and g_file_monitor_directory Date: Tue, 28 May 2013 12:39:15 +0200 Message-ID: <8738t7pewc.fsf@gmx.de> References: <87zjxxn6th.fsf@gmx.de> <87hajqpjn1.fsf@gmx.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1369737594 30358 80.91.229.3 (28 May 2013 10:39:54 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 28 May 2013 10:39:54 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue May 28 12:39:54 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UhHJo-0004PA-51 for ged-emacs-devel@m.gmane.org; Tue, 28 May 2013 12:39:52 +0200 Original-Received: from localhost ([::1]:45748 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhHJn-0003kZ-J3 for ged-emacs-devel@m.gmane.org; Tue, 28 May 2013 06:39:51 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:59078) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhHJX-0003d4-Kp for emacs-devel@gnu.org; Tue, 28 May 2013 06:39:48 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UhHJO-0003eQ-PV for emacs-devel@gnu.org; Tue, 28 May 2013 06:39:35 -0400 Original-Received: from mout.gmx.net ([212.227.15.18]:52366) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UhHJO-0003eG-AK for emacs-devel@gnu.org; Tue, 28 May 2013 06:39:26 -0400 Original-Received: from mailout-de.gmx.net ([10.1.76.10]) by mrigmx.server.lan (mrigmx002) with ESMTP (Nemesis) id 0LlKmm-1U7OrT1Dp0-00b4Ph for ; Tue, 28 May 2013 12:39:25 +0200 Original-Received: (qmail invoked by alias); 28 May 2013 10:39:21 -0000 Original-Received: from p5DCA3257.dip0.t-ipconnect.de (EHLO detlef.gmx.de) [93.202.50.87] by mail.gmx.net (mp010) with SMTP; 28 May 2013 12:39:21 +0200 X-Authenticated: #3708877 X-Provags-ID: V01U2FsdGVkX1+rJd0LzJ+rxdwzrPTmXal5ICshNC861exKvhljTW 5L9T0ElUzaoFCU In-Reply-To: (Stefan Monnier's message of "Wed, 03 Apr 2013 14:12:44 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-Y-GMX-Trusted: 0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 212.227.15.18 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:159852 Archived-At: --=-=-= Content-Type: text/plain Stefan Monnier writes: >>> What about adding this interface to Emacs, on C level? It could be in >>> parallel to, or replacing the inotify interface. > > That sounds good. AFAIK Emacs almost always links to glib indirectly > nowadays, so it would probably be OK to replace the inotify version with > the glib version. I've appended a patch which I have tested successfully under GNU/Linux. There is a new gfilenotify.c, which uses glib's functionality. There is also a new config option --with-file-notification=LIB, LIB can be "yes", "no", "gfile" or "inotify". Default on non-w32 machines is "gfile" if applicable. For w32 machines, this option is not taken into account yet, emacs undonditionally links w32notify (maybe we want also support "no" there?). Furthermore, all file notification libraries use now the same lisp event `file-notify' instead of `file-inotify' and `file-w32notify'. Changelog entries and proper documentation are not part of this patch yet. Comments on the patch are welcome. And we should also start to design an upper layer over gfilenotify.c, inotify.c and w32notify.c, which abstracts from the respective file notification events. They are very different for every library, which complicates a convenient use in other elisp packages. See the changes in autorevert.el in that patch. > Stefan Best regards, Michael. --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=bzr.diff === modified file 'autogen/config.in' --- autogen/config.in 2013-05-16 16:37:05 +0000 +++ autogen/config.in 2013-05-21 08:25:51 +0000 @@ -132,7 +132,7 @@ #if !defined _FORTIFY_SOURCE && defined __OPTIMIZE__ && __OPTIMIZE__ # define _FORTIFY_SOURCE 2 #endif - + /* Define to 1 if futimesat mishandles a NULL file name. */ #undef FUTIMESAT_NULL_BUG @@ -623,6 +623,9 @@ /* Define to 1 if you have inet sockets. */ #undef HAVE_INET_SOCKETS +/* Define to 1 to use glib's notify. */ +#undef HAVE_GFILENOTIFY + /* Define to 1 to use inotify. */ #undef HAVE_INOTIFY @@ -1836,4 +1839,3 @@ mode: c End: */ - === modified file 'configure.ac' --- configure.ac 2013-05-27 02:03:18 +0000 +++ configure.ac 2013-05-28 09:28:06 +0000 @@ -200,7 +200,23 @@ OPTION_DEFAULT_ON([gsettings],[don't compile with GSettings support]) OPTION_DEFAULT_ON([selinux],[don't compile with SELinux support]) OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support]) -OPTION_DEFAULT_ON([inotify],[don't compile with inotify (file-watch) support]) + +## In case of mingw32, it doesn't matter. +AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB], + [use a file notification library (LIB one of: yes or gfile, inotify, no)])], + [ case "${withval}" in + y | ye | yes ) val=gfile ;; + n | no ) val=no ;; + g | gf | gfi | gfil | gfile ) val=gfile ;; + i | in | ino | inot | inoti | inotif | inotify ) val=inotify ;; + * ) +AC_MSG_ERROR([`--with-file-notification=$withval' is invalid; +this option's value should be `yes', `no', `gfile' or `inotify'. +`yes' and `gfile' are synonyms.]) + ;; + esac + with_file_notification=$val +]) ## For the times when you want to build Emacs but don't have ## a suitable makeinfo, and can live without the manuals. @@ -1668,7 +1684,6 @@ W32_RES_LINK="-Wl,emacs.res" else W32_OBJ="$W32_OBJ w32.o w32console.o w32heap.o w32inevt.o w32proc.o" - W32_OBJ="$W32_OBJ w32notify.o" W32_LIBS="$W32_LIBS -lwinmm -lgdi32 -lcomdlg32" W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32 -lusp10" W32_RES_LINK="\$(EMACSRES)" @@ -2294,16 +2309,38 @@ AC_SUBST(LIBGNUTLS_LIBS) AC_SUBST(LIBGNUTLS_CFLAGS) +dnl g_file_monitor exists since glib 2.18. It has been tested under +dnl GNU/Linux only. We take precedence over inotify, but this makes +dnl only sense when glib has been compiled with inotify support. How +dnl to check? +NOTIFY_OBJ= +NOTIFY_SUMMARY=no +if test "${with_file_notification}" = "gfile" || test -z "${with_file_notification}"; then + PKG_CHECK_MODULES(GFILENOTIFY, gio-2.0 >= 2.18, HAVE_GFILENOTIFY=yes, HAVE_GFILENOTIFY=no) + if test "$HAVE_GFILENOTIFY" = "yes"; then + AC_DEFINE(HAVE_GFILENOTIFY, 1, [Define to 1 if using GFile.]) + LIBS="$LIBS $GFILENOTIFY_LIBS" + NOTIFY_OBJ=gfilenotify.o + NOTIFY_SUMMARY="yes -lgio (gfile)" + fi +fi dnl inotify is only available on GNU/Linux. -if test "${with_inotify}" = "yes"; then +if test "${with_file_notification}" = "inotify" || (test -z "${with_file_notification}" && test -z "$NOTIFY_OBJ"); then AC_CHECK_HEADERS(sys/inotify.h) if test "$ac_cv_header_sys_inotify_h" = yes ; then - AC_CHECK_FUNC(inotify_init1) - fi -fi -if test "$ac_cv_func_inotify_init1" = yes; then - AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.]) -fi + AC_CHECK_FUNC(inotify_init1) + if test "$ac_cv_func_inotify_init1" = yes; then + AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.]) + NOTIFY_OBJ=inotify.o + NOTIFY_SUMMARY="yes -lglibc (inotify)" + fi + fi +fi +if "${opsys}" = "mingw32"; then + NOTIFY_OBJ=w32notify.o + NOTIFY_SUMMARY="yes" +fi +AC_SUBST(NOTIFY_OBJ) dnl Do not put whitespace before the #include statements below. dnl Older compilers (eg sunos4 cc) choke on it. @@ -4682,6 +4719,7 @@ echo " Does Emacs use -ldbus? ${HAVE_DBUS}" echo " Does Emacs use -lgconf? ${HAVE_GCONF}" echo " Does Emacs use GSettings? ${HAVE_GSETTINGS}" +echo " Does Emacs use a file notification library? ${NOTIFY_SUMMARY}" echo " Does Emacs use -lselinux? ${HAVE_LIBSELINUX}" echo " Does Emacs use -lgnutls? ${HAVE_GNUTLS}" echo " Does Emacs use -lxml2? ${HAVE_LIBXML2}" === modified file 'lisp/autorevert.el' --- lisp/autorevert.el 2013-05-22 14:47:19 +0000 +++ lisp/autorevert.el 2013-05-22 15:03:33 +0000 @@ -271,7 +271,7 @@ :version "24.4") (defconst auto-revert-notify-enabled - (or (featurep 'inotify) (featurep 'w32notify)) + (or (featurep 'gfilenotify) (featurep 'inotify) (featurep 'w32notify)) "Non-nil when Emacs has been compiled with file notification support.") (defcustom auto-revert-use-notify auto-revert-notify-enabled @@ -502,9 +502,12 @@ (puthash key value auto-revert-notify-watch-descriptor-hash-list) (remhash key auto-revert-notify-watch-descriptor-hash-list) (ignore-errors - (funcall (if (fboundp 'inotify-rm-watch) - 'inotify-rm-watch 'w32notify-rm-watch) - auto-revert-notify-watch-descriptor))))) + (funcall + (cond + ((fboundp 'gfile-rm-watch) 'gfile-rm-watch) + ((fboundp 'inotify-rm-watch) 'inotify-rm-watch) + ((fboundp 'w32notify-rm-watch) 'w32notify-rm-watch)) + auto-revert-notify-watch-descriptor))))) auto-revert-notify-watch-descriptor-hash-list) (remove-hook 'kill-buffer-hook 'auto-revert-notify-rm-watch)) (setq auto-revert-notify-watch-descriptor nil @@ -519,12 +522,18 @@ (when (and buffer-file-name auto-revert-use-notify (not auto-revert-notify-watch-descriptor)) - (let ((func (if (fboundp 'inotify-add-watch) - 'inotify-add-watch 'w32notify-add-watch)) - ;; `attrib' is needed for file modification time. - (aspect (if (fboundp 'inotify-add-watch) - '(attrib create modify moved-to) '(size last-write-time))) - (file (if (fboundp 'inotify-add-watch) + (let ((func + (cond + ((fboundp 'gfile-add-watch) 'gfile-add-watch) + ((fboundp 'inotify-add-watch) 'inotify-add-watch) + ((fboundp 'w32notify-add-watch) 'w32notify-add-watch))) + (aspect + (cond + ((fboundp 'gfile-add-watch) '(watch-mounts)) + ;; `attrib' is needed for file modification time. + ((fboundp 'inotify-add-watch) '(attrib create modify moved-to)) + ((fboundp 'w32notify-add-watch) '(size last-write-time)))) + (file (if (or (fboundp 'gfile-add-watch) (fboundp 'inotify-add-watch)) (directory-file-name (expand-file-name default-directory)) (buffer-file-name)))) (setq auto-revert-notify-watch-descriptor @@ -545,10 +554,13 @@ (defun auto-revert-notify-event-p (event) "Check that event is a file notification event." - (cond ((featurep 'inotify) - (and (listp event) (= (length event) 4))) - ((featurep 'w32notify) - (and (listp event) (= (length event) 3) (stringp (nth 2 event)))))) + (and (listp event) + (cond ((featurep 'gfilenotify) + (and (>= (length event) 3) (stringp (nth 2 event)))) + ((featurep 'inotify) + (= (length event) 4)) + ((featurep 'w32notify) + (and (= (length event) 3) (stringp (nth 2 event))))))) (defun auto-revert-notify-event-descriptor (event) "Return watch descriptor of file notification event, or nil." @@ -561,7 +573,8 @@ (defun auto-revert-notify-event-file-name (event) "Return file name of file notification event, or nil." (and (auto-revert-notify-event-p event) - (cond ((featurep 'inotify) (nth 3 event)) + (cond ((featurep 'gfilenotify) (nth 2 event)) + ((featurep 'inotify) (nth 3 event)) ((featurep 'w32notify) (nth 2 event))))) (defun auto-revert-notify-handler (event) @@ -576,12 +589,18 @@ ;; Check, that event is meant for us. ;; TODO: Filter events which stop watching, like `move' or `removed'. (cl-assert descriptor) - (when (featurep 'inotify) + (cond + ((featurep 'gfilenotify) + (cl-assert (or (eq 'attribute-changed action) + (eq 'changed action) + (eq 'created action) + (eq 'deleted action)))) + ((featurep 'inotify) (cl-assert (or (memq 'attrib action) (memq 'create action) (memq 'modify action) (memq 'moved-to action)))) - (when (featurep 'w32notify) (cl-assert (eq 'modified action))) + ((featurep 'w32notify) (cl-assert (eq 'modified action)))) ;; Since we watch a directory, a file name must be returned. (cl-assert (stringp file)) (dolist (buffer buffers) === modified file 'lisp/subr.el' --- lisp/subr.el 2013-05-25 16:05:19 +0000 +++ lisp/subr.el 2013-05-27 06:24:20 +0000 @@ -4432,32 +4432,16 @@ ;;;; Support for watching filesystem events. -(defun inotify-event-p (event) - "Check if EVENT is an inotify event." - (and (listp event) - (>= (length event) 3) - (eq (car event) 'file-inotify))) - -;;;###autoload -(defun inotify-handle-event (event) - "Handle inotify file system monitoring event. -If EVENT is an inotify filewatch event, call its callback. -Otherwise, signal a `filewatch-error'." - (interactive "e") - (unless (inotify-event-p event) - (signal 'filewatch-error (cons "Not a valid inotify event" event))) - (funcall (nth 2 event) (nth 1 event))) - -(defun w32notify-handle-event (event) - "Handle MS-Windows file system monitoring event. -If EVENT is an MS-Windows filewatch event, call its callback. -Otherwise, signal a `filewatch-error'." - (interactive "e") - (if (and (eq (car event) 'file-w32notify) - (= (length event) 3)) +(defun file-notify-handle-event (event) + "Handle file system monitoring event. +If EVENT is a filewatch event, call its callback. +Otherwise, signal a `filewatch-error'." + (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 MS-Windows file-notify event" event)))) + (cons "Not a valid file-notify event" event)))) ;;;; Comparing version strings. === modified file 'src/Makefile.in' --- src/Makefile.in 2013-05-16 09:58:56 +0000 +++ src/Makefile.in 2013-05-28 09:35:00 +0000 @@ -156,6 +156,11 @@ ## gtkutil.o if USE_GTK, else empty. GTK_OBJ=@GTK_OBJ@ +## gfilenotify.o if HAVE_GFILENOTIFY. +## inotify.o if HAVE_INOTIFY. +## w32notify.o for mingw32. +NOTIFY_OBJ = @NOTIFY_OBJ@ + ## -ltermcap, or -lncurses, or -lcurses, or "". LIBS_TERMCAP=@LIBS_TERMCAP@ ## terminfo.o if TERMINFO, else tparam.o. @@ -363,7 +368,7 @@ syntax.o $(UNEXEC_OBJ) bytecode.o \ process.o gnutls.o callproc.o \ region-cache.o sound.o atimer.o \ - doprnt.o intervals.o textprop.o composite.o xml.o inotify.o \ + doprnt.o intervals.o textprop.o composite.o xml.o $(NOTIFY_OBJ) \ profiler.o \ $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) === modified file 'src/emacs.c' --- src/emacs.c 2013-03-19 14:09:05 +0000 +++ src/emacs.c 2013-04-10 09:27:58 +0000 @@ -1409,6 +1409,10 @@ syms_of_gnutls (); #endif +#ifdef HAVE_GFILENOTIFY + syms_of_gfilenotify (); +#endif /* HAVE_GFILENOTIFY */ + #ifdef HAVE_INOTIFY syms_of_inotify (); #endif /* HAVE_INOTIFY */ === added file 'src/gfilenotify.c' --- src/gfilenotify.c 1970-01-01 00:00:00 +0000 +++ src/gfilenotify.c 2013-05-22 15:04:04 +0000 @@ -0,0 +1,266 @@ +/* Elisp bindings for D-Bus. + Copyright (C) 2013 Free Software Foundation, Inc. + +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. + +GNU Emacs 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. + +You should have received a copy of the GNU General Public License +along with GNU Emacs. If not, see . */ + +#include + +#ifdef HAVE_GFILENOTIFY +#include +#include +#include "lisp.h" +#include "coding.h" +#include "frame.h" +#include "termhooks.h" +#include "keyboard.h" +#include "process.h" + + +/* Subroutines. */ +static Lisp_Object Qgfile_add_watch; +static Lisp_Object Qgfile_rm_watch; + +/* Filter objects. */ +static Lisp_Object Qwatch_mounts; /* G_FILE_MONITOR_WATCH_MOUNTS */ +static Lisp_Object Qsend_moved; /* G_FILE_MONITOR_SEND_MOVED */ + +/* Event types. */ +static Lisp_Object Qchanged; /* G_FILE_MONITOR_EVENT_CHANGED */ +static Lisp_Object Qchanges_done_hint; /* G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT */ +static Lisp_Object Qdeleted; /* G_FILE_MONITOR_EVENT_DELETED */ +static Lisp_Object Qcreated; /* G_FILE_MONITOR_EVENT_CREATED */ +static Lisp_Object Qattribute_changed; /* G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED */ +static Lisp_Object Qpre_unmount; /* G_FILE_MONITOR_EVENT_PRE_UNMOUNT */ +static Lisp_Object Qunmounted; /* G_FILE_MONITOR_EVENT_UNMOUNTED */ +static Lisp_Object Qmoved; /* G_FILE_MONITOR_EVENT_MOVED */ + +static Lisp_Object watch_list; + +/* This is the callback function for arriving signals from + g_file_monitor. It shall create a Lisp event, and put it into + Emacs input queue. */ +static gboolean +dir_monitor_callback (GFileMonitor* monitor, + GFile* file, + GFile* other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + Lisp_Object symbol, watch_object; + char *name = g_file_get_parse_name (file); + char *oname = other_file ? g_file_get_parse_name (other_file) : NULL; + + /* Determine event symbol. */ + switch (event_type) + { + case G_FILE_MONITOR_EVENT_CHANGED: + symbol = Qchanged; + break; + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + symbol = Qchanges_done_hint; + break; + case G_FILE_MONITOR_EVENT_DELETED: + symbol = Qdeleted; + break; + case G_FILE_MONITOR_EVENT_CREATED: + symbol = Qcreated; + break; + case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: + symbol = Qattribute_changed; + break; + case G_FILE_MONITOR_EVENT_PRE_UNMOUNT: + symbol = Qpre_unmount; + break; + case G_FILE_MONITOR_EVENT_UNMOUNTED: + symbol = Qunmounted; + break; + case G_FILE_MONITOR_EVENT_MOVED: + symbol = Qmoved; + break; + default: + goto cleanup; + } + + /* Determine callback function. */ + watch_object = Fassoc (XIL ((EMACS_INT) monitor), watch_list); + + if (FUNCTIONP (CDR_SAFE (watch_object))) + { + /* Construct an event. */ + struct input_event event; + EVENT_INIT (event); + event.kind = FILE_NOTIFY_EVENT; + event.frame_or_window = Qnil; + event.arg = oname + ? list2 (list4 (XIL ((EMACS_INT) monitor), symbol, + build_string (name), build_string (oname)), + CDR_SAFE (watch_object)) + : list2 (list3 (XIL ((EMACS_INT) monitor), symbol, build_string (name)), + CDR_SAFE (watch_object)); + + /* Store it into the input event queue. */ + kbd_buffer_store_event (&event); + } + + /* Cleanup. */ + cleanup: + g_free (name); + g_free (oname); + + return TRUE; +} + +DEFUN ("gfile-add-watch", Fgfile_add_watch, Sgfile_add_watch, 3, 3, 0, + doc: /* Add a watch for filesystem events pertaining to FILE. + +This arranges for filesystem events pertaining to FILE to be reported +to Emacs. Use `gfile-rm-watch' to cancel the watch. + +Value is a descriptor for the added watch. If the file cannot be +watched for some reason, this function signals a `file-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 (moves) and send a single 'event-moved' + event instead + +When any event happens, Emacs will call the CALLBACK function passing +it a single argument EVENT, which is of the form + + (DESCRIPTOR ACTION FILE [FILE1]) + +DESCRIPTOR is the same object as the one returned by this function. +ACTION is the description of the event. It could be any one of the +following: + + 'changed' -- FILE has changed + 'changes-done-hint' -- a hint that this was probably the last change + in a set of changes + 'deleted' -- FILE was deleted + 'created' -- FILE was created + 'attribute-changed' -- a FILE attribute was changed + 'pre-unmount' -- the FILE location will soon be unmounted + 'unmounted' -- the FILE location was unmounted + 'moved' -- FILE was moved to FILE1 + +FILE is the name of the file whose event is being reported. FILE1 +will be reported only in case of the 'moved' event. */) + (Lisp_Object file, Lisp_Object flags, Lisp_Object callback) +{ + Lisp_Object watch_descriptor, watch_object; + GFile *gfile; + GFileMonitor* monitor; + GFileMonitorFlags gflags = G_FILE_MONITOR_NONE; + + /* Check parameters. */ + CHECK_STRING (file); + file = Fdirectory_file_name (Fexpand_file_name (file, Qnil)); + if (NILP (Ffile_exists_p (file))) + report_file_error ("File does not exists", Fcons (file, Qnil)); + + CHECK_LIST (flags); + + if (!FUNCTIONP (callback)) + wrong_type_argument (Qinvalid_function, callback); + + /* Create GFile name. */ + gfile = g_file_new_for_path (SSDATA (ENCODE_FILE (file))); + + /* Assemble flags. */ + if (!NILP (Fmember (Qwatch_mounts, flags))) + gflags |= G_FILE_MONITOR_WATCH_MOUNTS; + if (!NILP (Fmember (Qsend_moved, flags))) + gflags |= G_FILE_MONITOR_SEND_MOVED; + + /* Enable watch. */ + monitor = g_file_monitor (gfile, gflags, NULL, NULL); + if (monitor != NULL) + g_signal_connect (monitor, "changed", + (GCallback) dir_monitor_callback, NULL); + else + report_file_error ("Cannot watch file", Fcons (file, Qnil)); + + /* Store watch object in watch list. */ + watch_descriptor = XIL ((EMACS_INT) monitor); + watch_object = Fcons (watch_descriptor, callback); + watch_list = Fcons (watch_object, watch_list); + + return watch_descriptor; +} + +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'. */) + (Lisp_Object watch_descriptor) +{ + Lisp_Object watch_object; + GFileMonitor *monitor = (GFileMonitor *) XLI (watch_descriptor); + + watch_object = Fassoc (watch_descriptor, watch_list); + if (NILP (watch_object)) + report_file_error ("Not a watch descriptor", + Fcons (watch_descriptor, Qnil)); + + if (!g_file_monitor_cancel (monitor)) + report_file_error ("Could not rm watch", + Fcons (watch_descriptor, Qnil)); + + /* Remove watch descriptor from watch list. */ + watch_list = Fdelete (watch_object, watch_list); + + /* Cleanup. */ + g_object_unref (monitor); + + return Qt; +} + + +void +syms_of_gfilenotify (void) +{ + + g_type_init (); + + DEFSYM (Qgfile_add_watch, "gfile-add-watch"); + defsubr (&Sgfile_add_watch); + + DEFSYM (Qgfile_rm_watch, "gfile-rm-watch"); + defsubr (&Sgfile_rm_watch); + + DEFSYM (Qwatch_mounts, "watch-mounts"); + DEFSYM (Qsend_moved, "send-moved"); + DEFSYM (Qchanged, "changed"); + DEFSYM (Qchanges_done_hint, "changes-done-hint"); + DEFSYM (Qdeleted, "deleted"); + DEFSYM (Qcreated, "created"); + DEFSYM (Qattribute_changed, "attribute-changed"); + DEFSYM (Qpre_unmount, "pre-unmount"); + DEFSYM (Qunmounted, "unmounted"); + DEFSYM (Qmoved, "moved"); + + /* Initialize internal objects. */ + watch_list = Qnil; + staticpro (&watch_list); + + Fprovide (intern_c_string ("gfilenotify"), Qnil); + +} + +#endif /* HAVE_GFILENOTIFY */ === modified file 'src/keyboard.c' --- src/keyboard.c 2013-05-23 18:49:57 +0000 +++ src/keyboard.c 2013-05-24 09:51:35 +0000 @@ -308,18 +308,15 @@ Lisp_Object Qmouse_click; #ifdef HAVE_NTGUI Lisp_Object Qlanguage_change; -#ifdef WINDOWSNT -Lisp_Object Qfile_w32notify; -#endif #endif static Lisp_Object Qdrag_n_drop; static Lisp_Object Qsave_session; #ifdef HAVE_DBUS static Lisp_Object Qdbus_event; #endif -#ifdef HAVE_INOTIFY -static Lisp_Object Qfile_inotify; -#endif /* HAVE_INOTIFY */ +#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY || defined WINDOWSNT +static Lisp_Object Qfile_notify; +#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY || defined WINDOWSNT */ static Lisp_Object Qconfig_changed_event; /* Lisp_Object Qmouse_movement; - also an event header */ @@ -4017,7 +4014,7 @@ else if (event->kind == FILE_NOTIFY_EVENT) { /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */ - obj = Fcons (Qfile_w32notify, + obj = Fcons (Qfile_notify, list2 (list3 (make_number (event->code), XCAR (event->arg), XCDR (event->arg)), @@ -4082,7 +4079,7 @@ kbd_fetch_ptr = event + 1; } #endif -#ifdef HAVE_INOTIFY +#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY else if (event->kind == FILE_NOTIFY_EVENT) { obj = make_lispy_event (event); @@ -5991,12 +5988,12 @@ } #endif /* HAVE_DBUS */ -#ifdef HAVE_INOTIFY +#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY case FILE_NOTIFY_EVENT: { - return Fcons (Qfile_inotify, event->arg); + return Fcons (Qfile_notify, event->arg); } -#endif /* HAVE_INOTIFY */ +#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY */ case CONFIG_CHANGED_EVENT: return Fcons (Qconfig_changed_event, @@ -11006,17 +11003,13 @@ DEFSYM (Qlanguage_change, "language-change"); #endif -#ifdef WINDOWSNT - DEFSYM (Qfile_w32notify, "file-w32notify"); -#endif - #ifdef HAVE_DBUS DEFSYM (Qdbus_event, "dbus-event"); #endif -#ifdef HAVE_INOTIFY - DEFSYM (Qfile_inotify, "file-inotify"); -#endif /* HAVE_INOTIFY */ +#if defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY || defined WINDOWSNT + DEFSYM (Qfile_notify, "file-notify"); +#endif /* defined HAVE_GFILENOTIFY || defined HAVE_INOTIFY || defined WINDOWSNT */ DEFSYM (QCenable, ":enable"); DEFSYM (QCvisible, ":visible"); @@ -11762,20 +11755,18 @@ "dbus-handle-event"); #endif -#ifdef HAVE_INOTIFY - /* Define a special event which is raised for inotify callback +#if defined HAVE_GFILENOTIFY || HAVE_INOTIFY || defined WINDOWSNT + /* Define a special event which is raised for notification callback functions. */ - initial_define_lispy_key (Vspecial_event_map, "file-inotify", - "inotify-handle-event"); -#endif /* HAVE_INOTIFY */ + initial_define_lispy_key (Vspecial_event_map, "file-notify", + "file-notify-handle-event"); +#endif /* defined HAVE_GFILENOTIFY || HAVE_INOTIFY || defined WINDOWSNT */ initial_define_lispy_key (Vspecial_event_map, "config-changed-event", "ignore"); #if defined (WINDOWSNT) initial_define_lispy_key (Vspecial_event_map, "language-change", "ignore"); - initial_define_lispy_key (Vspecial_event_map, "file-w32notify", - "w32notify-handle-event"); #endif } === modified file 'src/lisp.h' --- src/lisp.h 2013-05-15 18:54:49 +0000 +++ src/lisp.h 2013-05-21 08:25:51 +0000 @@ -3728,6 +3728,11 @@ extern void syms_of_w32notify (void); #endif +/* Defined in gfilenotify.c */ +#ifdef HAVE_GFILENOTIFY +extern void syms_of_gfilenotify (void); +#endif + /* Defined in inotify.c */ #ifdef HAVE_INOTIFY extern void syms_of_inotify (void); === modified file 'src/termhooks.h' --- src/termhooks.h 2013-03-11 01:17:40 +0000 +++ src/termhooks.h 2013-04-10 09:24:04 +0000 @@ -212,7 +212,7 @@ , NS_NONKEY_EVENT #endif -#if defined (HAVE_INOTIFY) || defined (HAVE_NTGUI) +#if defined (HAVE_GFILENOTIFY) || defined (HAVE_INOTIFY) || defined (HAVE_NTGUI) /* File or directory was changed. */ , FILE_NOTIFY_EVENT #endif --=-=-=--