diff src/event-msw.c @ 410:de805c49cfc1 r21-2-35

Import from CVS: tag r21-2-35
author cvs
date Mon, 13 Aug 2007 11:19:21 +0200
parents 501cfd01ee6d
children 697ef44129c6
line wrap: on
line diff
--- a/src/event-msw.c	Mon Aug 13 11:18:12 2007 +0200
+++ b/src/event-msw.c	Mon Aug 13 11:19:21 2007 +0200
@@ -69,13 +69,13 @@
 #ifdef HAVE_MSG_SELECT
 #include "sysfile.h"
 #include "console-tty.h"
-#elif defined(__CYGWIN32__)
+#elif defined(CYGWIN)
 typedef unsigned int SOCKET;
 #endif
 #include <io.h>
 #include <errno.h>
 
-#if !(defined(__CYGWIN32__) || defined(__MINGW32__))
+#if !(defined(CYGWIN) || defined(MINGW))
 # include <shlobj.h>	/* For IShellLink */
 #endif
 
@@ -471,7 +471,7 @@
 #define NTPIPE_SHOVE_STREAM_DATA(stream) \
   LSTREAM_TYPE_DATA (stream, ntpipe_shove)
 
-#define MAX_SHOVE_BUFFER_SIZE 128
+#define MAX_SHOVE_BUFFER_SIZE 512
 
 struct ntpipe_shove_stream
 {
@@ -505,15 +505,18 @@
       InterlockedIncrement (&s->idle_p);
       WaitForSingleObject (s->hev_thread, INFINITE);
 
-      if (s->die_p)
-	break;
-
-      /* Write passed buffer */
-      if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL)
-	  || bytes_written != s->size)
+      /* Write passed buffer if any */
+      if (s->size > 0)
 	{
-	  s->error_p = TRUE;
-	  InterlockedIncrement (&s->die_p);
+         if (!WriteFile (s->hpipe, s->buffer, s->size, &bytes_written, NULL)
+             || bytes_written != s->size)
+           {
+             s->error_p = TRUE;
+             InterlockedIncrement (&s->die_p);
+           }
+         /* Set size to zero so we won't write it again if the closer sets
+            die_p and kicks us */
+         s->size = 0;
 	}
 
       if (s->die_p)
@@ -546,6 +549,15 @@
       return Qnil;
     }
 
+  /* Set the priority of the thread higher so we don't end up waiting
+     on it to send things. */
+  if (!SetThreadPriority (s->hthread, THREAD_PRIORITY_HIGHEST))
+    {
+      CloseHandle (s->hthread);
+      Lstream_delete (lstr);
+      return Qnil;
+    }
+
   /* hev_thread is an auto-reset event, initially nonsignaled */
   s->hev_thread = CreateEvent (NULL, FALSE, FALSE, NULL);
 
@@ -586,6 +598,9 @@
   /* Start output */
   InterlockedDecrement (&s->idle_p);
   SetEvent (s->hev_thread);
+  /* Give it a chance to run -- this dramatically improves performance
+     of things like crypt. */
+  (void) SwitchToThread ();
   return size;
 }
 
@@ -604,14 +619,18 @@
   /* Force thread stop */
   InterlockedIncrement (&s->die_p);
 
-  /* Close pipe handle, possibly breaking it */
-  CloseHandle (s->hpipe);
-
-  /* Thread will end upon unblocking */
+  /* Thread will end upon unblocking.  If it's already unblocked this will
+     do nothing, but the thread won't look at die_p until it's written any
+     pending output. */
   SetEvent (s->hev_thread);
 
   /* Wait while thread terminates */
   WaitForSingleObject (s->hthread, INFINITE);
+
+  /* Close pipe handle, possibly breaking it */
+  CloseHandle (s->hpipe);
+
+  /* Close the thread handle */
   CloseHandle (s->hthread);
 
   /* Destroy the event */
@@ -1251,14 +1270,20 @@
 
   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.
+      /* We have to translate messages that are not sent to an XEmacs
+         frame. This is so that key presses work ok in things like
+         edit fields. However, we *musn't* translate message for XEmacs
+         frames as this is handled in the wnd proc.
          We also have to avoid generating paint magic events for windows
 	 that aren't XEmacs frames */
-      if (GetWindowLong (msg.hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP))
+      /* GetClassName will truncate a longer class name. By adding one
+	 extra character, we are forcing textual comparison to fail
+	 if the name is longer than XEMACS_CLASS */
+      char class_name_buf [sizeof (XEMACS_CLASS) + 2] = "";
+      GetClassName (msg.hwnd, class_name_buf, sizeof (class_name_buf) - 1);
+      if (stricmp (class_name_buf, XEMACS_CLASS) != 0)
 	{
+	  /* Not an XEmacs frame */
 	  TranslateMessage (&msg);
 	}
       else if (msg.message == WM_PAINT)
@@ -1270,8 +1295,8 @@
 	  assert (msg.wParam == 0);
 
 	  /* Queue a magic event for handling when safe */
-	  msframe = FRAME_MSWINDOWS_DATA (
-					  XFRAME (mswindows_find_frame (msg.hwnd)));
+	  msframe =
+	    FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (msg.hwnd)));
 	  if (!msframe->paint_pending)
 	    {
 	      msframe->paint_pending = 1;
@@ -1600,7 +1625,7 @@
 	  if (*end)
 	    return DDE_FNOTPROCESSED;
 
-#ifdef __CYGWIN32__
+#ifdef CYGWIN
 	  filename = alloca (cygwin32_win32_to_posix_path_list_buf_size (cmd) + 5);
 	  strcpy (filename, "file:");
 	  cygwin32_win32_to_posix_path_list (cmd, filename+5);
@@ -1755,7 +1780,7 @@
 	 This means that we need to distinguish between an
 	 auto-repeated key and a key pressed and released a bunch
 	 of times. */
-      else if (downp && !keyp ||
+      else if ((downp && !keyp) ||
 	       (downp && keyp && last_downkey &&
 		(wParam != last_downkey ||
 		 /* the "previous key state" bit indicates autorepeat */
@@ -1810,24 +1835,24 @@
     }						\
 } while (0)
 
-      if (wParam == VK_CONTROL && (lParam & 0x1000000)
+      if ((wParam == VK_CONTROL && (lParam & 0x1000000))
 	  || wParam == VK_RCONTROL)
 	FROB (XEMSW_RCONTROL);
-      if (wParam == VK_CONTROL && !(lParam & 0x1000000)
+      if ((wParam == VK_CONTROL && !(lParam & 0x1000000))
 	  || wParam == VK_LCONTROL)
 	FROB (XEMSW_LCONTROL);
 
-      if (wParam == VK_SHIFT && (lParam & 0x1000000)
+      if ((wParam == VK_SHIFT && (lParam & 0x1000000))
 	  || wParam == VK_RSHIFT)
 	FROB (XEMSW_RSHIFT);
-      if (wParam == VK_SHIFT && !(lParam & 0x1000000)
+      if ((wParam == VK_SHIFT && !(lParam & 0x1000000))
 	  || wParam == VK_LSHIFT)
 	FROB (XEMSW_LSHIFT);
 
-      if (wParam == VK_MENU && (lParam & 0x1000000)
+      if ((wParam == VK_MENU && (lParam & 0x1000000))
 	  || wParam == VK_RMENU)
 	FROB (XEMSW_RMENU);
-      if (wParam == VK_MENU && !(lParam & 0x1000000)
+      if ((wParam == VK_MENU && !(lParam & 0x1000000))
 	  || wParam == VK_LMENU)
 	FROB (XEMSW_LMENU);
     }
@@ -1889,6 +1914,8 @@
 
 #ifdef DEBUG_XEMACS
 
+#if 0
+
 static void
 output_modifier_keyboard_state (void)
 {
@@ -1919,6 +1946,8 @@
 	      keymap[VK_RSHIFT] & 0x1 ? 1 : 0);
 }
 
+#endif
+
 /* try to debug the stuck-alt-key problem.
 
  #### this happens only inconsistently, and may only happen when using
@@ -1971,7 +2000,7 @@
  * The windows procedure for the window class XEMACS_CLASS
  */
 LRESULT WINAPI
-mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
 {
   /* Note: Remember to initialize emacs_event and event before use.
      This code calls code that can GC. You must GCPRO before calling such code. */
@@ -1983,13 +2012,16 @@
   struct mswindows_frame* msframe;
 
   assert (!GetWindowLong (hwnd, GWL_USERDATA));
-  switch (message)
+  switch (message_)
     {
     case WM_DESTROYCLIPBOARD:
       /* We own the clipboard and someone else wants it.  Delete our
 	 cached copy of the clipboard contents so we'll ask for it from
-	 Windows again when someone does a paste. */
-      handle_selection_clear(QCLIPBOARD);
+	 Windows again when someone does a paste, and destroy any memory
+         objects we hold on the clipboard that are not in the list of types
+         that Windows will delete itself. */
+      mswindows_destroy_selection (QCLIPBOARD);
+      handle_selection_clear (QCLIPBOARD);
       break;
 
     case WM_ERASEBKGND:
@@ -2016,7 +2048,7 @@
 	if (mswindows_debug_events)
 	  {
 	    stderr_out ("%s wparam=%d lparam=%d\n",
-			message == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP",
+			message_ == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP",
 			wParam, (int)lParam);
 	    output_alt_keyboard_state ();
 	  }	    
@@ -2037,7 +2069,7 @@
 	  }
 
 	if (should_set_keymap)
-	  //	    && (message != WM_SYSKEYUP
+	  //	    && (message_ != WM_SYSKEYUP
 	  //	|| NILP (Vmenu_accelerator_enabled)))
 	  SetKeyboardState (keymap);
 
@@ -2073,7 +2105,7 @@
 	if (mswindows_debug_events)
 	  {
 	    stderr_out ("%s wparam=%d lparam=%d\n",
-			message == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
+			message_ == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
 			wParam, (int)lParam);
 	    output_alt_keyboard_state ();
 	  }	    
@@ -2087,7 +2119,7 @@
 	    GetKeyboardState (keymap_sticky);
 	    if (keymap_sticky[VK_MENU] & 0x80)
 	      {
-		message = WM_SYSKEYDOWN;
+		message_ = WM_SYSKEYDOWN;
 		/* We have to set the "context bit" so that the
 		   TranslateMessage() call below that generates the
 		   SYSCHAR message does its thing; see the documentation
@@ -2118,7 +2150,7 @@
 	    int got_accelerator = 0;
 	  
 	    msg.hwnd = hwnd;
-	    msg.message = message;
+	    msg.message = message_;
 	    msg.wParam = wParam;
 	    msg.lParam = lParam;
 	    msg.time = GetMessageTime();
@@ -2139,7 +2171,7 @@
 	      }
 
 	    if (!NILP (Vmenu_accelerator_enabled) &&
-		!(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN)
+		!(mods & XEMACS_MOD_SHIFT) && message_ == WM_SYSKEYDOWN)
 	      potential_accelerator = 1;
 
 	    /* Remove shift modifier from an ascii character */
@@ -2186,7 +2218,7 @@
 		    ++mswindows_quit_chars_count;
 		  }
 		else if (potential_accelerator && !got_accelerator &&
-			 msw_char_is_accelerator (frame, ch))
+			 mswindows_char_is_accelerator (frame, ch))
 		  {
 		    got_accelerator = 1;
 		    break;
@@ -2218,7 +2250,7 @@
       /* Real middle mouse button has nothing to do with emulated one:
 	 if one wants to exercise fingers playing chords on the mouse,
 	 he is allowed to do that! */
-      mswindows_enqueue_mouse_button_event (hwnd, message,
+      mswindows_enqueue_mouse_button_event (hwnd, message_,
 					    MAKEPOINTS (lParam), GetMessageTime());
       break;
 
@@ -2533,21 +2565,31 @@
     case WM_DISPLAYCHANGE:
       {
 	struct device *d;
+	DWORD message_tick = GetMessageTime ();
 
 	fobj = mswindows_find_frame (hwnd);
 	frame = XFRAME (fobj);
 	d = XDEVICE (FRAME_DEVICE (frame));
 
-	DEVICE_MSWINDOWS_HORZRES(d) = LOWORD (lParam);
-	DEVICE_MSWINDOWS_VERTRES(d) = HIWORD (lParam);
-	DEVICE_MSWINDOWS_BITSPIXEL(d) = wParam;
-	break;
+	/* Do this only once per message. XEmacs can receive this message
+	   through as many frames as it currently has open. Message time
+	   will be the same for all these messages. Despite extreme
+	   efficiency, the code below has about one in 4 billion
+	   probability that the HDC is not recreated, provided that
+	   XEmacs is running sufficiently longer than 52 days. */
+	if (DEVICE_MSWINDOWS_UPDATE_TICK(d) != message_tick)
+	  {
+	    DEVICE_MSWINDOWS_UPDATE_TICK(d) = message_tick;
+	    DeleteDC (DEVICE_MSWINDOWS_HCDC(d));
+	    DEVICE_MSWINDOWS_HCDC(d) = CreateCompatibleDC (NULL);
+	  }
       }
+      break;
 
       /* Misc magic events which only require that the frame be identified */
     case WM_SETFOCUS:
     case WM_KILLFOCUS:
-      mswindows_enqueue_magic_event (hwnd, message);
+      mswindows_enqueue_magic_event (hwnd, message_);
       break;
 
     case WM_WINDOWPOSCHANGING:
@@ -2696,7 +2738,7 @@
 	  break;
 #endif
 
-	return DefWindowProc (hwnd, message, wParam, lParam);
+	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. */
@@ -2796,7 +2838,7 @@
 	    DragQueryFile ((HANDLE) wParam, i, fname, len+1);
 
 	    /* May be a shell link aka "shortcut" - replace fname if so */
-#if !(defined(__CYGWIN32__) || defined(__MINGW32__))
+#if !(defined(CYGWIN) || defined(MINGW))
 	    /* cygwin doesn't define this COM stuff */
 	    if (!stricmp (fname + strlen (fname) - 4, ".LNK"))
 	      {
@@ -2833,7 +2875,7 @@
 	      }
 #endif
 
-#ifdef __CYGWIN32__
+#ifdef CYGWIN
 	    filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
 	    strcpy (filename, "file:");
 	    cygwin32_win32_to_posix_path_list (fname, filename+5);
@@ -2858,7 +2900,7 @@
 
     defproc:
     default:
-      return DefWindowProc (hwnd, message, wParam, lParam);
+      return DefWindowProc (hwnd, message_, wParam, lParam);
     }
   return (0);
 }