aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRüdiger Sonderfeld2012-12-10 06:17:21 -0500
committerEli Zaretskii2012-12-10 06:17:21 -0500
commit81606b10501169a5671061b8461bbc32dcec8705 (patch)
tree6dadb650dc1950fbb1e5d4cf6f0c8d18588e6787 /src
parent265c2fbf11cb8bf9b805df63ecb9508631f08e35 (diff)
downloademacs-81606b10501169a5671061b8461bbc32dcec8705.tar.gz
emacs-81606b10501169a5671061b8461bbc32dcec8705.zip
Support filesystem notification through inotify on GNU/Linux.
configure.ac (inotify): New option. (HAVE_INOTIFY): Test for inotify. src/termhooks.h (enum event_kind) [HAVE_INOTIFY]: Add FILE_NOTIFY_EVENT. src/lisp.h (syms_of_inotify) [HAVE_INOTIFY]: Add prototype. src/keyboard.c (Qfile_inotify) [HAVE_INOTIFY]: New variable. (syms_of_keyboard): DEFSYM it. (kbd_buffer_get_event) [HAVE_INOTIFY]: Generate FILE_NOTIFY_EVENT. (make_lispy_event): Support FILE_NOTIFY_EVENT by generating Qfile_inotify events. (keys_of_keyboard) [HAVE_INOTIFY]: Bind file-inotify events in special-event-map to inotify-handle-event. src/emacs.c (main) [HAVE_INOTIFY]: Call syms_of_inotify. src/Makefile.in (base_obj): Add inotify.o. src/inotify.c: New file. lisp/subr.el (inotify-event-p, inotify-handle-event): New functions. test/automated/inotify-test.el: New test.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog21
-rw-r--r--src/Makefile.in2
-rw-r--r--src/emacs.c4
-rw-r--r--src/inotify.c438
-rw-r--r--src/keyboard.c28
-rw-r--r--src/lisp.h5
-rw-r--r--src/termhooks.h5
7 files changed, 502 insertions, 1 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e7fc8179e07..e234b342ac7 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,24 @@
12012-12-10 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
2
3 * termhooks.h (enum event_kind) [HAVE_INOTIFY]: Add
4 FILE_NOTIFY_EVENT.
5
6 * lisp.h (syms_of_inotify) [HAVE_INOTIFY]: Add prototype.
7
8 * keyboard.c (Qfile_inotify) [HAVE_INOTIFY]: New variable.
9 (syms_of_keyboard): DEFSYM it.
10 (kbd_buffer_get_event) [HAVE_INOTIFY]: Generate FILE_NOTIFY_EVENT.
11 (make_lispy_event): Support FILE_NOTIFY_EVENT by generating
12 Qfile_inotify events.
13 (keys_of_keyboard) [HAVE_INOTIFY]: Bind file-inotify events in
14 special-event-map to inotify-handle-event.
15
16 * emacs.c (main) [HAVE_INOTIFY]: Call syms_of_inotify.
17
18 * Makefile.in (base_obj): Add inotify.o.
19
20 * inotify.c: New file.
21
12012-12-10 Jan Djärv <jan.h.d@swipnet.se> 222012-12-10 Jan Djärv <jan.h.d@swipnet.se>
2 23
3 * nsterm.m (fd_handler:): FD_ZERO fds (Bug#13103). 24 * nsterm.m (fd_handler:): FD_ZERO fds (Bug#13103).
diff --git a/src/Makefile.in b/src/Makefile.in
index d034ad04796..eb7c7720ea5 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -344,7 +344,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
344 syntax.o $(UNEXEC_OBJ) bytecode.o \ 344 syntax.o $(UNEXEC_OBJ) bytecode.o \
345 process.o gnutls.o callproc.o \ 345 process.o gnutls.o callproc.o \
346 region-cache.o sound.o atimer.o \ 346 region-cache.o sound.o atimer.o \
347 doprnt.o intervals.o textprop.o composite.o xml.o \ 347 doprnt.o intervals.o textprop.o composite.o xml.o inotify.o \
348 profiler.o \ 348 profiler.o \
349 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \ 349 $(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
350 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ) 350 $(W32_OBJ) $(WINDOW_SYSTEM_OBJ)
diff --git a/src/emacs.c b/src/emacs.c
index fbaf0355000..c5d27a28852 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -1442,6 +1442,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1442 syms_of_gnutls (); 1442 syms_of_gnutls ();
1443#endif 1443#endif
1444 1444
1445#ifdef HAVE_INOTIFY
1446 syms_of_inotify ();
1447#endif /* HAVE_INOTIFY */
1448
1445#ifdef HAVE_DBUS 1449#ifdef HAVE_DBUS
1446 syms_of_dbusbind (); 1450 syms_of_dbusbind ();
1447#endif /* HAVE_DBUS */ 1451#endif /* HAVE_DBUS */
diff --git a/src/inotify.c b/src/inotify.c
new file mode 100644
index 00000000000..4db95a069fe
--- /dev/null
+++ b/src/inotify.c
@@ -0,0 +1,438 @@
1/* Inotify support for Emacs
2
3Copyright (C) 2012
4 Free Software Foundation, Inc.
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21#include <config.h>
22
23#ifdef HAVE_INOTIFY
24
25#include "lisp.h"
26#include "coding.h"
27#include "process.h"
28#include "keyboard.h"
29#include "character.h"
30#include "frame.h" /* Required for termhooks.h. */
31#include "termhooks.h"
32
33static Lisp_Object Qaccess; /* IN_ACCESS */
34static Lisp_Object Qattrib; /* IN_ATTRIB */
35static Lisp_Object Qclose_write; /* IN_CLOSE_WRITE */
36static Lisp_Object Qclose_nowrite; /* IN_CLOSE_NOWRITE */
37static Lisp_Object Qcreate; /* IN_CREATE */
38static Lisp_Object Qdelete; /* IN_DELETE */
39static Lisp_Object Qdelete_self; /* IN_DELETE_SELF */
40static Lisp_Object Qmodify; /* IN_MODIFY */
41static Lisp_Object Qmove_self; /* IN_MOVE_SELF */
42static Lisp_Object Qmoved_from; /* IN_MOVED_FROM */
43static Lisp_Object Qmoved_to; /* IN_MOVED_TO */
44static Lisp_Object Qopen; /* IN_OPEN */
45
46static Lisp_Object Qall_events; /* IN_ALL_EVENTS */
47static Lisp_Object Qmove; /* IN_MOVE */
48static Lisp_Object Qclose; /* IN_CLOSE */
49
50static Lisp_Object Qdont_follow; /* IN_DONT_FOLLOW */
51static Lisp_Object Qexcl_unlink; /* IN_EXCL_UNLINK */
52static Lisp_Object Qmask_add; /* IN_MASK_ADD */
53static Lisp_Object Qoneshot; /* IN_ONESHOT */
54static Lisp_Object Qonlydir; /* IN_ONLYDIR */
55
56static Lisp_Object Qignored; /* IN_IGNORED */
57static Lisp_Object Qisdir; /* IN_ISDIR */
58static Lisp_Object Qq_overflow; /* IN_Q_OVERFLOW */
59static Lisp_Object Qunmount; /* IN_UNMOUNT */
60
61#include <sys/inotify.h>
62#include <sys/ioctl.h>
63
64/* Ignore bits that might be undefined on old GNU/Linux systems. */
65#ifndef IN_EXCL_UNLINK
66# define IN_EXCL_UNLINK 0
67#endif
68#ifndef IN_DONT_FOLLOW
69# define IN_DONT_FOLLOW 0
70#endif
71#ifndef IN_ONLYDIR
72# define IN_ONLYDIR 0
73#endif
74
75enum { uninitialized = -100 };
76/* File handle for inotify. */
77static int inotifyfd = uninitialized;
78
79/* Assoc list of files being watched.
80 Format:
81 (watch-descriptor . callback)
82 */
83static Lisp_Object watch_list;
84
85static Lisp_Object
86make_watch_descriptor (int wd)
87{
88 /* TODO replace this with a Misc Object! */
89 return make_number (wd);
90}
91
92static Lisp_Object
93mask_to_aspects (uint32_t mask) {
94 Lisp_Object aspects = Qnil;
95 if (mask & IN_ACCESS)
96 aspects = Fcons (Qaccess, aspects);
97 if (mask & IN_ATTRIB)
98 aspects = Fcons (Qattrib, aspects);
99 if (mask & IN_CLOSE_WRITE)
100 aspects = Fcons (Qclose_write, aspects);
101 if (mask & IN_CLOSE_NOWRITE)
102 aspects = Fcons (Qclose_nowrite, aspects);
103 if (mask & IN_CREATE)
104 aspects = Fcons (Qcreate, aspects);
105 if (mask & IN_DELETE)
106 aspects = Fcons (Qdelete, aspects);
107 if (mask & IN_DELETE_SELF)
108 aspects = Fcons (Qdelete_self, aspects);
109 if (mask & IN_MODIFY)
110 aspects = Fcons (Qmodify, aspects);
111 if (mask & IN_MOVE_SELF)
112 aspects = Fcons (Qmove_self, aspects);
113 if (mask & IN_MOVED_FROM)
114 aspects = Fcons (Qmoved_from, aspects);
115 if (mask & IN_MOVED_TO)
116 aspects = Fcons (Qmoved_to, aspects);
117 if (mask & IN_OPEN)
118 aspects = Fcons (Qopen, aspects);
119 if (mask & IN_IGNORED)
120 aspects = Fcons (Qignored, aspects);
121 if (mask & IN_ISDIR)
122 aspects = Fcons (Qisdir, aspects);
123 if (mask & IN_Q_OVERFLOW)
124 aspects = Fcons (Qq_overflow, aspects);
125 if (mask & IN_UNMOUNT)
126 aspects = Fcons (Qunmount, aspects);
127 return aspects;
128}
129
130static Lisp_Object
131inotifyevent_to_event (Lisp_Object watch_object, struct inotify_event const *ev)
132{
133 Lisp_Object name = Qnil;
134 if (ev->len > 0)
135 {
136 size_t const len = strlen (ev->name);
137 name = make_unibyte_string (ev->name, min (len, ev->len));
138 name = DECODE_FILE (name);
139 }
140
141 return list2 (list4 (make_watch_descriptor (ev->wd),
142 mask_to_aspects (ev->mask),
143 make_number (ev->cookie),
144 name),
145 XCDR (watch_object));
146}
147
148/* This callback is called when the FD is available for read. The inotify
149 events are read from FD and converted into input_events. */
150static void
151inotify_callback (int fd, void *_)
152{
153 struct input_event event;
154 Lisp_Object watch_object;
155 int to_read;
156 char *buffer;
157 ssize_t n;
158 size_t i;
159
160 to_read = 0;
161 if (ioctl (fd, FIONREAD, &to_read) == -1)
162 report_file_error ("Error while trying to retrieve file system events",
163 Qnil);
164 buffer = xmalloc (to_read);
165 n = read (fd, buffer, to_read);
166 if (n < 0)
167 {
168 xfree (buffer);
169 report_file_error ("Error while trying to read file system events",
170 Qnil);
171 }
172
173 EVENT_INIT (event);
174 event.kind = FILE_NOTIFY_EVENT;
175 event.arg = Qnil;
176
177 i = 0;
178 while (i < (size_t)n)
179 {
180 struct inotify_event *ev = (struct inotify_event*)&buffer[i];
181
182 watch_object = Fassoc (make_watch_descriptor (ev->wd), watch_list);
183 if (!NILP (watch_object))
184 {
185 event.arg = inotifyevent_to_event (watch_object, ev);
186
187 /* If event was removed automatically: Drop it from watch list. */
188 if (ev->mask & IN_IGNORED)
189 watch_list = Fdelete (watch_object, watch_list);
190 }
191
192 i += sizeof (*ev) + ev->len;
193 }
194
195 if (!NILP (event.arg))
196 kbd_buffer_store_event (&event);
197
198 xfree (buffer);
199}
200
201static uint32_t
202symbol_to_inotifymask (Lisp_Object symb)
203{
204 if (EQ (symb, Qaccess))
205 return IN_ACCESS;
206 else if (EQ (symb, Qattrib))
207 return IN_ATTRIB;
208 else if (EQ (symb, Qclose_write))
209 return IN_CLOSE_WRITE;
210 else if (EQ (symb, Qclose_nowrite))
211 return IN_CLOSE_NOWRITE;
212 else if (EQ (symb, Qcreate))
213 return IN_CREATE;
214 else if (EQ (symb, Qdelete))
215 return IN_DELETE;
216 else if (EQ (symb, Qdelete_self))
217 return IN_DELETE_SELF;
218 else if (EQ (symb, Qmodify))
219 return IN_MODIFY;
220 else if (EQ (symb, Qmove_self))
221 return IN_MOVE_SELF;
222 else if (EQ (symb, Qmoved_from))
223 return IN_MOVED_FROM;
224 else if (EQ (symb, Qmoved_to))
225 return IN_MOVED_TO;
226 else if (EQ (symb, Qopen))
227 return IN_OPEN;
228 else if (EQ (symb, Qmove))
229 return IN_MOVE;
230 else if (EQ (symb, Qclose))
231 return IN_CLOSE;
232
233 else if (EQ (symb, Qdont_follow))
234 return IN_DONT_FOLLOW;
235 else if (EQ (symb, Qexcl_unlink))
236 return IN_EXCL_UNLINK;
237 else if (EQ (symb, Qmask_add))
238 return IN_MASK_ADD;
239 else if (EQ (symb, Qoneshot))
240 return IN_ONESHOT;
241 else if (EQ (symb, Qonlydir))
242 return IN_ONLYDIR;
243
244 else if (EQ (symb, Qt) || EQ (symb, Qall_events))
245 return IN_ALL_EVENTS;
246 else
247 signal_error ("Unknown aspect", symb);
248}
249
250static uint32_t
251aspect_to_inotifymask (Lisp_Object aspect)
252{
253 if (CONSP (aspect))
254 {
255 Lisp_Object x = aspect;
256 uint32_t mask = 0;
257 while (CONSP (x))
258 {
259 mask |= symbol_to_inotifymask (XCAR (x));
260 x = XCDR (x);
261 }
262 return mask;
263 }
264 else
265 return symbol_to_inotifymask (aspect);
266}
267
268DEFUN ("inotify-add-watch", Finotify_add_watch, Sinotify_add_watch, 3, 3, 0,
269 doc: /* Add a watch for FILE-NAME to inotify.
270
271A WATCH-DESCRIPTOR is returned on success. ASPECT might be one of the following
272symbols or a list of those symbols:
273
274access
275attrib
276close-write
277close-nowrite
278create
279delete
280delete-self
281modify
282move-self
283moved-from
284moved-to
285open
286
287all-events or t
288move
289close
290
291The following symbols can also be added to a list of aspects
292
293dont-follow
294excl-unlink
295mask-add
296oneshot
297onlydir
298
299Watching a directory is not recursive. CALLBACK gets called in case of an
300event. It gets passed a single argument EVENT which contains an event structure
301of the format
302
303(WATCH-DESCRIPTOR ASPECTS COOKIE NAME)
304
305WATCH-DESCRIPTOR is the same object that was returned by this function. It can
306be tested for equality using `equal'. ASPECTS describes the event. It is a
307list of ASPECT symbols described above and can also contain one of the following
308symbols
309
310ignored
311isdir
312q-overflow
313unmount
314
315COOKIE is an object that can be compared using `equal' to identify two matching
316renames (moved-from and moved-to).
317
318If a directory is watched then NAME is the name of file that caused the event.
319
320See inotify(7) and inotify_add_watch(2) for further information. The inotify fd
321is managed internally and there is no corresponding inotify_init. Use
322`inotify-rm-watch' to remove a watch.
323 */)
324 (Lisp_Object file_name, Lisp_Object aspect, Lisp_Object callback)
325{
326 uint32_t mask;
327 Lisp_Object watch_object;
328 Lisp_Object decoded_file_name;
329 Lisp_Object watch_descriptor;
330 int watchdesc = -1;
331
332 CHECK_STRING (file_name);
333
334 if (inotifyfd == uninitialized)
335 {
336 inotifyfd = inotify_init1 (IN_NONBLOCK|IN_CLOEXEC);
337 if (inotifyfd == -1)
338 {
339 inotifyfd = uninitialized;
340 report_file_error ("File watching feature (inotify) is not available",
341 Qnil);
342 }
343 watch_list = Qnil;
344 add_read_fd (inotifyfd, &inotify_callback, NULL);
345 }
346
347 mask = aspect_to_inotifymask (aspect);
348 decoded_file_name = ENCODE_FILE (file_name);
349 watchdesc = inotify_add_watch (inotifyfd, SSDATA (decoded_file_name), mask);
350 if (watchdesc == -1)
351 report_file_error ("Could not add watch for file", Fcons (file_name, Qnil));
352
353 watch_descriptor = make_watch_descriptor (watchdesc);
354
355 /* Delete existing watch object. */
356 watch_object = Fassoc (watch_descriptor, watch_list);
357 if (!NILP (watch_object))
358 watch_list = Fdelete (watch_object, watch_list);
359
360 /* Store watch object in watch list. */
361 watch_object = Fcons (watch_descriptor, callback);
362 watch_list = Fcons (watch_object, watch_list);
363
364 return watch_descriptor;
365}
366
367DEFUN ("inotify-rm-watch", Finotify_rm_watch, Sinotify_rm_watch, 1, 1, 0,
368 doc: /* Remove an existing WATCH-DESCRIPTOR.
369
370WATCH-DESCRIPTOR should be an object returned by `inotify-add-watch'.
371
372See inotify_rm_watch(2) for more information.
373 */)
374 (Lisp_Object watch_descriptor)
375{
376 Lisp_Object watch_object;
377 int wd = XINT (watch_descriptor);
378
379 if (inotify_rm_watch (inotifyfd, wd) == -1)
380 report_file_error ("Could not rm watch", Fcons (watch_descriptor,
381 Qnil));
382
383 /* Remove watch descriptor from watch list. */
384 watch_object = Fassoc (watch_descriptor, watch_list);
385 if (!NILP (watch_object))
386 watch_list = Fdelete (watch_object, watch_list);
387
388 /* Cleanup if no more files are watched. */
389 if (NILP (watch_list))
390 {
391 close (inotifyfd);
392 delete_read_fd (inotifyfd);
393 inotifyfd = uninitialized;
394 }
395
396 return Qt;
397}
398
399void
400syms_of_inotify (void)
401{
402 DEFSYM (Qaccess, "access");
403 DEFSYM (Qattrib, "attrib");
404 DEFSYM (Qclose_write, "close-write");
405 DEFSYM (Qclose_nowrite, "close-nowrite");
406 DEFSYM (Qcreate, "create");
407 DEFSYM (Qdelete, "delete");
408 DEFSYM (Qdelete_self, "delete-self");
409 DEFSYM (Qmodify, "modify");
410 DEFSYM (Qmove_self, "move-self");
411 DEFSYM (Qmoved_from, "moved-from");
412 DEFSYM (Qmoved_to, "moved-to");
413 DEFSYM (Qopen, "open");
414
415 DEFSYM (Qall_events, "all-events");
416 DEFSYM (Qmove, "move");
417 DEFSYM (Qclose, "close");
418
419 DEFSYM (Qdont_follow, "dont-follow");
420 DEFSYM (Qexcl_unlink, "excl-unlink");
421 DEFSYM (Qmask_add, "mask-add");
422 DEFSYM (Qoneshot, "oneshot");
423 DEFSYM (Qonlydir, "onlydir");
424
425 DEFSYM (Qignored, "ignored");
426 DEFSYM (Qisdir, "isdir");
427 DEFSYM (Qq_overflow, "q-overflow");
428 DEFSYM (Qunmount, "unmount");
429
430 defsubr (&Sinotify_add_watch);
431 defsubr (&Sinotify_rm_watch);
432
433 staticpro (&watch_list);
434
435 Fprovide (intern_c_string ("inotify"), Qnil);
436}
437
438#endif /* HAVE_INOTIFY */
diff --git a/src/keyboard.c b/src/keyboard.c
index fc155c5a5f7..4c484efe0c0 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -319,6 +319,9 @@ static Lisp_Object Qsave_session;
319#ifdef HAVE_DBUS 319#ifdef HAVE_DBUS
320static Lisp_Object Qdbus_event; 320static Lisp_Object Qdbus_event;
321#endif 321#endif
322#ifdef HAVE_INOTIFY
323static Lisp_Object Qfile_inotify;
324#endif /* HAVE_INOTIFY */
322static Lisp_Object Qconfig_changed_event; 325static Lisp_Object Qconfig_changed_event;
323 326
324/* Lisp_Object Qmouse_movement; - also an event header */ 327/* Lisp_Object Qmouse_movement; - also an event header */
@@ -3961,6 +3964,13 @@ kbd_buffer_get_event (KBOARD **kbp,
3961 kbd_fetch_ptr = event + 1; 3964 kbd_fetch_ptr = event + 1;
3962 } 3965 }
3963#endif 3966#endif
3967#ifdef HAVE_INOTIFY
3968 else if (event->kind == FILE_NOTIFY_EVENT)
3969 {
3970 obj = make_lispy_event (event);
3971 kbd_fetch_ptr = event + 1;
3972 }
3973#endif
3964 else if (event->kind == CONFIG_CHANGED_EVENT) 3974 else if (event->kind == CONFIG_CHANGED_EVENT)
3965 { 3975 {
3966 obj = make_lispy_event (event); 3976 obj = make_lispy_event (event);
@@ -5874,6 +5884,13 @@ make_lispy_event (struct input_event *event)
5874 } 5884 }
5875#endif /* HAVE_DBUS */ 5885#endif /* HAVE_DBUS */
5876 5886
5887#ifdef HAVE_INOTIFY
5888 case FILE_NOTIFY_EVENT:
5889 {
5890 return Fcons (Qfile_inotify, event->arg);
5891 }
5892#endif /* HAVE_INOTIFY */
5893
5877 case CONFIG_CHANGED_EVENT: 5894 case CONFIG_CHANGED_EVENT:
5878 return Fcons (Qconfig_changed_event, 5895 return Fcons (Qconfig_changed_event,
5879 Fcons (event->arg, 5896 Fcons (event->arg,
@@ -11337,6 +11354,10 @@ syms_of_keyboard (void)
11337 DEFSYM (Qdbus_event, "dbus-event"); 11354 DEFSYM (Qdbus_event, "dbus-event");
11338#endif 11355#endif
11339 11356
11357#ifdef HAVE_INOTIFY
11358 DEFSYM (Qfile_inotify, "file-inotify");
11359#endif /* HAVE_INOTIFY */
11360
11340 DEFSYM (QCenable, ":enable"); 11361 DEFSYM (QCenable, ":enable");
11341 DEFSYM (QCvisible, ":visible"); 11362 DEFSYM (QCvisible, ":visible");
11342 DEFSYM (QChelp, ":help"); 11363 DEFSYM (QChelp, ":help");
@@ -12093,6 +12114,13 @@ keys_of_keyboard (void)
12093 "dbus-handle-event"); 12114 "dbus-handle-event");
12094#endif 12115#endif
12095 12116
12117#ifdef HAVE_INOTIFY
12118 /* Define a special event which is raised for inotify callback
12119 functions. */
12120 initial_define_lispy_key (Vspecial_event_map, "file-inotify",
12121 "inotify-handle-event");
12122#endif /* HAVE_INOTIFY */
12123
12096 initial_define_lispy_key (Vspecial_event_map, "config-changed-event", 12124 initial_define_lispy_key (Vspecial_event_map, "config-changed-event",
12097 "ignore"); 12125 "ignore");
12098#if defined (WINDOWSNT) 12126#if defined (WINDOWSNT)
diff --git a/src/lisp.h b/src/lisp.h
index 91fc3dfa1c6..5acb37f08d1 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3516,6 +3516,11 @@ extern void syms_of_fontset (void);
3516extern Lisp_Object Qfont_param; 3516extern Lisp_Object Qfont_param;
3517#endif 3517#endif
3518 3518
3519/* Defined in inotify.c */
3520#ifdef HAVE_INOTIFY
3521extern void syms_of_inotify (void);
3522#endif
3523
3519/* Defined in xfaces.c. */ 3524/* Defined in xfaces.c. */
3520extern Lisp_Object Qdefault, Qtool_bar, Qfringe; 3525extern Lisp_Object Qdefault, Qtool_bar, Qfringe;
3521extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor; 3526extern Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
diff --git a/src/termhooks.h b/src/termhooks.h
index b35c927fc53..da65f9d6b74 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -211,6 +211,11 @@ enum event_kind
211 , NS_NONKEY_EVENT 211 , NS_NONKEY_EVENT
212#endif 212#endif
213 213
214#ifdef HAVE_INOTIFY
215 /* File or directory was changed. */
216 , FILE_NOTIFY_EVENT
217#endif
218
214}; 219};
215 220
216/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT 221/* If a struct input_event has a kind which is SELECTION_REQUEST_EVENT