]> git.eshelyaron.com Git - emacs.git/commitdiff
The TTY case is resolved: notifications now work even if Emacs
authorEli Zaretskii <eliz@gnu.org>
Fri, 12 Oct 2012 09:47:00 +0000 (11:47 +0200)
committerEli Zaretskii <eliz@gnu.org>
Fri, 12 Oct 2012 09:47:00 +0000 (11:47 +0200)
doesn't have focus.

src/w32console.c
src/w32notify.c
src/w32proc.c
src/w32term.h
src/w32xfns.c

index f0574689bf17feaf4e321efe7ab22702fcfc3aab..f201ff190c2a4bb324ad0fc9579cff7f7f7ccd1d 100644 (file)
@@ -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"));
index 595476356367a1bb64f5fc761ca120d013b96c72..bdfdf3472a08bf8033b78516f6e62a4fae66359c 100644 (file)
@@ -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;
index 7e8183b0e8225aecc7154807b911bb35f37729f1..d8d32e78d5ca94200787e784f15a9705cba19587 100644 (file)
@@ -1867,7 +1867,24 @@ count_children:
             (*) 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)
        {
index 6540d0f4d3d24aa73011cb429c45fa15212fab13..a3579c8ff60a5238b79612e7aac7da9e3d829374 100644 (file)
@@ -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 *);
index cb452571665e765a1b302d2bd58bf269348708d3..8820edda6c2608e23a53bd93eb2057ea5fccd7b7 100644 (file)
@@ -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.  */