XEmacs 21.2.19 "Shinjuku".
[chise/xemacs-chise.git.1] / src / event-msw.c
index e6e87d1..45e77ee 100644 (file)
@@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA.  */
    Ultimately based on FSF.
    Rewritten by Ben Wing.
    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
    Ultimately based on FSF.
    Rewritten by Ben Wing.
    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
+   Subprocess and modal loop support by Kirill M. Katsnelson.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
@@ -50,6 +51,8 @@ Boston, MA 02111-1307, USA.  */
 #include "device.h"
 #include "events.h"
 #include "frame.h"
 #include "device.h"
 #include "events.h"
 #include "frame.h"
+#include "buffer.h"
+#include "faces.h"
 #include "lstream.h"
 #include "process.h"
 #include "redisplay.h"
 #include "lstream.h"
 #include "process.h"
 #include "redisplay.h"
@@ -57,16 +60,22 @@ Boston, MA 02111-1307, USA.  */
 #include "syswait.h"
 #include "systime.h"
 #include "sysdep.h"
 #include "syswait.h"
 #include "systime.h"
 #include "sysdep.h"
+#include "objects-msw.h"
 
 #include "events-mod.h"
 #ifdef HAVE_MSG_SELECT
 #include "sysfile.h"
 
 #include "events-mod.h"
 #ifdef HAVE_MSG_SELECT
 #include "sysfile.h"
+#include "console-tty.h"
 #elif defined(__CYGWIN32__)
 typedef unsigned int SOCKET;
 #endif
 #include <io.h>
 #include <errno.h>
 
 #elif defined(__CYGWIN32__)
 typedef unsigned int SOCKET;
 #endif
 #include <io.h>
 #include <errno.h>
 
+#if defined (__CYGWIN32__) && !defined (CYGWIN_VERSION_DLL_MAJOR)
+typedef NMHDR *LPNMHDR;
+#endif
+
 #ifdef HAVE_MENUBARS
 #define ADJR_MENUFLAG TRUE
 #else
 #ifdef HAVE_MENUBARS
 #define ADJR_MENUFLAG TRUE
 #else
@@ -84,6 +93,8 @@ extern Lisp_Object
 mswindows_get_toolbar_button_text (struct frame* f, int command_id);
 extern Lisp_Object
 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
 mswindows_get_toolbar_button_text (struct frame* f, int command_id);
 extern Lisp_Object
 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
+extern Lisp_Object
+mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id);
 
 static Lisp_Object mswindows_find_frame (HWND hwnd);
 static Lisp_Object mswindows_find_console (HWND hwnd);
 
 static Lisp_Object mswindows_find_frame (HWND hwnd);
 static Lisp_Object mswindows_find_console (HWND hwnd);
@@ -115,11 +126,16 @@ static Lisp_Object mswindows_s_dispatch_event_queue, mswindows_s_dispatch_event_
 /* The number of things we can wait on */
 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1)
 
 /* The number of things we can wait on */
 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1)
 
+#ifndef HAVE_MSG_SELECT
 /* List of mswindows waitable handles. */
 static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
 
 /* Number of wait handles */
 static int mswindows_waitable_count=0;
 /* List of mswindows waitable handles. */
 static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
 
 /* Number of wait handles */
 static int mswindows_waitable_count=0;
+#endif /* HAVE_MSG_SELECT */
+/* Brush for painting widgets */
+static HBRUSH widget_brush = 0;
+static LONG    last_widget_brushed = 0;
 
 /* Count of quit chars currently in the queue */
 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc()
 
 /* Count of quit chars currently in the queue */
 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc()
@@ -470,6 +486,7 @@ struct ntpipe_shove_stream
 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove,
                               sizeof (struct ntpipe_shove_stream));
 
 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove,
                               sizeof (struct ntpipe_shove_stream));
 
+#ifndef HAVE_MSG_SELECT
 static DWORD WINAPI
 shove_thread (LPVOID vparam)
 {
 static DWORD WINAPI
 shove_thread (LPVOID vparam)
 {
@@ -541,6 +558,7 @@ get_ntpipe_output_stream_param (Lstream *stream)
   struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
   return s->user_data;
 }
   struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
   return s->user_data;
 }
+#endif
 
 static int
 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
 
 static int
 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
@@ -939,6 +957,13 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT message, POINTS where, DWO
     {
       event->event_type = button_press_event;
       SetCapture (hwnd);
     {
       event->event_type = button_press_event;
       SetCapture (hwnd);
+      /* we need this to make sure the main window regains the focus
+         from control subwindows */
+      if (GetFocus() != hwnd)
+       {
+         SetFocus (hwnd);
+         mswindows_enqueue_magic_event (hwnd, WM_SETFOCUS);
+       }
     }
   else
     {
     }
   else
     {
@@ -997,18 +1022,18 @@ mswindows_dequeue_dispatch_event ()
 
 /*
  * Remove and return the first emacs event on the dispatch queue that matches
 
 /*
  * Remove and return the first emacs event on the dispatch queue that matches
- * the supplied event
- * Timeout event matches if interval_id equals to that of the given event.
+ * the supplied event.
+ * Timeout event matches if interval_id is equal to that of the given event.
  * Keypress event matches if logical AND between modifiers bitmask of the
  * Keypress event matches if logical AND between modifiers bitmask of the
- * event in the queue and that of the given event is non-zero
- * For all other event types, this function asserts.
+ * event in the queue and that of the given event is non-zero.
+ * For all other event types, this function aborts.
  */
 
 Lisp_Object
  */
 
 Lisp_Object
-mswindows_cancel_dispatch_event (struct Lisp_Event* match)
+mswindows_cancel_dispatch_event (struct Lisp_Event *match)
 {
   Lisp_Object event;
 {
   Lisp_Object event;
-  Lisp_Object previous_event=Qnil;
+  Lisp_Object previous_event = Qnil;
   int user_p = mswindows_user_event_p (match);
   Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : 
                               &mswindows_s_dispatch_event_queue;
   int user_p = mswindows_user_event_p (match);
   Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : 
                               &mswindows_s_dispatch_event_queue;
@@ -1020,19 +1045,12 @@ mswindows_cancel_dispatch_event (struct Lisp_Event* match)
 
   EVENT_CHAIN_LOOP (event, *head)
     {
 
   EVENT_CHAIN_LOOP (event, *head)
     {
-      int found = 1;
-      if (XEVENT_TYPE (event) != match->event_type)
-       found = 0;
-      if (found && match->event_type == timeout_event
-         && (XEVENT(event)->event.timeout.interval_id !=
-             match->event.timeout.interval_id))
-       found = 0;
-      if (found && match->event_type == key_press_event
-         && ((XEVENT(event)->event.key.modifiers &
-             match->event.key.modifiers) == 0))
-       found = 0;
-
-      if (found)
+      struct Lisp_Event *e = XEVENT (event);
+      if ((e->event_type == match->event_type) &&
+         ((e->event_type == timeout_event) ?
+          (e->event.timeout.interval_id == match->event.timeout.interval_id) :
+          /* Must be key_press_event */
+          ((e->event.key.modifiers & match->event.key.modifiers) != 0)))
        {
          if (NILP (previous_event))
            dequeue_event (head, tail);
        {
          if (NILP (previous_event))
            dequeue_event (head, tail);
@@ -1050,6 +1068,7 @@ mswindows_cancel_dispatch_event (struct Lisp_Event* match)
   return Qnil;
 }
 \f
   return Qnil;
 }
 \f
+#ifndef HAVE_MSG_SELECT
 /************************************************************************/
 /*                     Waitable handles manipulation                    */
 /************************************************************************/
 /************************************************************************/
 /*                     Waitable handles manipulation                    */
 /************************************************************************/
@@ -1085,6 +1104,7 @@ remove_waitable_handle (HANDLE h)
   mswindows_waitable_handles [ix] = 
     mswindows_waitable_handles [--mswindows_waitable_count];
 }
   mswindows_waitable_handles [ix] = 
     mswindows_waitable_handles [--mswindows_waitable_count];
 }
+#endif /* HAVE_MSG_SELECT */
 
 \f
 /************************************************************************/
 
 \f
 /************************************************************************/
@@ -1214,6 +1234,14 @@ mswindows_drain_windows_queue ()
   MSG msg;
   while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     {
   MSG msg;
   while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     {
+      /* we have to translate messages that are not sent to the main
+         window. this is so that key presses work ok in things like
+         edit fields. however, we *musn't* translate message for the
+         main window as this is handled in the wnd proc. */
+      if ( GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD )
+       {
+         TranslateMessage (&msg);
+       }
       DispatchMessage (&msg);
       mswindows_unmodalize_signal_maybe ();
     }
       DispatchMessage (&msg);
       mswindows_unmodalize_signal_maybe ();
     }
@@ -1299,32 +1327,11 @@ mswindows_need_event (int badly_p)
          pointer_to_this = &select_time_to_block;
        }
 
          pointer_to_this = &select_time_to_block;
        }
 
-      /* select() is slow and buggy so if we don't have any processes
-         just wait as normal */
-      if (memcmp (&process_only_mask, &zero_mask, sizeof(SELECT_TYPE))==0)
-       {
-         /* Now try getting a message or process event */
-         active = MsgWaitForMultipleObjects (0, mswindows_waitable_handles,
-                                             FALSE, badly_p ? INFINITE : 0,
-                                             QS_ALLINPUT);
-         
-         if (active == WAIT_TIMEOUT)
-           {
-             /* No luck trying - just return what we've already got */
-             return;
-           }
-         else if (active == WAIT_OBJECT_0)
-           {
-             /* Got your message, thanks */
-             mswindows_drain_windows_queue ();
-             continue;
-           }
-       }
-
       active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
       
       if (active == 0)
        {
       active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
       
       if (active == 0)
        {
+         assert (!badly_p);
          return;               /* timeout */
        }
       else if (active > 0)
          return;               /* timeout */
        }
       else if (active > 0)
@@ -1333,7 +1340,28 @@ mswindows_need_event (int badly_p)
            {
              mswindows_drain_windows_queue ();
            }
            {
              mswindows_drain_windows_queue ();
            }
-         
+#ifdef HAVE_TTY          
+         /* Look for a TTY event */
+         for (i = 0; i < MAXDESC-1; i++)
+           {
+             /* To avoid race conditions (among other things, an infinite
+                loop when called from Fdiscard_input()), we must return
+                user events ahead of process events. */
+             if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask))
+               {
+                 struct console *c = tty_find_console_from_fd (i);
+                 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
+                 struct Lisp_Event* event = XEVENT (emacs_event);
+                 
+                 assert (c);
+                 if (read_event_from_tty_or_stream_desc (event, c, i))
+                   {
+                     mswindows_enqueue_dispatch_event (emacs_event);
+                     return;
+                   }
+               }
+           }
+#endif
          /* Look for a process event */
          for (i = 0; i < MAXDESC-1; i++)
            {
          /* Look for a process event */
          for (i = 0; i < MAXDESC-1; i++)
            {
@@ -1346,11 +1374,6 @@ mswindows_need_event (int badly_p)
                      
                      mswindows_enqueue_process_event (p);
                    }
                      
                      mswindows_enqueue_process_event (p);
                    }
-                 else if (FD_ISSET (i, &tty_only_mask))
-                   {
-                               /* do we care about tty events? Do we
-                                   ever get tty events? */
-                   }
                  else
                    {
                      /* We might get here when a fake event came
                  else
                    {
                      /* We might get here when a fake event came
@@ -1446,6 +1469,8 @@ mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
   event->timestamp = dwtime;
   event->event_type = timeout_event;
   event->event.timeout.interval_id = id_timer;
   event->timestamp = dwtime;
   event->event_type = timeout_event;
   event->event.timeout.interval_id = id_timer;
+  event->event.timeout.function = Qnil;
+  event->event.timeout.object = Qnil;
 
   mswindows_enqueue_dispatch_event (emacs_event);
 }
 
   mswindows_enqueue_dispatch_event (emacs_event);
 }
@@ -1646,7 +1671,15 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        {
          int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
          BYTE keymap_orig[256];
        {
          int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
          BYTE keymap_orig[256];
-         MSG msg = { hwnd, message, wParam, lParam, GetMessageTime(), (GetMessagePos()) };
+         POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
+         MSG msg;
+         
+         msg.hwnd = hwnd;
+         msg.message = message;
+         msg.wParam = wParam;
+         msg.lParam = lParam;
+         msg.time = GetMessageTime();
+         msg.pt = pnt;
 
          /* GetKeyboardState() does not work as documented on Win95. We have
           * to loosely track Left and Right modifiers on behalf of the OS,
 
          /* GetKeyboardState() does not work as documented on Win95. We have
           * to loosely track Left and Right modifiers on behalf of the OS,
@@ -1897,17 +1930,20 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                       Qcancel_mode_internal, Qnil);
     break;
 
                                       Qcancel_mode_internal, Qnil);
     break;
 
-#ifdef HAVE_TOOLBARS
   case WM_NOTIFY:
     {
   case WM_NOTIFY:
     {
-      LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
-      Lisp_Object btext;
-      if (tttext->hdr.code ==  TTN_NEEDTEXT)    
+      LPNMHDR nmhdr = (LPNMHDR)lParam;
+
+      if (nmhdr->code ==  TTN_NEEDTEXT)
        {
        {
+#ifdef HAVE_TOOLBARS
+         LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam;
+         Lisp_Object btext;
+
          /* find out which toolbar */
          frame = XFRAME (mswindows_find_frame (hwnd));
          btext = mswindows_get_toolbar_button_text ( frame, 
          /* find out which toolbar */
          frame = XFRAME (mswindows_find_frame (hwnd));
          btext = mswindows_get_toolbar_button_text ( frame, 
-                                                     tttext->hdr.idFrom );
+                                                     nmhdr->idFrom );
          
          tttext->lpszText = NULL;
          tttext->hinst = NULL;
          
          tttext->lpszText = NULL;
          tttext->hinst = NULL;
@@ -1916,15 +1952,33 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
              /* I think this is safe since the text will only go away
                  when the toolbar does...*/
            {
              /* I think this is safe since the text will only go away
                  when the toolbar does...*/
-             tttext->lpszText=XSTRING_DATA (btext);
+             GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS, 
+                                           tttext->lpszText);
            }
            }
-#if 0
-         tttext->uFlags |= TTF_DI_SETITEM;
 #endif
 #endif
-       }    
+       }
+      /* handle tree view callbacks */
+      else if (nmhdr->code == TVN_SELCHANGED)
+       {
+         NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam;
+         frame = XFRAME (mswindows_find_frame (hwnd));
+         mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam);
+       }
+      /* handle tab control callbacks */
+      else if (nmhdr->code == TCN_SELCHANGE)
+       {
+         TC_ITEM item;
+         int index = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
+         frame = XFRAME (mswindows_find_frame (hwnd));
+
+         item.mask = TCIF_PARAM;
+         SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)index,
+                      (LPARAM)&item);
+         
+         mswindows_handle_gui_wm_command (frame, 0, item.lParam);
+       }
     }
     break;
     }
     break;
-#endif
     
   case WM_PAINT:
     {
     
   case WM_PAINT:
     {
@@ -2113,6 +2167,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_COMMAND:
     {
       WORD id = LOWORD (wParam);
   case WM_COMMAND:
     {
       WORD id = LOWORD (wParam);
+      WORD nid = HIWORD (wParam);
       HWND cid = (HWND)lParam;
       frame = XFRAME (mswindows_find_frame (hwnd));
 
       HWND cid = (HWND)lParam;
       frame = XFRAME (mswindows_find_frame (hwnd));
 
@@ -2120,17 +2175,85 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
        break;
 #endif
       if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
        break;
 #endif
-
+      /* widgets in a buffer only eval a callback for suitable events.*/
+      switch (nid)
+       {
+       case BN_CLICKED:
+       case EN_CHANGE:
+       case CBN_EDITCHANGE:
+       case CBN_SELCHANGE:
+         if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
+           return 0;
+       }
+      /* menubars always must come last since the hashtables do not
+         always exist*/
 #ifdef HAVE_MENUBARS
       if (!NILP (mswindows_handle_wm_command (frame, id)))
        break;
 #endif
 
 #ifdef HAVE_MENUBARS
       if (!NILP (mswindows_handle_wm_command (frame, id)))
        break;
 #endif
 
-      /* Bite me - a spurious command. This cannot happen. */
-      error ("XEMACS BUG: Cannot decode command message");
+      return DefWindowProc (hwnd, message, wParam, lParam);
+      /* Bite me - a spurious command. This used to not be able to
+         happen but with the introduction of widgets its now
+         possible. */
     }
   break;
 
     }
   break;
 
+  case WM_CTLCOLORBTN:
+  case WM_CTLCOLORLISTBOX:
+  case WM_CTLCOLOREDIT:
+  case WM_CTLCOLORSTATIC:
+  case WM_CTLCOLORSCROLLBAR:
+    {
+      /* if we get an opportunity to paint a widget then do so if
+         there is an appropriate face */
+      HWND crtlwnd = (HWND)lParam;
+      LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
+      if (ii)
+       {
+         Lisp_Object image_instance;
+         VOID_TO_LISP (image_instance, ii);
+         if (IMAGE_INSTANCEP (image_instance)
+             && 
+             IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)
+             &&
+             !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance)))
+           {
+             /* set colors for the buttons */
+             HDC hdc = (HDC)wParam;
+             if (last_widget_brushed != ii)
+               {
+                 if (widget_brush)
+                   DeleteObject (widget_brush);
+                 widget_brush = CreateSolidBrush 
+                   (COLOR_INSTANCE_MSWINDOWS_COLOR 
+                    (XCOLOR_INSTANCE 
+                     (FACE_BACKGROUND 
+                      (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
+                       XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+               }
+             last_widget_brushed = ii;
+             SetTextColor
+               (hdc,
+                COLOR_INSTANCE_MSWINDOWS_COLOR 
+                (XCOLOR_INSTANCE 
+                 (FACE_FOREGROUND 
+                  (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
+                   XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+             SetBkMode (hdc, OPAQUE);
+             SetBkColor
+               (hdc,
+                COLOR_INSTANCE_MSWINDOWS_COLOR 
+                (XCOLOR_INSTANCE 
+                 (FACE_BACKGROUND 
+                  (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
+                   XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
+             return (LRESULT)widget_brush;
+           }
+       }
+    }
+    goto defproc;
+
 #ifdef HAVE_DRAGNDROP
   case WM_DROPFILES:   /* implementation ripped-off from event-Xt.c */
     {
 #ifdef HAVE_DRAGNDROP
   case WM_DROPFILES:   /* implementation ripped-off from event-Xt.c */
     {
@@ -2454,7 +2577,7 @@ emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
 
   mswindows_need_event (1);
 
 
   mswindows_need_event (1);
 
-  event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue));
+  event = mswindows_dequeue_dispatch_event ();
   XSETEVENT (event2, emacs_event);
   Fcopy_event (event, event2);
   Fdeallocate_event (event);
   XSETEVENT (event2, emacs_event);
   Fcopy_event (event, event2);
   Fdeallocate_event (event);
@@ -2516,6 +2639,7 @@ emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
     }
 }
 
     }
 }
 
+#ifndef HAVE_MSG_SELECT
 static HANDLE
 get_process_input_waitable (struct Lisp_Process *process)
 {
 static HANDLE
 get_process_input_waitable (struct Lisp_Process *process)
 {
@@ -2565,28 +2689,47 @@ emacs_mswindows_unselect_process (struct Lisp_Process *process)
   HANDLE hev = get_process_input_waitable (process);
   remove_waitable_handle (hev);
 }
   HANDLE hev = get_process_input_waitable (process);
   remove_waitable_handle (hev);
 }
+#endif /* HAVE_MSG_SELECT */
 
 static void
 emacs_mswindows_select_console (struct console *con)
 {
 
 static void
 emacs_mswindows_select_console (struct console *con)
 {
+#ifdef HAVE_MSG_SELECT
+  if (CONSOLE_MSWINDOWS_P (con))
+    return; /* mswindows consoles are automatically selected */
+
+  event_stream_unixoid_select_console (con);
+#endif
 }
 
 static void
 emacs_mswindows_unselect_console (struct console *con)
 {
 }
 
 static void
 emacs_mswindows_unselect_console (struct console *con)
 {
+#ifdef HAVE_MSG_SELECT
+  if (CONSOLE_MSWINDOWS_P (con))
+    return; /* mswindows consoles are automatically selected */
+
+  event_stream_unixoid_unselect_console (con);
+#endif
 }
 
 static void
 emacs_mswindows_quit_p (void)
 {
 }
 
 static void
 emacs_mswindows_quit_p (void)
 {
+  MSG msg;
+
   /* Quit cannot happen in modal loop: all program
      input is dedicated to Windows. */
   if (mswindows_in_modal_loop)
     return;
 
   /* Quit cannot happen in modal loop: all program
      input is dedicated to Windows. */
   if (mswindows_in_modal_loop)
     return;
 
-  /* Drain windows queue. This sets up number of quit
-     characters in in the queue */
-  mswindows_drain_windows_queue ();
+  /* Drain windows queue. This sets up number of quit characters in the queue
+   * (and also processes wm focus change, move, resize, etc messages).
+   * We don't want to process WM_PAINT messages because this function can be
+   * called from almost anywhere and the windows' states may be changing. */
+  while (PeekMessage (&msg, NULL, 0, WM_PAINT-1, PM_REMOVE) ||
+        PeekMessage (&msg, NULL, WM_PAINT+1, WM_USER-1, PM_REMOVE))
+      DispatchMessage (&msg);
 
   if (mswindows_quit_chars_count > 0)
     {
 
   if (mswindows_quit_chars_count > 0)
     {