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: Wed, 29 May 2013 17:57:19 +0200 Message-ID: <87obbtaie8.fsf@gmx.de> References: <87zjxxn6th.fsf@gmx.de> <87hajqpjn1.fsf@gmx.de> <8738t7pewc.fsf@gmx.de> <83fvx7p1h4.fsf@gnu.org> <877gihc3qm.fsf@gmx.de> <83mwrd6c54.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1369843073 8416 80.91.229.3 (29 May 2013 15:57:53 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 29 May 2013 15:57:53 +0000 (UTC) Cc: Daniel Colascione , monnier@iro.umontreal.ca, Ken Brown , emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed May 29 17:57:52 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 1Uhil5-0001RO-BQ for ged-emacs-devel@m.gmane.org; Wed, 29 May 2013 17:57:51 +0200 Original-Received: from localhost ([::1]:52827 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uhil4-00075u-MK for ged-emacs-devel@m.gmane.org; Wed, 29 May 2013 11:57:50 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:55243) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uhikt-00075C-J7 for emacs-devel@gnu.org; Wed, 29 May 2013 11:57:47 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Uhikm-0003PL-K8 for emacs-devel@gnu.org; Wed, 29 May 2013 11:57:39 -0400 Original-Received: from mout.gmx.net ([212.227.15.15]:61886) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Uhikm-0003Oz-3y for emacs-devel@gnu.org; Wed, 29 May 2013 11:57:32 -0400 Original-Received: from mailout-de.gmx.net ([10.1.76.30]) by mrigmx.server.lan (mrigmx001) with ESMTP (Nemesis) id 0MGDg9-1UbvSP3aul-00FBg6 for ; Wed, 29 May 2013 17:57:30 +0200 Original-Received: (qmail invoked by alias); 29 May 2013 15:57:26 -0000 Original-Received: from p5DCA31B8.dip0.t-ipconnect.de (EHLO detlef.gmx.de) [93.202.49.184] by mail.gmx.net (mp030) with SMTP; 29 May 2013 17:57:26 +0200 X-Authenticated: #3708877 X-Provags-ID: V01U2FsdGVkX1/BM3hg/YDBp29gbCSyz6aEkKcGVex0lAQ2rAHFms dDiuyZpmfat138 In-Reply-To: <83mwrd6c54.fsf@gnu.org> (Eli Zaretskii's message of "Wed, 29 May 2013 18:25:59 +0300") 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.15 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:159893 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: >> I cannot test the MS Windows case; here I trust on you. > > Can you post an updated patch? Appended. > Also, it would be good for someone on Cygwin to test this and/or > comment on the applicability of the options to the Cygwin builds. > Ken, Daniel, can you take a look, please? TIA. 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-29 11:29:31 +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 @@ -547,6 +547,9 @@ /* Define to 1 if you have the `get_current_dir_name' function. */ #undef HAVE_GET_CURRENT_DIR_NAME +/* Define to 1 to use glib's notify. */ +#undef HAVE_GFILENOTIFY + /* Define to 1 if you have a gif (or ungif) library. */ #undef HAVE_GIF @@ -1140,6 +1143,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_VFORK_H +/* Define to 1 to use w32notify. */ +#undef HAVE_W32NOTIFY + /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H @@ -1496,6 +1502,9 @@ /* Define to nonzero if you want access control list support. */ #undef USE_ACL +/* Define to 1 if if using file notifications. */ +#undef USE_FILE_NOTIFY + /* Define to 1 if using GTK. */ #undef USE_GTK @@ -1836,4 +1845,3 @@ mode: c End: */ - === modified file 'configure.ac' --- configure.ac 2013-05-27 02:03:18 +0000 +++ configure.ac 2013-05-29 12:41:52 +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]) + +AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB], + [use a file notification library (LIB one of: yes, gfile, inotify, w32, no)])], + [ case "${withval}" in + y | ye | yes ) val=yes ;; + n | no ) val=no ;; + g | gf | gfi | gfil | gfile ) val=gfile ;; + i | in | ino | inot | inoti | inotif | inotify ) val=inotify ;; + w | w3 | w32 ) val=w32 ;; + * ) AC_MSG_ERROR([`--with-file-notification=$withval' is invalid; +this option's value should be `yes', `no', `gfile', `inotify' or `w32'. +`yes' is a synonym for `w32' on MS-Windows, and for `gfile' otherwise.]) + ;; + esac + with_file_notification=$val + ], + [with_file_notification=yes]) ## 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,56 @@ AC_SUBST(LIBGNUTLS_LIBS) AC_SUBST(LIBGNUTLS_CFLAGS) +NOTIFY_OBJ= +NOTIFY_SUMMARY=no + +dnl Set defaults of $with_file_notification. +if test "${with_file_notification}" = "yes"; then + if test "${opsys}" = "mingw32"; then + with_file_notification=w32 + else + with_file_notification=gfile + fi +fi + +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? +if test "${with_file_notification}" = "gfile"; 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 - AC_CHECK_HEADERS(sys/inotify.h) +if test "${with_file_notification}" = "inotify"; then + AC_CHECK_HEADER(sys/inotify.h) if test "$ac_cv_header_sys_inotify_h" = yes ; then - AC_CHECK_FUNC(inotify_init1) + 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 +dnl MS Windows native file monitor is available for mingw32 only. +if test "${with_file_notification}" = "w32"; then + AC_CHECK_HEADER(windows.h) + if test "$ac_cv_header_windows_h" = yes ; then + AC_DEFINE(HAVE_W32NOTIFY, 1, [Define to 1 to use w32notify.]) + NOTIFY_OBJ=w32notify.o + NOTIFY_SUMMARY="yes (w32)" fi fi -if test "$ac_cv_func_inotify_init1" = yes; then - AC_DEFINE(HAVE_INOTIFY, 1, [Define to 1 to use inotify.]) +if test -n "$NOTIFY_OBJ"; then + AC_DEFINE(USE_FILE_NOTIFY, 1, [Define to 1 if using file notifications.]) 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 +4737,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-29 11:31:27 +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 if HAVE_W32NOTIFY. +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-05-29 12:46:37 +0000 @@ -1252,7 +1252,9 @@ #ifdef WINDOWSNT globals_of_w32 (); +#ifdef HAVE_W32NOTIFY globals_of_w32notify (); +#endif /* Initialize environment from registry settings. */ init_environment (argv); init_ntproc (dumping); /* must precede init_editfns. */ @@ -1409,17 +1411,24 @@ syms_of_gnutls (); #endif +#ifdef HAVE_GFILENOTIFY + syms_of_gfilenotify (); +#endif /* HAVE_GFILENOTIFY */ + #ifdef HAVE_INOTIFY syms_of_inotify (); #endif /* HAVE_INOTIFY */ +#ifdef HAVE_W32NOTIFY + syms_of_w32notify (); +#endif /* HAVE_W32NOTIFY */ + #ifdef HAVE_DBUS syms_of_dbusbind (); #endif /* HAVE_DBUS */ #ifdef WINDOWSNT syms_of_ntterm (); - syms_of_w32notify (); #endif /* WINDOWSNT */ syms_of_profiler (); === 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-29 12:52:13 +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 */ +#ifdef USE_FILE_NOTIFY +static Lisp_Object Qfile_notify; +#endif /* USE_FILE_NOTIFY */ static Lisp_Object Qconfig_changed_event; /* Lisp_Object Qmouse_movement; - also an event header */ @@ -4013,18 +4010,22 @@ kbd_fetch_ptr = event + 1; } #endif -#ifdef WINDOWSNT +#ifdef USE_FILE_NOTIFY else if (event->kind == FILE_NOTIFY_EVENT) { +#ifdef HAVE_W32NOTIFY /* 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)), event->frame_or_window)); +#else + obj = make_lispy_event (event); +#endif kbd_fetch_ptr = event + 1; } -#endif +#endif /* USE_FILE_NOTIFY */ else if (event->kind == SAVE_SESSION_EVENT) { obj = Fcons (Qsave_session, Fcons (event->arg, Qnil)); @@ -4082,13 +4083,6 @@ kbd_fetch_ptr = event + 1; } #endif -#ifdef HAVE_INOTIFY - else if (event->kind == FILE_NOTIFY_EVENT) - { - obj = make_lispy_event (event); - kbd_fetch_ptr = event + 1; - } -#endif else if (event->kind == CONFIG_CHANGED_EVENT) { obj = make_lispy_event (event); @@ -5991,12 +5985,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 +11000,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 */ +#ifdef USE_FILE_NOTIFY + DEFSYM (Qfile_notify, "file-notify"); +#endif /* USE_FILE_NOTIFY */ DEFSYM (QCenable, ":enable"); DEFSYM (QCvisible, ":visible"); @@ -11762,20 +11752,18 @@ "dbus-handle-event"); #endif -#ifdef HAVE_INOTIFY - /* Define a special event which is raised for inotify callback +#ifdef USE_FILE_NOTIFY + /* 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 /* USE_FILE_NOTIFY */ 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-29 12:39:19 +0000 @@ -3723,9 +3723,9 @@ extern Lisp_Object Qfont_param; #endif -#ifdef WINDOWSNT -/* Defined on w32notify.c. */ -extern void syms_of_w32notify (void); +/* Defined in gfilenotify.c */ +#ifdef HAVE_GFILENOTIFY +extern void syms_of_gfilenotify (void); #endif /* Defined in inotify.c */ @@ -3733,6 +3733,11 @@ extern void syms_of_inotify (void); #endif +#ifdef HAVE_W32NOTIFY +/* 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; === modified file 'src/termhooks.h' --- src/termhooks.h 2013-03-11 01:17:40 +0000 +++ src/termhooks.h 2013-05-29 12:40:17 +0000 @@ -212,7 +212,7 @@ , NS_NONKEY_EVENT #endif -#if defined (HAVE_INOTIFY) || defined (HAVE_NTGUI) +#ifdef USE_FILE_NOTIFY /* File or directory was changed. */ , FILE_NOTIFY_EVENT #endif --=-=-=--