X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fevent-msw.c;h=f098d730b82de3df153905d3b593479a2428357a;hb=a699139716d7a947173ebc9a7130cc0eead5da7f;hp=5b7d03b03e775570fe90fc5292fa491c12acbf21;hpb=76759ab036458c54499a454399e19602b8ae6ce3;p=chise%2Fxemacs-chise.git- diff --git a/src/event-msw.c b/src/event-msw.c index 5b7d03b..f098d73 100644 --- a/src/event-msw.c +++ b/src/event-msw.c @@ -69,13 +69,13 @@ Boston, MA 02111-1307, USA. */ #ifdef HAVE_MSG_SELECT #include "sysfile.h" #include "console-tty.h" -#elif defined(__CYGWIN32__) +#elif defined(CYGWIN) typedef unsigned int SOCKET; #endif #include #include -#if !(defined(__CYGWIN32__) || defined(__MINGW32__)) +#if !(defined(CYGWIN) || defined(MINGW)) # include /* For IShellLink */ #endif @@ -96,7 +96,8 @@ static Lisp_Object mswindows_find_frame (HWND hwnd); static Lisp_Object mswindows_find_console (HWND hwnd); static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, int extendedp); -static int mswindows_modifier_state (BYTE* keymap, int has_AltGr); +static int mswindows_modifier_state (BYTE* keymap, DWORD fwKeys, + int has_AltGr); static void mswindows_set_chord_timer (HWND hwnd); static int mswindows_button2_near_enough (POINTS p1, POINTS p2); static int mswindows_current_layout_has_AltGr (void); @@ -145,13 +146,13 @@ int mswindows_quit_chars_count = 0; /* These are Lisp integers; see DEFVARS in this file for description. */ int mswindows_dynamic_frame_resize; int mswindows_alt_by_itself_activates_menu; -int mswindows_num_mouse_buttons; -int mswindows_mouse_button_max_skew_x; -int mswindows_mouse_button_max_skew_y; -int mswindows_mouse_button_tolerance; +Fixnum mswindows_num_mouse_buttons; +Fixnum mswindows_mouse_button_max_skew_x; +Fixnum mswindows_mouse_button_max_skew_y; +Fixnum mswindows_mouse_button_tolerance; #ifdef DEBUG_XEMACS -int mswindows_debug_events; +Fixnum debug_mswindows_events; #endif /* This is the event signaled by the event pump. @@ -161,6 +162,8 @@ static int mswindows_in_modal_loop; /* Count of wound timers */ static int mswindows_pending_timers_count; + +static DWORD mswindows_last_mouse_button_state; /************************************************************************/ /* Pipe instream - reads process output */ @@ -471,7 +474,7 @@ init_slurp_stream (void) #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 +508,18 @@ shove_thread (LPVOID vparam) 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 +552,15 @@ make_ntpipe_output_stream (HANDLE hpipe, LPARAM param) 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 +601,10 @@ ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size) /* Start output */ InterlockedDecrement (&s->idle_p); SetEvent (s->hev_thread); + /* Give it a chance to run -- this dramatically improves performance + of things like crypt. */ + if (xSwitchToThread) /* not in Win9x or NT 3.51 */ + (void) xSwitchToThread (); return size; } @@ -604,14 +623,18 @@ ntpipe_shove_closer (Lstream *stream) /* 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 */ @@ -940,7 +963,7 @@ mswindows_enqueue_process_event (Lisp_Process* p) static void mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, - DWORD when) + int mods, DWORD when) { int downp = (msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN || msg == WM_RBUTTONDOWN); @@ -960,7 +983,7 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2); event->event.button.x = where.x; event->event.button.y = where.y; - event->event.button.modifiers = mswindows_modifier_state (NULL, 0); + event->event.button.modifiers = mswindows_modifier_state (NULL, mods, 0); if (downp) { @@ -1251,27 +1274,43 @@ mswindows_drain_windows_queue (void) 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. + char class_name_buf [sizeof (XEMACS_CLASS) + 2] = ""; + + /* Don't translate messages destined for a dialog box, this + makes keyboard traversal work. I think?? */ + if (mswindows_is_dialog_msg (&msg)) + { + mswindows_unmodalize_signal_maybe (); + continue; + } + + /* 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 */ + + 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) { struct mswindows_frame* msframe; - + /* hdc will be NULL unless this is a subwindow - in which case we shouldn't have received a paint message for it here. */ 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; @@ -1375,7 +1414,7 @@ mswindows_need_event (int badly_p) { mswindows_drain_windows_queue (); } - else + else { #ifdef HAVE_TTY /* Look for a TTY event */ @@ -1389,7 +1428,7 @@ mswindows_need_event (int badly_p) struct console *c = tty_find_console_from_fd (i); Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); Lisp_Event* event = XEVENT (emacs_event); - + assert (c); if (read_event_from_tty_or_stream_desc (event, c, i)) { @@ -1408,7 +1447,7 @@ mswindows_need_event (int badly_p) { Lisp_Process *p = get_process_from_usid (FD_TO_USID(i)); - + mswindows_enqueue_process_event (p); } else @@ -1600,7 +1639,7 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv, 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); @@ -1684,7 +1723,7 @@ mswindows_handle_paint (struct frame *frame) } /* - * Returns 1 if a key is a real modifier or special key, which + * Returns 1 if a key is a real modifier or special key, which * is better handled by DefWindowProc */ static int @@ -1755,7 +1794,7 @@ mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam, 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 +1849,24 @@ do { \ } \ } 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 +1928,8 @@ clear_sticky_modifiers (void) #ifdef DEBUG_XEMACS +#if 0 + static void output_modifier_keyboard_state (void) { @@ -1919,6 +1960,8 @@ output_modifier_keyboard_state (void) 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 @@ -1964,14 +2007,14 @@ output_alt_keyboard_state (void) /* asyncstate[2] & 0x1 ? 1 : 0); */ } -#endif /* DEBUG_XEMACS */ +#endif /* DEBUG_XEMACS */ /* * 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. */ @@ -1982,14 +2025,22 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) struct frame *frame; struct mswindows_frame* msframe; + /* Not perfect but avoids crashes. There is potential for wierd + behavior here. */ + if (gc_in_progress) + goto defproc; + 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: @@ -2013,14 +2064,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int should_set_keymap = 0; #ifdef DEBUG_XEMACS - if (mswindows_debug_events) + if (debug_mswindows_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 (); - } -#endif /* DEBUG_XEMACS */ + } +#endif /* DEBUG_XEMACS */ mswindows_handle_sticky_modifiers (wParam, lParam, 0, 1); if (wParam == VK_CONTROL) @@ -2037,12 +2088,12 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } if (should_set_keymap) - // && (message != WM_SYSKEYUP + // && (message_ != WM_SYSKEYUP // || NILP (Vmenu_accelerator_enabled))) SetKeyboardState (keymap); } - + if (key_needs_default_processing_p (wParam)) goto defproc; else @@ -2052,7 +2103,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SYSKEYDOWN: /* In some locales the right-hand Alt key is labelled AltGr. This key - * should produce alternative charcaters when combined with another key. + * should produce alternative characters when combined with another key. * eg on a German keyboard pressing AltGr+q should produce '@'. * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if * TranslateMessage() is called with *any* combination of Ctrl+Alt down, @@ -2070,14 +2121,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) int sticky_changed; #ifdef DEBUG_XEMACS - if (mswindows_debug_events) + if (debug_mswindows_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 (); - } -#endif /* DEBUG_XEMACS */ + } +#endif /* DEBUG_XEMACS */ GetKeyboardState (keymap_orig); frame = XFRAME (mswindows_find_frame (hwnd)); @@ -2087,7 +2138,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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 @@ -2098,7 +2149,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) else memcpy (keymap_sticky, keymap_orig, 256); - mods = mswindows_modifier_state (keymap_sticky, has_AltGr); + mods = mswindows_modifier_state (keymap_sticky, (DWORD) -1, has_AltGr); /* Handle non-printables */ if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods, @@ -2116,9 +2167,9 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) MSG msg, tranmsg; int potential_accelerator = 0; int got_accelerator = 0; - + msg.hwnd = hwnd; - msg.message = message; + msg.message = message_; msg.wParam = wParam; msg.lParam = lParam; msg.time = GetMessageTime(); @@ -2139,7 +2190,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } 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 +2237,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) ++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; @@ -2197,7 +2248,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* This generates WM_SYSCHAR messages, which are interpreted by DefWindowProc as the menu selections. */ if (got_accelerator) - { + { SetKeyboardState (keymap_sticky); TranslateMessage (&msg); SetKeyboardState (keymap_orig); @@ -2218,8 +2269,10 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* 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, - MAKEPOINTS (lParam), GetMessageTime()); + mswindows_enqueue_mouse_button_event (hwnd, message_, + MAKEPOINTS (lParam), + wParam &~ MK_MBUTTON, + GetMessageTime()); break; case WM_LBUTTONUP: @@ -2237,7 +2290,11 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) msframe->button2_is_down = 0; msframe->ignore_next_rbutton_up = 1; mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam + &~ (MK_LBUTTON | MK_MBUTTON + | MK_RBUTTON), + GetMessageTime()); } else { @@ -2245,10 +2302,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { msframe->button2_need_rbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_LBUTTON, + GetMessageTime()); } mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_LBUTTON, + GetMessageTime()); } break; @@ -2267,7 +2328,11 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) msframe->button2_is_down = 0; msframe->ignore_next_lbutton_up = 1; mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam + &~ (MK_LBUTTON | MK_MBUTTON + | MK_RBUTTON), + GetMessageTime()); } else { @@ -2275,10 +2340,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { msframe->button2_need_lbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_RBUTTON, + GetMessageTime()); } mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_RBUTTON, + GetMessageTime()); } break; @@ -2290,18 +2359,28 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) KillTimer (hwnd, BUTTON_2_TIMER_ID); msframe->button2_need_lbutton = 0; msframe->button2_need_rbutton = 0; - if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) + if (mswindows_button2_near_enough (msframe->last_click_point, + MAKEPOINTS (lParam))) { mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam + &~ (MK_LBUTTON | MK_MBUTTON + | MK_RBUTTON), + GetMessageTime()); msframe->button2_is_down = 1; } else { mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - msframe->last_click_point, msframe->last_click_time); + msframe->last_click_point, + msframe->last_click_mods + &~ MK_RBUTTON, + msframe->last_click_time); mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_LBUTTON, + GetMessageTime()); } } else @@ -2309,6 +2388,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) mswindows_set_chord_timer (hwnd); msframe->button2_need_rbutton = 1; msframe->last_click_point = MAKEPOINTS (lParam); + msframe->last_click_mods = wParam; } msframe->last_click_time = GetMessageTime(); break; @@ -2321,18 +2401,28 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) KillTimer (hwnd, BUTTON_2_TIMER_ID); msframe->button2_need_lbutton = 0; msframe->button2_need_rbutton = 0; - if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) + if (mswindows_button2_near_enough (msframe->last_click_point, + MAKEPOINTS (lParam))) { mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam + &~ (MK_LBUTTON | MK_MBUTTON + | MK_RBUTTON), + GetMessageTime()); msframe->button2_is_down = 1; } else { mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - msframe->last_click_point, msframe->last_click_time); + msframe->last_click_point, + msframe->last_click_mods + &~ MK_LBUTTON, + msframe->last_click_time); mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - MAKEPOINTS (lParam), GetMessageTime()); + MAKEPOINTS (lParam), + wParam &~ MK_RBUTTON, + GetMessageTime()); } } else @@ -2340,6 +2430,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) mswindows_set_chord_timer (hwnd); msframe->button2_need_lbutton = 1; msframe->last_click_point = MAKEPOINTS (lParam); + msframe->last_click_mods = wParam; } msframe->last_click_time = GetMessageTime(); break; @@ -2354,13 +2445,19 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { msframe->button2_need_lbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, - msframe->last_click_point, msframe->last_click_time); + msframe->last_click_point, + msframe->last_click_mods + &~ MK_RBUTTON, + msframe->last_click_time); } else if (msframe->button2_need_rbutton) { msframe->button2_need_rbutton = 0; mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, - msframe->last_click_point, msframe->last_click_time); + msframe->last_click_point, + msframe->last_click_mods + &~ MK_LBUTTON, + msframe->last_click_time); } } else @@ -2391,7 +2488,8 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) event->event_type = pointer_motion_event; event->event.motion.x = MAKEPOINTS(lParam).x; event->event.motion.y = MAKEPOINTS(lParam).y; - event->event.motion.modifiers = mswindows_modifier_state (NULL, 0); + event->event.motion.modifiers = + mswindows_modifier_state (NULL, wParam, 0); mswindows_enqueue_dispatch_event (emacs_event); } @@ -2427,9 +2525,7 @@ 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...*/ - TO_EXTERNAL_FORMAT (LISP_STRING, btext, - C_STRING_ALLOCA, tttext->lpszText, - Qnative); + LISP_STRING_TO_EXTERNAL (btext, tttext->lpszText, Qnative); } #endif } @@ -2461,7 +2557,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) shouldn't have received a paint message for it here. */ assert (wParam == 0); - /* Can't queue a magic event because windows goes modal and sends paint + /* Can't queue a magic event because windows goes modal and sends paint messages directly to the windows procedure when doing solid drags and the message queue doesn't get processed. */ mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd))); @@ -2533,21 +2629,31 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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 +2802,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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. */ @@ -2779,7 +2885,8 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) event->channel = mswindows_find_frame(hwnd); event->timestamp = GetMessageTime(); event->event.misc.button = 1; /* #### Should try harder */ - event->event.misc.modifiers = mswindows_modifier_state (NULL, 0); + event->event.misc.modifiers = mswindows_modifier_state (NULL, + (DWORD) -1, 0); event->event.misc.x = point.x; event->event.misc.y = point.y; event->event.misc.function = Qdragdrop_drop_dispatch; @@ -2796,7 +2903,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 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")) { @@ -2804,7 +2911,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (CoCreateInstance (&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl) == S_OK) - { + { IPersistFile* ppf; if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, @@ -2833,7 +2940,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } #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 +2965,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) defproc: default: - return DefWindowProc (hwnd, message, wParam, lParam); + return DefWindowProc (hwnd, message_, wParam, lParam); } return (0); } @@ -2905,8 +3012,10 @@ mswindows_current_layout_has_AltGr (void) time when a key typed at autorepeat rate of 30 cps! */ static HKL last_hkl = 0; static int last_hkl_has_AltGr; + HKL current_hkl = (HKL) -1; - HKL current_hkl = GetKeyboardLayout (0); + if (xGetKeyboardLayout) /* not in NT 3.5 */ + current_hkl = xGetKeyboardLayout (0); if (current_hkl != last_hkl) { TCHAR c; @@ -2926,11 +3035,20 @@ mswindows_current_layout_has_AltGr (void) /* Returns the state of the modifier keys in the format expected by the * Lisp_Event key_data, button_data and motion_data modifiers member */ static int -mswindows_modifier_state (BYTE* keymap, int has_AltGr) +mswindows_modifier_state (BYTE* keymap, DWORD fwKeys, int has_AltGr) { int mods = 0; + int keys_is_real = 0; BYTE keymap2[256]; + if (fwKeys == (DWORD) -1) + fwKeys = mswindows_last_mouse_button_state; + else + { + keys_is_real = 1; + mswindows_last_mouse_button_state = fwKeys; + } + if (keymap == NULL) { keymap = keymap2; @@ -2938,6 +3056,8 @@ mswindows_modifier_state (BYTE* keymap, int has_AltGr) has_AltGr = mswindows_current_layout_has_AltGr (); } + /* #### should look at fwKeys for MK_CONTROL. I don't understand how + AltGr works. */ if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) { mods |= (keymap [VK_LMENU] & 0x80) ? XEMACS_MOD_META : 0; @@ -2949,7 +3069,11 @@ mswindows_modifier_state (BYTE* keymap, int has_AltGr) mods |= (keymap [VK_CONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0; } - mods |= (keymap [VK_SHIFT] & 0x80) ? XEMACS_MOD_SHIFT : 0; + mods |= (keys_is_real ? fwKeys & MK_SHIFT : (keymap [VK_SHIFT] & 0x80)) + ? XEMACS_MOD_SHIFT : 0; + mods |= fwKeys & MK_LBUTTON ? XEMACS_MOD_BUTTON1 : 0; + mods |= fwKeys & MK_MBUTTON ? XEMACS_MOD_BUTTON2 : 0; + mods |= fwKeys & MK_RBUTTON ? XEMACS_MOD_BUTTON3 : 0; return mods; } @@ -2958,7 +3082,6 @@ mswindows_modifier_state (BYTE* keymap, int has_AltGr) * Translate a mswindows virtual key to a keysym. * Only returns non-Qnil for keys that don't generate WM_CHAR messages * or whose ASCII codes (like space) xemacs doesn't like. - * Virtual key values are defined in winresrc.h */ Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, int extendedp) @@ -2967,6 +3090,7 @@ Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, { switch (mswindows_key) { + case VK_CANCEL: return KEYSYM ("pause"); case VK_RETURN: return KEYSYM ("kp-enter"); case VK_PRIOR: return KEYSYM ("prior"); case VK_NEXT: return KEYSYM ("next"); @@ -2978,6 +3102,11 @@ Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, case VK_DOWN: return KEYSYM ("down"); case VK_INSERT: return KEYSYM ("insert"); case VK_DELETE: return QKdelete; +#if 0 /* FSF Emacs allows these to return configurable syms/mods */ + case VK_LWIN return KEYSYM (""); + case VK_RWIN return KEYSYM (""); +#endif + case VK_APPS: return KEYSYM ("menu"); } } else @@ -2989,6 +3118,7 @@ Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, case '\n': return QKlinefeed; case VK_CLEAR: return KEYSYM ("clear"); case VK_RETURN: return QKreturn; + case VK_PAUSE: return KEYSYM ("pause"); case VK_ESCAPE: return QKescape; case VK_SPACE: return QKspace; case VK_PRIOR: return KEYSYM ("kp-prior"); @@ -3006,11 +3136,6 @@ Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, case VK_INSERT: return KEYSYM ("kp-insert"); case VK_DELETE: return KEYSYM ("kp-delete"); case VK_HELP: return KEYSYM ("help"); -#if 0 /* FSF Emacs allows these to return configurable syms/mods */ - case VK_LWIN return KEYSYM (""); - case VK_RWIN return KEYSYM (""); -#endif - case VK_APPS: return KEYSYM ("menu"); case VK_NUMPAD0: return KEYSYM ("kp-0"); case VK_NUMPAD1: return KEYSYM ("kp-1"); case VK_NUMPAD2: return KEYSYM ("kp-2"); @@ -3323,7 +3448,7 @@ emacs_mswindows_quit_p (void) { emacs_event = mswindows_cancel_dispatch_event (&match_against); assert (!NILP (emacs_event)); - + if (XEVENT(emacs_event)->event.key.modifiers & XEMACS_MOD_SHIFT) critical_p = 1; @@ -3437,6 +3562,12 @@ emacs_mswindows_delete_stream_pair (Lisp_Object instream, : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (instream)))); } +static int +emacs_mswindows_current_event_timestamp (struct console *c) +{ + return GetTickCount (); +} + #ifndef HAVE_X_WINDOWS /* This is called from GC when a process object is about to be freed. If we've still got pointers to it in this file, we're gonna lose hard. @@ -3491,6 +3622,8 @@ reinit_vars_of_event_mswindows (void) mswindows_event_stream->create_stream_pair_cb = emacs_mswindows_create_stream_pair; mswindows_event_stream->delete_stream_pair_cb = emacs_mswindows_delete_stream_pair; #endif + mswindows_event_stream->current_event_timestamp_cb = + emacs_mswindows_current_event_timestamp; } void @@ -3501,19 +3634,19 @@ vars_of_event_mswindows (void) mswindows_u_dispatch_event_queue = Qnil; staticpro (&mswindows_u_dispatch_event_queue); mswindows_u_dispatch_event_queue_tail = Qnil; - pdump_wire (&mswindows_u_dispatch_event_queue_tail); + dump_add_root_object (&mswindows_u_dispatch_event_queue_tail); mswindows_s_dispatch_event_queue = Qnil; staticpro (&mswindows_s_dispatch_event_queue); mswindows_s_dispatch_event_queue_tail = Qnil; - pdump_wire (&mswindows_s_dispatch_event_queue_tail); + dump_add_root_object (&mswindows_s_dispatch_event_queue_tail); mswindows_error_caught_in_modal_loop = Qnil; staticpro (&mswindows_error_caught_in_modal_loop); #ifdef DEBUG_XEMACS - DEFVAR_INT ("mswindows-debug-events", &mswindows_debug_events /* + DEFVAR_INT ("debug-mswindows-events", &debug_mswindows_events /* If non-zero, display debug information about Windows events that XEmacs sees. Information is displayed in a console window. Currently defined values are: @@ -3522,7 +3655,7 @@ Information is displayed in a console window. Currently defined values are: #### Unfortunately, not yet implemented. */ ); - mswindows_debug_events = 0; + debug_mswindows_events = 0; #endif DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu",