Add kqueue support
* configure.ac (--with-file-notification): Add kqueue. (top): Remove special test for "${HAVE_NS}" and ${with_file_notification}, this is handled inside gfilenotify tests. Add kqueue tests. Use NOTIFY_CFLAGS and NOTIFY_LIBS instead of library specific variables. * src/Makefile.in: Use NOTIFY_CFLAGS and NOTIFY_LIBS. * src/emacs.c (main): Call globals_of_kqueue and syms_of_kqueue. * src/kqueue.c: New file. * src/lisp.h: Declare extern globals_of_kqueue and syms_of_kqueue.
This commit is contained in:
parent
c6457cef92
commit
e3354e2265
5 changed files with 400 additions and 33 deletions
51
configure.ac
51
configure.ac
|
@ -355,17 +355,18 @@ OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
|
||||||
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
|
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
|
||||||
|
|
||||||
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
|
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)])],
|
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
|
||||||
[ case "${withval}" in
|
[ case "${withval}" in
|
||||||
y | ye | yes ) val=yes ;;
|
y | ye | yes ) val=yes ;;
|
||||||
n | no ) val=no ;;
|
n | no ) val=no ;;
|
||||||
g | gf | gfi | gfil | gfile ) val=gfile ;;
|
|
||||||
i | in | ino | inot | inoti | inotif | inotify ) val=inotify ;;
|
i | in | ino | inot | inoti | inotif | inotify ) val=inotify ;;
|
||||||
|
k | kq | kqu | kque | kqueu | kqueue ) val=kqueue ;;
|
||||||
|
g | gf | gfi | gfil | gfile ) val=gfile ;;
|
||||||
w | w3 | w32 ) val=w32 ;;
|
w | w3 | w32 ) val=w32 ;;
|
||||||
* ) AC_MSG_ERROR(['--with-file-notification=$withval' is invalid;
|
* ) AC_MSG_ERROR(['--with-file-notification=$withval' is invalid;
|
||||||
this option's value should be 'yes', 'no', 'gfile', 'inotify' or 'w32'.
|
this option's value should be 'yes', 'no', 'inotify', 'kqeue', 'gfile' or 'w32'.
|
||||||
'yes' is a synonym for 'w32' on MS-Windows, for 'no' on Nextstep,
|
'yes' is a synonym for 'w32' on MS-Windows, for 'no' on Nextstep,
|
||||||
otherwise for the first of 'inotify' or 'gfile' that is usable.])
|
otherwise for the first of 'inotify', 'kqueue' or 'gfile' that is usable.])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
with_file_notification=$val
|
with_file_notification=$val
|
||||||
|
@ -2690,12 +2691,6 @@ AC_SUBST(LIBGNUTLS_CFLAGS)
|
||||||
NOTIFY_OBJ=
|
NOTIFY_OBJ=
|
||||||
NOTIFY_SUMMARY=no
|
NOTIFY_SUMMARY=no
|
||||||
|
|
||||||
dnl FIXME? Don't auto-detect on NS, but do allow someone to specify
|
|
||||||
dnl a particular library. This doesn't make much sense?
|
|
||||||
if test "${HAVE_NS}" = yes && test ${with_file_notification} = yes; then
|
|
||||||
with_file_notification=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl MS Windows native file monitor is available for mingw32 only.
|
dnl MS Windows native file monitor is available for mingw32 only.
|
||||||
case $with_file_notification,$opsys in
|
case $with_file_notification,$opsys in
|
||||||
w32,cygwin)
|
w32,cygwin)
|
||||||
|
@ -2726,16 +2721,34 @@ case $with_file_notification,$NOTIFY_OBJ in
|
||||||
fi ;;
|
fi ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
dnl kqueue is available on BSD-like systems.
|
||||||
|
case $with_file_notification,$NOTIFY_OBJ in
|
||||||
|
kqueue,* | yes,)
|
||||||
|
EMACS_CHECK_MODULES([KQUEUE], [libkqueue])
|
||||||
|
if test "$HAVE_KQUEUE" = "yes"; then
|
||||||
|
AC_DEFINE(HAVE_KQUEUE, 1, [Define to 1 to use kqueue.])
|
||||||
|
CPPFLAGS="$CPPFLAGS -I/usr/include/kqueue"
|
||||||
|
NOTIFY_CFLAGS=$KQUEUE_CFLAGS
|
||||||
|
NOTIFY_LIBS=$KQUEUE_LIBS
|
||||||
|
NOTIFY_OBJ=kqueue.o
|
||||||
|
NOTIFY_SUMMARY="yes -lkqueue"
|
||||||
|
fi ;;
|
||||||
|
esac
|
||||||
|
|
||||||
dnl g_file_monitor exists since glib 2.18. G_FILE_MONITOR_EVENT_MOVED
|
dnl g_file_monitor exists since glib 2.18. G_FILE_MONITOR_EVENT_MOVED
|
||||||
dnl has been added in glib 2.24. It has been tested under
|
dnl has been added in glib 2.24. It has been tested under
|
||||||
dnl GNU/Linux only.
|
dnl GNU/Linux only.
|
||||||
case $with_file_notification,$NOTIFY_OBJ in
|
case $with_file_notification,$NOTIFY_OBJ in
|
||||||
gfile,* | yes,)
|
gfile,* | yes,)
|
||||||
EMACS_CHECK_MODULES([GFILENOTIFY], [gio-2.0 >= 2.24])
|
if test "${HAVE_NS}" != yes; then
|
||||||
if test "$HAVE_GFILENOTIFY" = "yes"; then
|
EMACS_CHECK_MODULES([GFILENOTIFY], [gio-2.0 >= 2.24])
|
||||||
AC_DEFINE(HAVE_GFILENOTIFY, 1, [Define to 1 if using GFile.])
|
if test "$HAVE_GFILENOTIFY" = "yes"; then
|
||||||
NOTIFY_OBJ=gfilenotify.o
|
AC_DEFINE(HAVE_GFILENOTIFY, 1, [Define to 1 if using GFile.])
|
||||||
NOTIFY_SUMMARY="yes -lgio (gfile)"
|
NOTIFY_CFLAGS=$GFILENOTIFY_CFLAGS
|
||||||
|
NOTIFY_LIBS=$GFILENOTIFY_LIBS
|
||||||
|
NOTIFY_OBJ=gfilenotify.o
|
||||||
|
NOTIFY_SUMMARY="yes -lgio (gfile)"
|
||||||
|
fi
|
||||||
fi ;;
|
fi ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
@ -2747,9 +2760,9 @@ esac
|
||||||
if test -n "$NOTIFY_OBJ"; then
|
if test -n "$NOTIFY_OBJ"; then
|
||||||
AC_DEFINE(USE_FILE_NOTIFY, 1, [Define to 1 if using file notifications.])
|
AC_DEFINE(USE_FILE_NOTIFY, 1, [Define to 1 if using file notifications.])
|
||||||
fi
|
fi
|
||||||
|
AC_SUBST(NOTIFY_CFLAGS)
|
||||||
|
AC_SUBST(NOTIFY_LIBS)
|
||||||
AC_SUBST(NOTIFY_OBJ)
|
AC_SUBST(NOTIFY_OBJ)
|
||||||
AC_SUBST(GFILENOTIFY_CFLAGS)
|
|
||||||
AC_SUBST(GFILENOTIFY_LIBS)
|
|
||||||
|
|
||||||
dnl Do not put whitespace before the #include statements below.
|
dnl Do not put whitespace before the #include statements below.
|
||||||
dnl Older compilers (eg sunos4 cc) choke on it.
|
dnl Older compilers (eg sunos4 cc) choke on it.
|
||||||
|
@ -4066,8 +4079,8 @@ OLDCFLAGS="$CFLAGS"
|
||||||
OLDLIBS="$LIBS"
|
OLDLIBS="$LIBS"
|
||||||
CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS"
|
CFLAGS="$CFLAGS $GTK_CFLAGS $RSVG_CFLAGS $DBUS_CFLAGS $SETTINGS_CFLAGS"
|
||||||
LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS"
|
LIBS="$LIBS $GTK_LIBS $RSVG_LIBS $DBUS_LIBS $SETTINGS_LIBS"
|
||||||
CFLAGS="$CFLAGS $GFILENOTIFY_CFLAGS $CAIRO_CFLAGS"
|
CFLAGS="$CFLAGS $NOTIFY_CFLAGS $CAIRO_CFLAGS"
|
||||||
LIBS="$LIBS $GFILENOTIFY_LIBS $CAIRO_LIBS"
|
LIBS="$LIBS $NOTIFY_LIBS $CAIRO_LIBS"
|
||||||
AC_MSG_CHECKING([whether GLib is linked in])
|
AC_MSG_CHECKING([whether GLib is linked in])
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
AC_LINK_IFELSE([AC_LANG_PROGRAM(
|
||||||
[[#include <glib.h>
|
[[#include <glib.h>
|
||||||
|
|
|
@ -160,12 +160,13 @@ SETTINGS_LIBS = @SETTINGS_LIBS@
|
||||||
## gtkutil.o if USE_GTK, else empty.
|
## gtkutil.o if USE_GTK, else empty.
|
||||||
GTK_OBJ=@GTK_OBJ@
|
GTK_OBJ=@GTK_OBJ@
|
||||||
|
|
||||||
## gfilenotify.o if HAVE_GFILENOTIFY.
|
|
||||||
## inotify.o if HAVE_INOTIFY.
|
## inotify.o if HAVE_INOTIFY.
|
||||||
|
## kqueue.o if HAVE_KQUEUE.
|
||||||
|
## gfilenotify.o if HAVE_GFILENOTIFY.
|
||||||
## w32notify.o if HAVE_W32NOTIFY.
|
## w32notify.o if HAVE_W32NOTIFY.
|
||||||
NOTIFY_OBJ = @NOTIFY_OBJ@
|
NOTIFY_OBJ = @NOTIFY_OBJ@
|
||||||
GFILENOTIFY_CFLAGS = @GFILENOTIFY_CFLAGS@
|
NOTIFY_CFLAGS = @NOTIFY_CFLAGS@
|
||||||
GFILENOTIFY_LIBS = @GFILENOTIFY_LIBS@
|
NOTIFY_LIBS = @NOTIFY_LIBS@
|
||||||
|
|
||||||
## -ltermcap, or -lncurses, or -lcurses, or "".
|
## -ltermcap, or -lncurses, or -lcurses, or "".
|
||||||
LIBS_TERMCAP=@LIBS_TERMCAP@
|
LIBS_TERMCAP=@LIBS_TERMCAP@
|
||||||
|
@ -355,7 +356,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
|
||||||
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
|
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
|
||||||
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
|
||||||
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
|
||||||
$(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
|
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
|
||||||
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
|
$(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
|
||||||
ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
|
ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
|
||||||
|
|
||||||
|
@ -468,7 +469,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
|
||||||
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
|
$(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
|
||||||
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
|
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
|
||||||
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
|
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
|
||||||
$(GFILENOTIFY_LIBS) $(LIB_MATH) $(LIBZ)
|
$(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ)
|
||||||
|
|
||||||
$(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT)
|
$(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT)
|
||||||
$(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)"
|
$(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)"
|
||||||
|
|
16
src/emacs.c
16
src/emacs.c
|
@ -1350,6 +1350,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
||||||
tzset ();
|
tzset ();
|
||||||
#endif /* MSDOS */
|
#endif /* MSDOS */
|
||||||
|
|
||||||
|
#ifdef HAVE_KQUEUE
|
||||||
|
globals_of_kqueue ();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GFILENOTIFY
|
#ifdef HAVE_GFILENOTIFY
|
||||||
globals_of_gfilenotify ();
|
globals_of_gfilenotify ();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1520,14 +1524,18 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
||||||
|
|
||||||
syms_of_gnutls ();
|
syms_of_gnutls ();
|
||||||
|
|
||||||
#ifdef HAVE_GFILENOTIFY
|
|
||||||
syms_of_gfilenotify ();
|
|
||||||
#endif /* HAVE_GFILENOTIFY */
|
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
syms_of_inotify ();
|
syms_of_inotify ();
|
||||||
#endif /* HAVE_INOTIFY */
|
#endif /* HAVE_INOTIFY */
|
||||||
|
|
||||||
|
#ifdef HAVE_KQUEUE
|
||||||
|
syms_of_kqueue ();
|
||||||
|
#endif /* HAVE_KQUEUE */
|
||||||
|
|
||||||
|
#ifdef HAVE_GFILENOTIFY
|
||||||
|
syms_of_gfilenotify ();
|
||||||
|
#endif /* HAVE_GFILENOTIFY */
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
syms_of_dbusbind ();
|
syms_of_dbusbind ();
|
||||||
#endif /* HAVE_DBUS */
|
#endif /* HAVE_DBUS */
|
||||||
|
|
339
src/kqueue.c
Normal file
339
src/kqueue.c
Normal file
|
@ -0,0 +1,339 @@
|
||||||
|
/* Filesystem notifications support with glib API.
|
||||||
|
Copyright (C) 2013-2015 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 <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_KQUEUE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/event.h>
|
||||||
|
#include "lisp.h"
|
||||||
|
#include "coding.h"
|
||||||
|
#include "termhooks.h"
|
||||||
|
#include "keyboard.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* File handle for kqueue. */
|
||||||
|
static int kqueuefd = -1;
|
||||||
|
|
||||||
|
/* This is a list, elements are triples (DESCRIPTOR FILE FLAGS CALLBACK) */
|
||||||
|
static Lisp_Object watch_list;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* 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, 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;
|
||||||
|
|
||||||
|
/* 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. */
|
||||||
|
monitor_object = make_pointer_integer (monitor);
|
||||||
|
eassert (INTEGERP (monitor_object));
|
||||||
|
watch_object = assq_no_quit (monitor_object, watch_list);
|
||||||
|
|
||||||
|
if (CONSP (watch_object))
|
||||||
|
{
|
||||||
|
struct input_event event;
|
||||||
|
Lisp_Object otail = oname ? list1 (build_string (oname)) : Qnil;
|
||||||
|
|
||||||
|
/* 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 (!NILP (Fmember (symbol, list2 (Qdeleted, Qmoved))) &&
|
||||||
|
(strcmp (name, SSDATA (XCAR (XCDR (watch_object)))) == 0) &&
|
||||||
|
!g_file_monitor_is_cancelled (monitor))
|
||||||
|
g_file_monitor_cancel (monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cleanup. */
|
||||||
|
cleanup:
|
||||||
|
g_free (name);
|
||||||
|
g_free (oname);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
DEFUN ("kqueue-add-watch", Fkqueue_add_watch, Skqueue_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-notify-error' error.
|
||||||
|
|
||||||
|
FLAGS is a list of conditions to set what will be watched for. It can
|
||||||
|
include the following symbols:
|
||||||
|
|
||||||
|
`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
|
||||||
|
|
||||||
|
(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_object;
|
||||||
|
GFile *gfile;
|
||||||
|
GFileMonitor *monitor;
|
||||||
|
GFileMonitorFlags gflags = G_FILE_MONITOR_NONE;
|
||||||
|
GError *gerror = NULL;
|
||||||
|
|
||||||
|
/* 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 exist", file);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (kqueuefd < 0)
|
||||||
|
{
|
||||||
|
kqueuefd = kqueue ();
|
||||||
|
if (kqueuefd < 0)
|
||||||
|
report_file_notify_error ("File watching is not available", Qnil);
|
||||||
|
watch_list = Qnil;
|
||||||
|
// add_read_fd (inotifyfd, &inotify_callback, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
mask = aspect_to_inotifymask (aspect);
|
||||||
|
encoded_file_name = ENCODE_FILE (file_name);
|
||||||
|
watchdesc = inotify_add_watch (inotifyfd, SSDATA (encoded_file_name), mask);
|
||||||
|
if (watchdesc == -1)
|
||||||
|
report_file_notify_error ("Could not add watch for file", file_name);
|
||||||
|
|
||||||
|
/* Enable watch. */
|
||||||
|
monitor = g_file_monitor (gfile, gflags, NULL, &gerror);
|
||||||
|
g_object_unref (gfile);
|
||||||
|
if (gerror)
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
strcpy (msg, gerror->message);
|
||||||
|
g_error_free (gerror);
|
||||||
|
xsignal1 (Qfile_notify_error, build_string (msg));
|
||||||
|
}
|
||||||
|
if (! monitor)
|
||||||
|
xsignal2 (Qfile_notify_error, build_string ("Cannot watch file"), file);
|
||||||
|
|
||||||
|
Lisp_Object watch_descriptor = make_pointer_integer (monitor);
|
||||||
|
|
||||||
|
/* Check the dicey assumption that make_pointer_integer is safe. */
|
||||||
|
if (! INTEGERP (watch_descriptor))
|
||||||
|
{
|
||||||
|
g_object_unref (monitor);
|
||||||
|
xsignal2 (Qfile_notify_error, build_string ("Unsupported file watcher"),
|
||||||
|
file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The default rate limit is 800 msec. We adapt this. */
|
||||||
|
g_file_monitor_set_rate_limit (monitor, 100);
|
||||||
|
|
||||||
|
/* Subscribe to the "changed" signal. */
|
||||||
|
g_signal_connect (monitor, "changed",
|
||||||
|
(GCallback) dir_monitor_callback, NULL);
|
||||||
|
|
||||||
|
/* Store watch object in watch list. */
|
||||||
|
watch_object = list4 (watch_descriptor, file, flags, 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 = assq_no_quit (watch_descriptor, watch_list);
|
||||||
|
|
||||||
|
if (! CONSP (watch_object))
|
||||||
|
xsignal2 (Qfile_notify_error, build_string ("Not a watch descriptor"),
|
||||||
|
watch_descriptor);
|
||||||
|
|
||||||
|
eassert (INTEGERP (watch_descriptor));
|
||||||
|
GFileMonitor *monitor = XINTPTR (watch_descriptor);
|
||||||
|
if (!g_file_monitor_is_cancelled (monitor) &&
|
||||||
|
!g_file_monitor_cancel (monitor))
|
||||||
|
xsignal2 (Qfile_notify_error, build_string ("Could not rm watch"),
|
||||||
|
watch_descriptor);
|
||||||
|
|
||||||
|
/* Remove watch descriptor from watch list. */
|
||||||
|
watch_list = Fdelq (watch_object, watch_list);
|
||||||
|
|
||||||
|
/* Cleanup. */
|
||||||
|
g_object_unref (monitor);
|
||||||
|
|
||||||
|
return Qt;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN ("gfile-valid-p", Fgfile_valid_p, Sgfile_valid_p, 1, 1, 0,
|
||||||
|
doc: /* "Check a watch specified by its WATCH-DESCRIPTOR.
|
||||||
|
|
||||||
|
WATCH-DESCRIPTOR should be an object returned by `gfile-add-watch'.
|
||||||
|
|
||||||
|
A watch can become invalid if the file or directory it watches is
|
||||||
|
deleted, or if the watcher thread exits abnormally for any other
|
||||||
|
reason. Removing the watch by calling `gfile-rm-watch' also makes it
|
||||||
|
invalid. */)
|
||||||
|
(Lisp_Object watch_descriptor)
|
||||||
|
{
|
||||||
|
Lisp_Object watch_object = Fassoc (watch_descriptor, watch_list);
|
||||||
|
if (NILP (watch_object))
|
||||||
|
return Qnil;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GFileMonitor *monitor = XINTPTR (watch_descriptor);
|
||||||
|
return g_file_monitor_is_cancelled (monitor) ? Qnil : Qt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
globals_of_kqueue (void)
|
||||||
|
{
|
||||||
|
watch_list = Qnil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
syms_of_kqueue (void)
|
||||||
|
{
|
||||||
|
defsubr (&Skqueue_add_watch);
|
||||||
|
// defsubr (&Skqueue_rm_watch);
|
||||||
|
// defsubr (&Skqueue_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 */
|
||||||
|
|
||||||
|
/* Event types. */
|
||||||
|
DEFSYM (Qdelete, "delete"); /* NOTE_DELETE */
|
||||||
|
DEFSYM (Qwrite, "write"); /* NOTE_WRITE */
|
||||||
|
DEFSYM (Qextend, "extend"); /* NOTE_EXTEND */
|
||||||
|
DEFSYM (Qattrib, "attrib"); /* NOTE_ATTRIB */
|
||||||
|
DEFSYM (Qlink, "link"); /* NOTE_LINK */
|
||||||
|
DEFSYM (Qrename, "rename"); /* NOTE_RENAME */
|
||||||
|
|
||||||
|
staticpro (&watch_list);
|
||||||
|
|
||||||
|
Fprovide (intern_c_string ("kqueue"), Qnil);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_KQUEUE */
|
16
src/lisp.h
16
src/lisp.h
|
@ -4257,17 +4257,23 @@ extern void init_font (void);
|
||||||
extern void syms_of_fontset (void);
|
extern void syms_of_fontset (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Defined in inotify.c */
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
extern void syms_of_inotify (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Defined in kqueue.c */
|
||||||
|
#ifdef HAVE_KQUEUE
|
||||||
|
extern void globals_of_kqueue (void);
|
||||||
|
extern void syms_of_kqueue (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Defined in gfilenotify.c */
|
/* Defined in gfilenotify.c */
|
||||||
#ifdef HAVE_GFILENOTIFY
|
#ifdef HAVE_GFILENOTIFY
|
||||||
extern void globals_of_gfilenotify (void);
|
extern void globals_of_gfilenotify (void);
|
||||||
extern void syms_of_gfilenotify (void);
|
extern void syms_of_gfilenotify (void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Defined in inotify.c */
|
|
||||||
#ifdef HAVE_INOTIFY
|
|
||||||
extern void syms_of_inotify (void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_W32NOTIFY
|
#ifdef HAVE_W32NOTIFY
|
||||||
/* Defined on w32notify.c. */
|
/* Defined on w32notify.c. */
|
||||||
extern void syms_of_w32notify (void);
|
extern void syms_of_w32notify (void);
|
||||||
|
|
Loading…
Add table
Reference in a new issue