Mercurial > hg > xemacs-beta
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); }