Commit 977c6479 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

The TTY case is resolved: notifications now work even if Emacs

doesn't have focus.
parent 0dc9ee4a
......@@ -746,6 +746,9 @@ initialize_w32_display (struct terminal *term)
else
w32_console_unicode_input = 0;
/* This is needed by w32notify.c:send_notifications. */
dwMainThreadId = GetCurrentThreadId ();
/* Setup w32_display_info structure for this frame. */
w32_initialize_display_info (build_string ("Console"));
......
......@@ -36,21 +36,32 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
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.
In a GUI session, 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).
In a non-GUI session, we send the WM_EMACS_FILENOTIFY message to
the main (a.k.a. "Lisp") thread instead, since there are no window
procedures in console programs. That message wakes up
MsgWaitForMultipleObjects inside sys_select, which then signals to
its caller that some keyboard input is available. This causes
w32_console_read_socket to be called, which accesses the buffer
with file notifications and stuffs them into the input event queue
for keyboard.c to process.
When the FILE_NOTIFY_EVENT event is processed by keyboard.c's
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 or w32_console_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
......@@ -134,12 +145,19 @@ send_notifications (BYTE *info, DWORD info_size, HANDLE hdir, int *terminate)
memcpy (file_notifications, info, info_size);
notifications_size = info_size;
notifications_desc = hdir;
if (FRAME_TERMCAP_P (f)
/* If PostMessage fails, the message queue is full. If that
happens, the last thing they will worry about is file
notifications. So we effectively discard the
notification in that case. */
if ((FRAME_TERMCAP_P (f)
/* We send the message to the main (a.k.a. "Lisp")
thread, where it will wake up MsgWaitForMultipleObjects
inside sys_select, causing it to report that there's
some keyboard input available. This will in turn cause
w32_console_read_socket to be called, which will pick
up the file notifications. */
&& PostThreadMessage (dwMainThreadId, WM_EMACS_FILENOTIFY, 0, 0))
|| (FRAME_W32_P (f)
/* If PostMessage fails, the message queue is full.
If that happens, the last thing they will worry
about is file notifications. So we effectively
discard the notification in that case. */
&& PostMessage (FRAME_W32_WINDOW (f),
WM_EMACS_FILENOTIFY, 0, 0)))
notification_buffer_in_use = 1;
......
......@@ -1867,7 +1867,24 @@ sys_select (int nfds, SELECT_TYPE *rfds, SELECT_TYPE *wfds, SELECT_TYPE *efds,
(*) Note that MsgWaitForMultipleObjects above is an
internal dispatch point for messages that are sent to
windows created by this thread. */
drain_message_queue ();
if (drain_message_queue ()
/* If drain_message_queue returns non-zero, that means
we received a WM_EMACS_FILENOTIFY message. If this
is a TTY frame, we must signal the caller that keyboard
input is available, so that w32_console_read_socket
will be called to pick up the notifications. If we
don't do that, file notifications will only work when
the Emacs TTY frame has focus. */
&& FRAME_TERMCAP_P (SELECTED_FRAME ())
/* they asked for stdin reads */
&& FD_ISSET (0, &orfds)
/* the stdin handle is valid */
&& keyboard_handle)
{
FD_SET (0, rfds);
if (nr == 0)
nr = 1;
}
}
else if (active >= nh)
{
......
......@@ -672,7 +672,7 @@ extern void deselect_palette (struct frame * f, HDC hdc);
extern HDC get_frame_dc (struct frame * f);
extern int release_frame_dc (struct frame * f, HDC hDC);
extern void drain_message_queue (void);
extern int drain_message_queue (void);
extern BOOL get_next_msg (W32Msg *, BOOL);
extern BOOL post_msg (W32Msg *);
......
......@@ -315,16 +315,22 @@ prepend_msg (W32Msg *lpmsg)
return (TRUE);
}
/* Process all messages in the current thread's queue. */
void
/* Process all messages in the current thread's queue. Value is 1 if
one of these messages was WM_EMACS_FILENOTIFY, zero otherwise. */
int
drain_message_queue (void)
{
MSG msg;
int retval = 0;
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_EMACS_FILENOTIFY)
retval = 1;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return retval;
}
/* x_sync is a no-op on W32. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment