mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-30 04:10:54 -08:00
Final version that supports only one watch at a time.
This commit is contained in:
parent
25d99a950d
commit
c5c91b847a
6 changed files with 94 additions and 57 deletions
|
|
@ -1,3 +1,7 @@
|
|||
2012-10-07 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* makefile.w32-in (obj): Add w32notify.o.
|
||||
|
||||
2012-10-01 Fabrice Popineau <fabrice.popineau@gmail.com>
|
||||
|
||||
* make-docfile.c (write_globals): Special-case
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
2012-10-07 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* subr.el (w32notify-handle-event): New function.
|
||||
|
||||
2012-10-07 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* mail/rmailmm.el (rmail-mime-process-multipart):
|
||||
|
|
|
|||
|
|
@ -1,3 +1,37 @@
|
|||
2012-10-07 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* w32term.h (WM_EMACS_FILENOTIFY): New custom message.
|
||||
(WM_EMACS_END): Bump value by 1.
|
||||
|
||||
* w32term.c (lispy_file_action, queue_notifications): New functions.
|
||||
(syms_of_w32term) <Qadded, Qremoved, Qmodified, Qrenamed_from>
|
||||
<Qrenamed_to>: New symbols.
|
||||
|
||||
* w32notify.c: New file, implement file event notifications for
|
||||
MS-Windows.
|
||||
|
||||
* w32fns.c (w32_wnd_proc): Handle the WM_EMACS_FILENOTIFY message
|
||||
by posting it to the w32_read_socket queue.
|
||||
|
||||
* termhooks.h (enum event_kind) [WINDOWSNT]: New event kind
|
||||
FILE_NOTIFY_EVENT.
|
||||
|
||||
* makefile.w32-in (OBJ2): Add $(BLD)/w32notify.$(O).
|
||||
(GLOBAL_SOURCES): Add w32notify.c
|
||||
($(BLD)/w32notify.$(O)): New set of dependencies.
|
||||
|
||||
* lisp.h (syms_of_w32notify) [WINDOWSNT]: Add prototype.
|
||||
|
||||
* keyboard.c (kbd_buffer_get_event) [WINDOWSNT]: Handle
|
||||
FILE_NOTIFY_EVENT.
|
||||
(syms_of_keyboard) [WINDOWSNT] <Qfile_notify>: New symbol.
|
||||
(keys_of_keyboard) [WINDOWSNT]: Bind file-notify to
|
||||
w32notify-handle-event by default.
|
||||
|
||||
* emacs.c (main) [WINDOWSNT]: Call syms_of_w32notify.
|
||||
|
||||
* alloc.c (NSTATICS): Enlarge to 0x660.
|
||||
|
||||
2012-10-07 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* nsterm.m (ns_dumpglyphs_image): Only draw slize of image (Bug#12506).
|
||||
|
|
|
|||
|
|
@ -2259,8 +2259,6 @@ w32_msg_pump (deferred_msg * msg_buf)
|
|||
|
||||
while ((w32_unicode_gui ? GetMessageW : GetMessageA) (&msg, NULL, 0, 0))
|
||||
{
|
||||
if (msg.message == WM_EMACS_FILENOTIFY)
|
||||
DebPrint (("w32_msg_pump: File notification, hwnd = 0x%p\n", msg.hwnd));
|
||||
if (msg.hwnd == NULL)
|
||||
{
|
||||
switch (msg.message)
|
||||
|
|
@ -3810,7 +3808,6 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
return retval;
|
||||
}
|
||||
case WM_EMACS_FILENOTIFY:
|
||||
DebPrint (("w32_wnd_proc: File notification arrived, posting\n"));
|
||||
my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
|
||||
return 1;
|
||||
|
||||
|
|
|
|||
102
src/w32notify.c
102
src/w32notify.c
|
|
@ -16,6 +16,54 @@ 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/>. */
|
||||
|
||||
/* Design overview:
|
||||
|
||||
For each watch request, we launch a separate worker thread. The
|
||||
worker thread runs the watch_worker function, which issues an
|
||||
asynchronous call to ReadDirectoryChangesW, and then waits for that
|
||||
call to complete in SleepEx. Waiting in SleepEx puts the thread in
|
||||
an alertable state, so it wakes up when either (a) the call to
|
||||
ReadDirectoryChangesW completes, or (b) the main thread instructs
|
||||
the worker thread to terminate by sending it an APC, see below.
|
||||
|
||||
When the ReadDirectoryChangesW call completes, its completion
|
||||
routine watch_completion is automatically called. watch_completion
|
||||
stashes the received file events in a buffer used to communicate
|
||||
them to the main thread (using a critical section, so that several
|
||||
threads could use the same buffer), posts a special message,
|
||||
WM_EMACS_FILENOTIFY, to the Emacs's message queue, and returns.
|
||||
That causes the SleepEx function call inside watch_worker to
|
||||
return, and watch_worker then issues another call to
|
||||
ReadDirectoryChangesW. (Except when it does not, see below.)
|
||||
|
||||
The WM_EMACS_FILENOTIFY message, posted to the message queue gets
|
||||
dispatched to the main Emacs window procedure, which queues it for
|
||||
processing by w32_read_socket. When w32_read_socket sees this
|
||||
message, it accesses the buffer with file notifications (using a
|
||||
critical section), extracts the information, converts it to a
|
||||
series of FILE_NOTIFY_EVENT events, and stuffs them into the input
|
||||
event queue to be processed by keyboard.c input machinery
|
||||
(read_char via a call to kbd_buffer_get_event). When the
|
||||
FILE_NOTIFY_EVENT event is processed by kbd_buffer_get_event, it is
|
||||
converted to a Lispy event that can be bound to a command. The
|
||||
default binding is w32notify-handle-event, defined on subr.el.
|
||||
|
||||
After w32_read_socket is done processing the notifications, it
|
||||
resets a flag signaling to all watch worker threads that the
|
||||
notifications buffer is available for more input.
|
||||
|
||||
When the watch is removed by a call to w32notify-rm-watch, the main
|
||||
thread requests that the worker thread terminates by queuing an APC
|
||||
for the worker thread. The APC specifies the watch_end function to
|
||||
be called. watch_end calls CancelIo on the outstanding
|
||||
ReadDirectoryChangesW call and closes the handle on which the
|
||||
watched directory was open. When watch_end returns, the
|
||||
watch_completion function is called one last time with the
|
||||
ERROR_OPERATION_ABORTED status, which causes it to clean up and set
|
||||
a flag telling watch_worker to exit without issuing another
|
||||
ReadDirectoryChangesW call. The main thread waits for the worker
|
||||
thread to exit, and if it doesn't, terminate it forcibly. */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
|
@ -58,51 +106,6 @@ static Lisp_Object Qfile_name, Qdirectory_name, Qattributes, Qsize;
|
|||
static Lisp_Object Qlast_write_time, Qlast_access_time, Qcreation_time;
|
||||
static Lisp_Object Qsecurity_desc, Qsubtree, watch_list;
|
||||
|
||||
#if 0
|
||||
/* FIXME: Debugging code, should be removed eventually. */
|
||||
const wchar_t *
|
||||
format_file_action (DWORD action)
|
||||
{
|
||||
static const wchar_t *action_str[] =
|
||||
{ L"???", L"Added", L"Removed", L"Modified", L"Renamed from", L"Renamed to" };
|
||||
|
||||
if (action >= sizeof(action_str)/sizeof(action_str[0]))
|
||||
action = 0;
|
||||
return action_str[action];
|
||||
}
|
||||
|
||||
void
|
||||
parse_notifications (BYTE *info, DWORD info_size)
|
||||
{
|
||||
BYTE *p = info;
|
||||
FILE_NOTIFY_INFORMATION *fni = (PFILE_NOTIFY_INFORMATION)p;
|
||||
const DWORD min_size
|
||||
= offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
|
||||
|
||||
if (!info_size)
|
||||
{
|
||||
printf ("No info in notifications!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (info_size >= min_size)
|
||||
{
|
||||
wchar_t *fn = alloca (fni->FileNameLength + sizeof(wchar_t));
|
||||
const wchar_t *action_str;
|
||||
|
||||
memcpy (fn, fni->FileName, fni->FileNameLength);
|
||||
fn[fni->FileNameLength/sizeof(wchar_t)] = 0;
|
||||
action_str = format_file_action (fni->Action);
|
||||
wprintf (L"%s: %s\n", action_str, fn);
|
||||
if (!fni->NextEntryOffset)
|
||||
break;
|
||||
p += fni->NextEntryOffset;
|
||||
fni = (PFILE_NOTIFY_INFORMATION)p;
|
||||
info_size -= fni->NextEntryOffset;
|
||||
}
|
||||
}
|
||||
#endif /* debugging code */
|
||||
|
||||
/* Signal to the main thread that we have file notifications for it to
|
||||
process. */
|
||||
static void
|
||||
|
|
@ -141,7 +144,6 @@ send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate)
|
|||
if (PostMessage (FRAME_W32_WINDOW (f), WM_EMACS_FILENOTIFY, 0, 0))
|
||||
notification_buffer_in_use = 1;
|
||||
done = 1;
|
||||
DebPrint (("Announced notifications of %lu bytes\n", info_size));
|
||||
}
|
||||
leave_crit ();
|
||||
if (!done)
|
||||
|
|
@ -205,9 +207,6 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if 0 /* debugging code */
|
||||
parse_notifications (dirwatch->buf, bytes_ret);
|
||||
#endif
|
||||
/* Tell the main thread we have notifications for it. */
|
||||
send_notifications (dirwatch->buf, bytes_ret, dirwatch->dir,
|
||||
&dirwatch->terminate);
|
||||
|
|
@ -233,7 +232,7 @@ watch_worker (LPVOID arg)
|
|||
dirwatch->io_info, watch_completion);
|
||||
if (!status)
|
||||
{
|
||||
DebPrint (("watch_worker(1): %lu\n", GetLastError ()));
|
||||
DebPrint (("watch_worker, abnormal exit: %lu\n", GetLastError ()));
|
||||
xfree (dirwatch->buf);
|
||||
dirwatch->buf = NULL;
|
||||
xfree (dirwatch->io_info);
|
||||
|
|
@ -249,11 +248,8 @@ watch_worker (LPVOID arg)
|
|||
could be either a change notification or a cancellation of the
|
||||
watch. */
|
||||
sleep_result = SleepEx (INFINITE, TRUE);
|
||||
if (dirwatch->terminate)
|
||||
DebPrint (("watch_worker: exiting by request\n"));
|
||||
} while (!dirwatch->terminate);
|
||||
|
||||
DebPrint (("watch_worker(2): %lu\n", GetLastError ()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3204,6 +3204,9 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
/* File event notifications (see w32notify.c). */
|
||||
|
||||
static Lisp_Object
|
||||
lispy_file_action (DWORD action)
|
||||
{
|
||||
|
|
@ -4945,7 +4948,6 @@ w32_read_socket (struct terminal *terminal,
|
|||
break;
|
||||
|
||||
case WM_EMACS_FILENOTIFY:
|
||||
DebPrint (("w32_read_socket: File notification arrived\n"));
|
||||
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
|
||||
if (f)
|
||||
queue_notifications (&inev, &msg, f, &count);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue