Drop FRAME_PTR typedef.
[bpt/emacs.git] / src / w32inevt.c
index 9b63d0c..ce36f29 100644 (file)
@@ -1,5 +1,6 @@
 /* Input event support for Emacs on the Microsoft Windows API.
-   Copyright (C) 1992-1993, 1995, 2001-2012  Free Software Foundation, Inc.
+   Copyright (C) 1992-1993, 1995, 2001-2013 Free Software Foundation,
+   Inc.
 
 This file is part of GNU Emacs.
 
@@ -102,10 +103,10 @@ fill_queue (BOOL block)
 }
 
 /* In a generic, multi-frame world this should take a console handle
-   and return the frame for it
+   and return the frame for it.
 
    Right now, there's only one frame so return it.  */
-static FRAME_PTR
+static struct frame *
 get_frame (void)
 {
   return SELECTED_FRAME ();
@@ -393,7 +394,7 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 
 /* Mouse position hook.  */
 void
-w32_console_mouse_position (FRAME_PTR *f,
+w32_console_mouse_position (struct frame **f,
                            int insist,
                            Lisp_Object *bar_window,
                            enum scroll_bar_part *part,
@@ -460,7 +461,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 
   if (event->dwEventFlags == MOUSE_MOVED)
     {
-      FRAME_PTR f = SELECTED_FRAME ();
+      struct frame *f = SELECTED_FRAME ();
       Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
       int mx = event->dwMousePosition.X, my = event->dwMousePosition.Y;
 
@@ -554,7 +555,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 static void
 resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
 {
-  FRAME_PTR f = get_frame ();
+  struct frame *f = get_frame ();
 
   change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
   SET_FRAME_GARBAGED (f);
@@ -564,7 +565,7 @@ static void
 maybe_generate_resize_event (void)
 {
   CONSOLE_SCREEN_BUFFER_INFO info;
-  FRAME_PTR f = get_frame ();
+  struct frame *f = get_frame ();
 
   GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
 
@@ -576,7 +577,8 @@ maybe_generate_resize_event (void)
                     0, 0, 0);
 }
 
-static void
+#if HAVE_W32NOTIFY
+static int
 handle_file_notifications (struct input_event *hold_quit)
 {
   BYTE *p = file_notifications;
@@ -584,26 +586,32 @@ handle_file_notifications (struct input_event *hold_quit)
   const DWORD min_size
     = offsetof (FILE_NOTIFY_INFORMATION, FileName) + sizeof(wchar_t);
   struct input_event inev;
+  int nevents = 0;
 
   /* We cannot process notification before Emacs is fully initialized,
      since we need the UTF-16LE coding-system to be set up.  */
   if (!initialized)
     {
       notification_buffer_in_use = 0;
-      return;
+      return nevents;
     }
 
   enter_crit ();
   if (notification_buffer_in_use)
     {
       DWORD info_size = notifications_size;
+      Lisp_Object cs = intern ("utf-16le");
+      Lisp_Object obj = w32_get_watch_object (notifications_desc);
 
       /* notifications_size could be zero when the buffer of
         notifications overflowed on the OS level, or when the
         directory being watched was itself deleted.  Do nothing in
         that case.  */
-      if (info_size)
+      if (info_size
+         && !NILP (obj) && CONSP (obj))
        {
+         Lisp_Object callback = XCDR (obj);
+
          EVENT_INIT (inev);
 
          while (info_size >= min_size)
@@ -614,22 +622,16 @@ handle_file_notifications (struct input_event *hold_quit)
              /* Note: mule-conf is preloaded, so utf-16le must
                 already be defined at this point.  */
              Lisp_Object fname
-               = code_convert_string_norecord (utf_16_fn,
-                                               intern ("utf-16le"), 0);
+               = code_convert_string_norecord (utf_16_fn, cs, 0);
              Lisp_Object action = lispy_file_action (fni->Action);
-             Lisp_Object obj;
 
-             obj = get_watch_object (make_number (notifications_desc));
-             if (!NILP (obj) && CONSP (obj))
-               {
-                 inev.kind = FILE_NOTIFY_EVENT;
-                 inev.code = (ptrdiff_t)notifications_desc;
-                 inev.timestamp = GetTickCount ();
-                 inev.modifiers = 0;
-                 inev.frame_or_window = XCDR (obj);
-                 inev.arg = Fcons (action, fname);
-                 kbd_buffer_store_event_hold (&inev, hold_quit);
-               }
+             inev.kind = FILE_NOTIFY_EVENT;
+             inev.code = (ptrdiff_t)XINT (XIL ((EMACS_INT)notifications_desc));
+             inev.timestamp = GetTickCount ();
+             inev.modifiers = 0;
+             inev.frame_or_window = callback;
+             inev.arg = Fcons (action, fname);
+             kbd_buffer_store_event_hold (&inev, hold_quit);
 
              if (!fni->NextEntryOffset)
                break;
@@ -641,7 +643,47 @@ handle_file_notifications (struct input_event *hold_quit)
       notification_buffer_in_use = 0;
     }
   leave_crit ();
+  return nevents;
 }
+#else  /* !HAVE_W32NOTIFY */
+static int
+handle_file_notifications (struct input_event *hold_quit)
+{
+  return 0;
+}
+#endif /* !HAVE_W32NOTIFY */
+
+/* Here's an overview of how Emacs input works in non-GUI sessions on
+   MS-Windows.  (For description of the GUI input, see the commentary
+   before w32_msg_pump in w32fns.c.)
+
+   When Emacs is idle, it loops inside wait_reading_process_output,
+   calling pselect periodically to check whether any input is
+   available.  On Windows, pselect is redirected to sys_select, which
+   uses MsgWaitForMultipleObjects to wait for input, either from the
+   keyboard or from any of the Emacs subprocesses.  In addition,
+   MsgWaitForMultipleObjects wakes up when some Windows message is
+   posted to the input queue of the Emacs's main thread (which is the
+   thread in which sys_select runs).
+
+   When the Emacs's console window has focus, Windows sends input
+   events that originate from the keyboard or the mouse; these events
+   wake up MsgWaitForMultipleObjects, which reports that input is
+   available.  Emacs then calls w32_console_read_socket, below, to
+   read the input.  w32_console_read_socket uses
+   GetNumberOfConsoleInputEvents and ReadConsoleInput to peek at and
+   read the console input events.
+
+   One type of non-keyboard input event that gets reported as input
+   available is due to the Emacs's console window receiving focus.
+   When that happens, Emacs gets the FOCUS_EVENT event and sys_select
+   reports some input; however, w32_console_read_socket ignores such
+   events when called to read them.
+
+   Note that any other Windows message sent to the main thread will
+   also wake up MsgWaitForMultipleObjects.  These messages get
+   immediately dispatched to their destinations by calling
+   drain_message_queue.  */
 
 int
 w32_console_read_socket (struct terminal *terminal,
@@ -654,13 +696,16 @@ w32_console_read_socket (struct terminal *terminal,
 
   for (;;)
     {
-      handle_file_notifications (hold_quit);
+      int nfnotify = handle_file_notifications (hold_quit);
+
       nev = fill_queue (0);
       if (nev <= 0)
         {
          /* If nev == -1, there was some kind of error
-            If nev == 0 then waitp must be zero and no events were available
+            If nev == 0 then no events were available
             so return.  */
+         if (nfnotify)
+           nev = 0;
          break;
         }