comparison src/event-msw.c @ 408:501cfd01ee6d r21-2-34

Import from CVS: tag r21-2-34
author cvs
date Mon, 13 Aug 2007 11:18:11 +0200
parents b8cc9ab3f761
children de805c49cfc1
comparison
equal deleted inserted replaced
407:ed6218a7d4d3 408:501cfd01ee6d
1 /* The mswindows event_stream interface. 1 /* The mswindows event_stream interface.
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. 2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996, 2000 Ben Wing. 4 Copyright (C) 1996, 2000 Ben Wing.
5 Copyright (C) 1997 Jonathan Harris. 5 Copyright (C) 1997 Jonathan Harris.
6 6
56 #include "faces.h" 56 #include "faces.h"
57 #include "lstream.h" 57 #include "lstream.h"
58 #include "process.h" 58 #include "process.h"
59 #include "redisplay.h" 59 #include "redisplay.h"
60 #include "select.h" 60 #include "select.h"
61 #include "window.h"
61 #include "sysproc.h" 62 #include "sysproc.h"
62 #include "syswait.h" 63 #include "syswait.h"
63 #include "systime.h" 64 #include "systime.h"
64 #include "sysdep.h" 65 #include "sysdep.h"
65 #include "objects-msw.h" 66 #include "objects-msw.h"
74 #include <io.h> 75 #include <io.h>
75 #include <errno.h> 76 #include <errno.h>
76 77
77 #if !(defined(__CYGWIN32__) || defined(__MINGW32__)) 78 #if !(defined(__CYGWIN32__) || defined(__MINGW32__))
78 # include <shlobj.h> /* For IShellLink */ 79 # include <shlobj.h> /* For IShellLink */
79 #endif
80
81 #if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20)
82 typedef NMHDR *LPNMHDR;
83 #endif 80 #endif
84 81
85 #ifdef HAVE_MENUBARS 82 #ifdef HAVE_MENUBARS
86 #define ADJR_MENUFLAG TRUE 83 #define ADJR_MENUFLAG TRUE
87 #else 84 #else
101 int extendedp); 98 int extendedp);
102 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr); 99 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr);
103 static void mswindows_set_chord_timer (HWND hwnd); 100 static void mswindows_set_chord_timer (HWND hwnd);
104 static int mswindows_button2_near_enough (POINTS p1, POINTS p2); 101 static int mswindows_button2_near_enough (POINTS p1, POINTS p2);
105 static int mswindows_current_layout_has_AltGr (void); 102 static int mswindows_current_layout_has_AltGr (void);
103 static int mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
104 int downp, int keyp);
106 105
107 static struct event_stream *mswindows_event_stream; 106 static struct event_stream *mswindows_event_stream;
108 107
109 #ifdef HAVE_MSG_SELECT 108 #ifdef HAVE_MSG_SELECT
110 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask; 109 extern SELECT_TYPE input_wait_mask, non_fake_input_wait_mask;
148 int mswindows_alt_by_itself_activates_menu; 147 int mswindows_alt_by_itself_activates_menu;
149 int mswindows_num_mouse_buttons; 148 int mswindows_num_mouse_buttons;
150 int mswindows_mouse_button_max_skew_x; 149 int mswindows_mouse_button_max_skew_x;
151 int mswindows_mouse_button_max_skew_y; 150 int mswindows_mouse_button_max_skew_y;
152 int mswindows_mouse_button_tolerance; 151 int mswindows_mouse_button_tolerance;
152
153 #ifdef DEBUG_XEMACS
154 int mswindows_debug_events;
155 #endif
153 156
154 /* This is the event signaled by the event pump. 157 /* This is the event signaled by the event pump.
155 See mswindows_pump_outstanding_events for comments */ 158 See mswindows_pump_outstanding_events for comments */
156 static Lisp_Object mswindows_error_caught_in_modal_loop; 159 static Lisp_Object mswindows_error_caught_in_modal_loop;
157 static int mswindows_in_modal_loop; 160 static int mswindows_in_modal_loop;
934 937
935 mswindows_enqueue_dispatch_event (emacs_event); 938 mswindows_enqueue_dispatch_event (emacs_event);
936 } 939 }
937 940
938 static void 941 static void
939 mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, DWORD when) 942 mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where,
940 { 943 DWORD when)
944 {
945 int downp = (msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN ||
946 msg == WM_RBUTTONDOWN);
941 947
942 /* We always use last message time, because mouse button 948 /* We always use last message time, because mouse button
943 events may get delayed, and XEmacs double click 949 events may get delayed, and XEmacs double click
944 recognition will fail */ 950 recognition will fail */
945 951
946 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 952 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
947 Lisp_Event* event = XEVENT(emacs_event); 953 Lisp_Event* event = XEVENT (emacs_event);
948 954
949 event->channel = mswindows_find_frame(hwnd); 955 mswindows_handle_sticky_modifiers (0, 0, downp, 0);
956 event->channel = mswindows_find_frame (hwnd);
950 event->timestamp = when; 957 event->timestamp = when;
951 event->event.button.button = 958 event->event.button.button =
952 (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 : 959 (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 :
953 ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2); 960 ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2);
954 event->event.button.x = where.x; 961 event->event.button.x = where.x;
955 event->event.button.y = where.y; 962 event->event.button.y = where.y;
956 event->event.button.modifiers = mswindows_modifier_state (NULL, 0); 963 event->event.button.modifiers = mswindows_modifier_state (NULL, 0);
957 964
958 if (msg==WM_LBUTTONDOWN || msg==WM_MBUTTONDOWN || 965 if (downp)
959 msg==WM_RBUTTONDOWN)
960 { 966 {
961 event->event_type = button_press_event; 967 event->event_type = button_press_event;
962 SetCapture (hwnd); 968 SetCapture (hwnd);
963 /* we need this to make sure the main window regains the focus 969 /* we need this to make sure the main window regains the focus
964 from control subwindows */ 970 from control subwindows */
1662 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top; 1668 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
1663 /* Normally we want to ignore expose events when child 1669 /* Normally we want to ignore expose events when child
1664 windows are unmapped, however once we are in the guts of 1670 windows are unmapped, however once we are in the guts of
1665 WM_PAINT we need to make sure that we don't register 1671 WM_PAINT we need to make sure that we don't register
1666 unmaps then because they will not actually occur. */ 1672 unmaps then because they will not actually occur. */
1673 /* #### commenting out the next line seems to fix some problems
1674 but not all. only andy currently understands this stuff and
1675 he needs to review it more carefully. --ben */
1667 if (!check_for_ignored_expose (frame, x, y, width, height)) 1676 if (!check_for_ignored_expose (frame, x, y, width, height))
1668 { 1677 {
1669 hold_ignored_expose_registration = 1; 1678 hold_ignored_expose_registration = 1;
1670 mswindows_redraw_exposed_area (frame, x, y, width, height); 1679 mswindows_redraw_exposed_area (frame, x, y, width, height);
1671 hold_ignored_expose_registration = 0; 1680 hold_ignored_expose_registration = 0;
1679 * is better handled by DefWindowProc 1688 * is better handled by DefWindowProc
1680 */ 1689 */
1681 static int 1690 static int
1682 key_needs_default_processing_p (UINT vkey) 1691 key_needs_default_processing_p (UINT vkey)
1683 { 1692 {
1684 if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU) 1693 if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU
1694 /* if we let ALT activate the menu like this, then sticky ALT-modified
1695 keystrokes become impossible. */
1696 && !modifier_keys_are_sticky)
1685 return 1; 1697 return 1;
1686 1698
1687 return 0; 1699 return 0;
1688 } 1700 }
1701
1702 /* key-handling code is always ugly. It just ends up working out
1703 that way.
1704
1705 #### Most of the sticky-modifier code below is copied from similar
1706 code in event-Xt.c. They should somehow or other be merged.
1707
1708 Here are some pointers:
1709
1710 -- DOWN_MASK indicates which modifiers should be treated as "down"
1711 when the corresponding upstroke happens. It gets reset for
1712 a particular modifier when that modifier goes up, and reset
1713 for all modifiers when a non-modifier key is pressed. Example:
1714
1715 I press Control-A-Shift and then release Control-A-Shift.
1716 I want the Shift key to be sticky but not the Control key.
1717
1718 -- If a modifier key is sticky, I can unstick it by pressing
1719 the modifier key again. */
1720
1721 static WPARAM last_downkey;
1722 static int need_to_add_mask, down_mask;
1723
1724 #define XEMSW_LCONTROL (1<<0)
1725 #define XEMSW_RCONTROL (1<<1)
1726 #define XEMSW_LSHIFT (1<<2)
1727 #define XEMSW_RSHIFT (1<<3)
1728 #define XEMSW_LMENU (1<<4)
1729 #define XEMSW_RMENU (1<<5)
1730
1731 static int
1732 mswindows_handle_sticky_modifiers (WPARAM wParam, LPARAM lParam,
1733 int downp, int keyp)
1734 {
1735 int mods = 0;
1736
1737 if (!modifier_keys_are_sticky) /* Optimize for non-sticky modifiers */
1738 return 0;
1739
1740 if (! (keyp &&
1741 (wParam == VK_CONTROL || wParam == VK_LCONTROL ||
1742 wParam == VK_RCONTROL ||
1743 wParam == VK_MENU || wParam == VK_LMENU ||
1744 wParam == VK_RMENU ||
1745 wParam == VK_SHIFT || wParam == VK_LSHIFT ||
1746 wParam == VK_RSHIFT)))
1747 { /* Not a modifier key */
1748 if (downp && keyp && !last_downkey)
1749 last_downkey = wParam;
1750 /* If I hold press-and-release the Control key and then press
1751 and hold down the right arrow, I want it to auto-repeat
1752 Control-Right. On the other hand, if I do the same but
1753 manually press the Right arrow a bunch of times, I want
1754 to see one Control-Right and then a bunch of Rights.
1755 This means that we need to distinguish between an
1756 auto-repeated key and a key pressed and released a bunch
1757 of times. */
1758 else if (downp && !keyp ||
1759 (downp && keyp && last_downkey &&
1760 (wParam != last_downkey ||
1761 /* the "previous key state" bit indicates autorepeat */
1762 ! (lParam & (1 << 30)))))
1763 {
1764 need_to_add_mask = 0;
1765 last_downkey = 0;
1766 }
1767 if (downp)
1768 down_mask = 0;
1769
1770 mods = need_to_add_mask;
1771 }
1772 else /* Modifier key pressed */
1773 {
1774 /* If a non-modifier key was pressed in the middle of a bunch
1775 of modifiers, then it unsticks all the modifiers that were
1776 previously pressed. We cannot unstick the modifiers until
1777 now because we want to check for auto-repeat of the
1778 non-modifier key. */
1779
1780 if (last_downkey)
1781 {
1782 last_downkey = 0;
1783 need_to_add_mask = 0;
1784 }
1785
1786 #define FROB(mask) \
1787 do { \
1788 if (downp && keyp) \
1789 { \
1790 /* If modifier key is already sticky, \
1791 then unstick it. Note that we do \
1792 not test down_mask to deal with the \
1793 unlikely but possible case that the \
1794 modifier key auto-repeats. */ \
1795 if (need_to_add_mask & mask) \
1796 { \
1797 need_to_add_mask &= ~mask; \
1798 down_mask &= ~mask; \
1799 } \
1800 else \
1801 down_mask |= mask; \
1802 } \
1803 else \
1804 { \
1805 if (down_mask & mask) \
1806 { \
1807 down_mask &= ~mask; \
1808 need_to_add_mask |= mask; \
1809 } \
1810 } \
1811 } while (0)
1812
1813 if (wParam == VK_CONTROL && (lParam & 0x1000000)
1814 || wParam == VK_RCONTROL)
1815 FROB (XEMSW_RCONTROL);
1816 if (wParam == VK_CONTROL && !(lParam & 0x1000000)
1817 || wParam == VK_LCONTROL)
1818 FROB (XEMSW_LCONTROL);
1819
1820 if (wParam == VK_SHIFT && (lParam & 0x1000000)
1821 || wParam == VK_RSHIFT)
1822 FROB (XEMSW_RSHIFT);
1823 if (wParam == VK_SHIFT && !(lParam & 0x1000000)
1824 || wParam == VK_LSHIFT)
1825 FROB (XEMSW_LSHIFT);
1826
1827 if (wParam == VK_MENU && (lParam & 0x1000000)
1828 || wParam == VK_RMENU)
1829 FROB (XEMSW_RMENU);
1830 if (wParam == VK_MENU && !(lParam & 0x1000000)
1831 || wParam == VK_LMENU)
1832 FROB (XEMSW_LMENU);
1833 }
1834 #undef FROB
1835
1836 if (mods && downp)
1837 {
1838 BYTE keymap[256];
1839
1840 GetKeyboardState (keymap);
1841
1842 if (mods & XEMSW_LCONTROL)
1843 {
1844 keymap [VK_CONTROL] |= 0x80;
1845 keymap [VK_LCONTROL] |= 0x80;
1846 }
1847 if (mods & XEMSW_RCONTROL)
1848 {
1849 keymap [VK_CONTROL] |= 0x80;
1850 keymap [VK_RCONTROL] |= 0x80;
1851 }
1852
1853 if (mods & XEMSW_LSHIFT)
1854 {
1855 keymap [VK_SHIFT] |= 0x80;
1856 keymap [VK_LSHIFT] |= 0x80;
1857 }
1858 if (mods & XEMSW_RSHIFT)
1859 {
1860 keymap [VK_SHIFT] |= 0x80;
1861 keymap [VK_RSHIFT] |= 0x80;
1862 }
1863
1864 if (mods & XEMSW_LMENU)
1865 {
1866 keymap [VK_MENU] |= 0x80;
1867 keymap [VK_LMENU] |= 0x80;
1868 }
1869 if (mods & XEMSW_RMENU)
1870 {
1871 keymap [VK_MENU] |= 0x80;
1872 keymap [VK_RMENU] |= 0x80;
1873 }
1874
1875 SetKeyboardState (keymap);
1876 return 1;
1877 }
1878
1879 return 0;
1880 }
1881
1882 static void
1883 clear_sticky_modifiers (void)
1884 {
1885 need_to_add_mask = 0;
1886 last_downkey = 0;
1887 down_mask = 0;
1888 }
1889
1890 #ifdef DEBUG_XEMACS
1891
1892 static void
1893 output_modifier_keyboard_state (void)
1894 {
1895 BYTE keymap[256];
1896
1897 GetKeyboardState (keymap);
1898
1899 stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1900 keymap[VK_MENU] & 0x80 ? 1 : 0,
1901 keymap[VK_MENU] & 0x1 ? 1 : 0,
1902 keymap[VK_LMENU] & 0x80 ? 1 : 0,
1903 keymap[VK_LMENU] & 0x1 ? 1 : 0,
1904 keymap[VK_RMENU] & 0x80 ? 1 : 0,
1905 keymap[VK_RMENU] & 0x1 ? 1 : 0);
1906 stderr_out ("GetKeyboardState VK_CONTROL %d %d VK_LCONTROL %d %d VK_RCONTROL %d %d\n",
1907 keymap[VK_CONTROL] & 0x80 ? 1 : 0,
1908 keymap[VK_CONTROL] & 0x1 ? 1 : 0,
1909 keymap[VK_LCONTROL] & 0x80 ? 1 : 0,
1910 keymap[VK_LCONTROL] & 0x1 ? 1 : 0,
1911 keymap[VK_RCONTROL] & 0x80 ? 1 : 0,
1912 keymap[VK_RCONTROL] & 0x1 ? 1 : 0);
1913 stderr_out ("GetKeyboardState VK_SHIFT %d %d VK_LSHIFT %d %d VK_RSHIFT %d %d\n",
1914 keymap[VK_SHIFT] & 0x80 ? 1 : 0,
1915 keymap[VK_SHIFT] & 0x1 ? 1 : 0,
1916 keymap[VK_LSHIFT] & 0x80 ? 1 : 0,
1917 keymap[VK_LSHIFT] & 0x1 ? 1 : 0,
1918 keymap[VK_RSHIFT] & 0x80 ? 1 : 0,
1919 keymap[VK_RSHIFT] & 0x1 ? 1 : 0);
1920 }
1921
1922 /* try to debug the stuck-alt-key problem.
1923
1924 #### this happens only inconsistently, and may only happen when using
1925 StickyKeys in the Win2000 accessibility section of the control panel,
1926 which is extremely broken for other reasons. */
1927
1928 static void
1929 output_alt_keyboard_state (void)
1930 {
1931 BYTE keymap[256];
1932 SHORT keystate[3];
1933 // SHORT asyncstate[3];
1934
1935 GetKeyboardState (keymap);
1936 keystate[0] = GetKeyState (VK_MENU);
1937 keystate[1] = GetKeyState (VK_LMENU);
1938 keystate[2] = GetKeyState (VK_RMENU);
1939 /* Doing this interferes with key processing. */
1940 /* asyncstate[0] = GetAsyncKeyState (VK_MENU); */
1941 /* asyncstate[1] = GetAsyncKeyState (VK_LMENU); */
1942 /* asyncstate[2] = GetAsyncKeyState (VK_RMENU); */
1943
1944 stderr_out ("GetKeyboardState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1945 keymap[VK_MENU] & 0x80 ? 1 : 0,
1946 keymap[VK_MENU] & 0x1 ? 1 : 0,
1947 keymap[VK_LMENU] & 0x80 ? 1 : 0,
1948 keymap[VK_LMENU] & 0x1 ? 1 : 0,
1949 keymap[VK_RMENU] & 0x80 ? 1 : 0,
1950 keymap[VK_RMENU] & 0x1 ? 1 : 0);
1951 stderr_out ("GetKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n",
1952 keystate[0] & 0x8000 ? 1 : 0,
1953 keystate[0] & 0x1 ? 1 : 0,
1954 keystate[1] & 0x8000 ? 1 : 0,
1955 keystate[1] & 0x1 ? 1 : 0,
1956 keystate[2] & 0x8000 ? 1 : 0,
1957 keystate[2] & 0x1 ? 1 : 0);
1958 /* stderr_out ("GetAsyncKeyState VK_MENU %d %d VK_LMENU %d %d VK_RMENU %d %d\n", */
1959 /* asyncstate[0] & 0x8000 ? 1 : 0, */
1960 /* asyncstate[0] & 0x1 ? 1 : 0, */
1961 /* asyncstate[1] & 0x8000 ? 1 : 0, */
1962 /* asyncstate[1] & 0x1 ? 1 : 0, */
1963 /* asyncstate[2] & 0x8000 ? 1 : 0, */
1964 /* asyncstate[2] & 0x1 ? 1 : 0); */
1965 }
1966
1967 #endif /* DEBUG_XEMACS */
1968
1689 1969
1690 /* 1970 /*
1691 * The windows procedure for the window class XEMACS_CLASS 1971 * The windows procedure for the window class XEMACS_CLASS
1692 */ 1972 */
1693 LRESULT WINAPI 1973 LRESULT WINAPI
1694 mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 1974 mswindows_wnd_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1695 { 1975 {
1696 /* Note: Remember to initialize emacs_event and event before use. 1976 /* Note: Remember to initialize emacs_event and event before use.
1697 This code calls code that can GC. You must GCPRO before calling such code. */ 1977 This code calls code that can GC. You must GCPRO before calling such code. */
1698 Lisp_Object emacs_event = Qnil; 1978 Lisp_Object emacs_event = Qnil;
1699 Lisp_Object fobj = Qnil; 1979 Lisp_Object fobj = Qnil;
1724 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt)); 2004 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt));
1725 break; 2005 break;
1726 2006
1727 case WM_KEYUP: 2007 case WM_KEYUP:
1728 case WM_SYSKEYUP: 2008 case WM_SYSKEYUP:
2009
1729 /* See Win95 comment under WM_KEYDOWN */ 2010 /* See Win95 comment under WM_KEYDOWN */
1730 { 2011 {
1731 BYTE keymap[256]; 2012 BYTE keymap[256];
1732 int should_set_keymap = 0; 2013 int should_set_keymap = 0;
1733 2014
2015 #ifdef DEBUG_XEMACS
2016 if (mswindows_debug_events)
2017 {
2018 stderr_out ("%s wparam=%d lparam=%d\n",
2019 message == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP",
2020 wParam, (int)lParam);
2021 output_alt_keyboard_state ();
2022 }
2023 #endif /* DEBUG_XEMACS */
2024
2025 mswindows_handle_sticky_modifiers (wParam, lParam, 0, 1);
1734 if (wParam == VK_CONTROL) 2026 if (wParam == VK_CONTROL)
1735 { 2027 {
1736 GetKeyboardState (keymap); 2028 GetKeyboardState (keymap);
1737 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80; 2029 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80;
1738 should_set_keymap = 1; 2030 should_set_keymap = 1;
1742 GetKeyboardState (keymap); 2034 GetKeyboardState (keymap);
1743 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80; 2035 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80;
1744 should_set_keymap = 1; 2036 should_set_keymap = 1;
1745 } 2037 }
1746 2038
1747 if (should_set_keymap 2039 if (should_set_keymap)
1748 && (message != WM_SYSKEYUP 2040 // && (message != WM_SYSKEYUP
1749 || NILP (Vmenu_accelerator_enabled))) 2041 // || NILP (Vmenu_accelerator_enabled)))
1750 SetKeyboardState (keymap); 2042 SetKeyboardState (keymap);
1751 2043
1752 } 2044 }
2045
1753 if (key_needs_default_processing_p (wParam)) 2046 if (key_needs_default_processing_p (wParam))
1754 goto defproc; 2047 goto defproc;
1755 else 2048 else
1756 break; 2049 break;
1757 2050
1758 case WM_KEYDOWN: 2051 case WM_KEYDOWN:
1759 case WM_SYSKEYDOWN: 2052 case WM_SYSKEYDOWN:
2053
1760 /* In some locales the right-hand Alt key is labelled AltGr. This key 2054 /* In some locales the right-hand Alt key is labelled AltGr. This key
1761 * should produce alternative charcaters when combined with another key. 2055 * should produce alternative charcaters when combined with another key.
1762 * eg on a German keyboard pressing AltGr+q should produce '@'. 2056 * eg on a German keyboard pressing AltGr+q should produce '@'.
1763 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if 2057 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if
1764 * TranslateMessage() is called with *any* combination of Ctrl+Alt down, 2058 * TranslateMessage() is called with *any* combination of Ctrl+Alt down,
1765 * it translates as if AltGr were down. 2059 * it translates as if AltGr were down.
1766 * We get round this by removing all modifiers from the keymap before 2060 * We get round this by removing all modifiers from the keymap before
1767 * calling TranslateMessage() unless AltGr is *really* down. */ 2061 * calling TranslateMessage() unless AltGr is *really* down. */
1768 { 2062 {
1769 BYTE keymap[256]; 2063 BYTE keymap_trans[256];
2064 BYTE keymap_orig[256];
2065 BYTE keymap_sticky[256];
1770 int has_AltGr = mswindows_current_layout_has_AltGr (); 2066 int has_AltGr = mswindows_current_layout_has_AltGr ();
1771 int mods; 2067 int mods = 0;
1772 int extendedp = lParam & 0x1000000; 2068 int extendedp = lParam & 0x1000000;
1773 Lisp_Object keysym; 2069 Lisp_Object keysym;
1774 2070 int sticky_changed;
2071
2072 #ifdef DEBUG_XEMACS
2073 if (mswindows_debug_events)
2074 {
2075 stderr_out ("%s wparam=%d lparam=%d\n",
2076 message == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
2077 wParam, (int)lParam);
2078 output_alt_keyboard_state ();
2079 }
2080 #endif /* DEBUG_XEMACS */
2081
2082 GetKeyboardState (keymap_orig);
1775 frame = XFRAME (mswindows_find_frame (hwnd)); 2083 frame = XFRAME (mswindows_find_frame (hwnd));
1776 GetKeyboardState (keymap); 2084 if ((sticky_changed =
1777 mods = mswindows_modifier_state (keymap, has_AltGr); 2085 mswindows_handle_sticky_modifiers (wParam, lParam, 1, 1)))
2086 {
2087 GetKeyboardState (keymap_sticky);
2088 if (keymap_sticky[VK_MENU] & 0x80)
2089 {
2090 message = WM_SYSKEYDOWN;
2091 /* We have to set the "context bit" so that the
2092 TranslateMessage() call below that generates the
2093 SYSCHAR message does its thing; see the documentation
2094 on WM_SYSKEYDOWN */
2095 lParam |= 1 << 29;
2096 }
2097 }
2098 else
2099 memcpy (keymap_sticky, keymap_orig, 256);
2100
2101 mods = mswindows_modifier_state (keymap_sticky, has_AltGr);
1778 2102
1779 /* Handle non-printables */ 2103 /* Handle non-printables */
1780 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods, 2104 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
1781 extendedp))) 2105 extendedp)))
1782 mswindows_enqueue_keypress_event (hwnd, keysym, mods); 2106 {
2107 mswindows_enqueue_keypress_event (hwnd, keysym, mods);
2108 if (sticky_changed)
2109 SetKeyboardState (keymap_orig);
2110 }
1783 else /* Normal keys & modifiers */ 2111 else /* Normal keys & modifiers */
1784 { 2112 {
1785 Emchar quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); 2113 Emchar quit_ch =
1786 BYTE keymap_orig[256]; 2114 CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
1787 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; 2115 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
1788 MSG msg, tranmsg; 2116 MSG msg, tranmsg;
1789 int potential_accelerator = 0; 2117 int potential_accelerator = 0;
1790 int got_accelerator = 0; 2118 int got_accelerator = 0;
1791 2119
1798 2126
1799 /* GetKeyboardState() does not work as documented on Win95. We have 2127 /* GetKeyboardState() does not work as documented on Win95. We have
1800 * to loosely track Left and Right modifiers on behalf of the OS, 2128 * to loosely track Left and Right modifiers on behalf of the OS,
1801 * without screwing up Windows NT which tracks them properly. */ 2129 * without screwing up Windows NT which tracks them properly. */
1802 if (wParam == VK_CONTROL) 2130 if (wParam == VK_CONTROL)
1803 keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; 2131 {
2132 keymap_orig[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
2133 keymap_sticky[extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80;
2134 }
1804 else if (wParam == VK_MENU) 2135 else if (wParam == VK_MENU)
1805 keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80; 2136 {
1806 2137 keymap_orig[extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
1807 memcpy (keymap_orig, keymap, 256); 2138 keymap_sticky[extendedp ? VK_RMENU : VK_LMENU] |= 0x80;
2139 }
1808 2140
1809 if (!NILP (Vmenu_accelerator_enabled) && 2141 if (!NILP (Vmenu_accelerator_enabled) &&
1810 !(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN) 2142 !(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN)
1811 potential_accelerator = 1; 2143 potential_accelerator = 1;
1812 2144
1813 /* Remove shift modifier from an ascii character */ 2145 /* Remove shift modifier from an ascii character */
1814 mods &= ~XEMACS_MOD_SHIFT; 2146 mods &= ~XEMACS_MOD_SHIFT;
1815 2147
2148 memcpy (keymap_trans, keymap_sticky, 256);
2149
1816 /* Clear control and alt modifiers unless AltGr is pressed */ 2150 /* Clear control and alt modifiers unless AltGr is pressed */
1817 keymap [VK_RCONTROL] = 0; 2151 keymap_trans[VK_RCONTROL] = 0;
1818 keymap [VK_LMENU] = 0; 2152 keymap_trans[VK_LMENU] = 0;
1819 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) 2153 if (!has_AltGr || !(keymap_trans[VK_LCONTROL] & 0x80)
1820 || !(keymap [VK_RMENU] & 0x80)) 2154 || !(keymap_trans[VK_RMENU] & 0x80))
1821 { 2155 {
1822 keymap [VK_LCONTROL] = 0; 2156 keymap_trans[VK_LCONTROL] = 0;
1823 keymap [VK_CONTROL] = 0; 2157 keymap_trans[VK_CONTROL] = 0;
1824 keymap [VK_RMENU] = 0; 2158 keymap_trans[VK_RMENU] = 0;
1825 keymap [VK_MENU] = 0; 2159 keymap_trans[VK_MENU] = 0;
1826 } 2160 }
1827 SetKeyboardState (keymap); 2161 SetKeyboardState (keymap_trans);
1828 2162
1829 /* Maybe generate some WM_[SYS]CHARs in the queue */ 2163 /* Maybe generate some WM_[SYS]CHARs in the queue */
1830 TranslateMessage (&msg); 2164 TranslateMessage (&msg);
1831 2165
1832 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) 2166 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE)
1833 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) 2167 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR,
2168 PM_REMOVE))
1834 { 2169 {
1835 int mods1 = mods; 2170 int mods1 = mods;
1836 WPARAM ch = tranmsg.wParam; 2171 WPARAM ch = tranmsg.wParam;
1837 2172
1838 /* If a quit char with no modifiers other than control and 2173 /* If a quit char with no modifiers other than control and
1839 shift, then mark it with a fake modifier, which is removed 2174 shift, then mark it with a fake modifier, which is removed
1840 upon dequeueing the event */ 2175 upon dequeueing the event */
1841 /* #### This might also not withstand localization, if 2176 /* #### This might also not withstand localization, if
1842 quit character is not a latin-1 symbol */ 2177 quit character is not a latin-1 symbol */
1843 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) && quit_ch + 'a' - 1 == ch) 2178 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL)
1844 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) && quit_ch == ch)) 2179 && quit_ch + 'a' - 1 == ch)
1845 && ((mods & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) == 0)) 2180 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL)
2181 && quit_ch == ch))
2182 && ((mods & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT))
2183 == 0))
1846 { 2184 {
1847 mods1 |= FAKE_MOD_QUIT; 2185 mods1 |= FAKE_MOD_QUIT;
1848 ++mswindows_quit_chars_count; 2186 ++mswindows_quit_chars_count;
1849 } 2187 }
1850 else if (potential_accelerator && !got_accelerator && 2188 else if (potential_accelerator && !got_accelerator &&
1853 got_accelerator = 1; 2191 got_accelerator = 1;
1854 break; 2192 break;
1855 } 2193 }
1856 mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1); 2194 mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1);
1857 } /* while */ 2195 } /* while */
1858 SetKeyboardState (keymap_orig); 2196
1859 /* This generates WM_SYSCHAR messages, which are interpreted 2197 /* This generates WM_SYSCHAR messages, which are interpreted
1860 by DefWindowProc as the menu selections. */ 2198 by DefWindowProc as the menu selections. */
1861 if (got_accelerator) 2199 if (got_accelerator)
1862 { 2200 {
2201 SetKeyboardState (keymap_sticky);
1863 TranslateMessage (&msg); 2202 TranslateMessage (&msg);
2203 SetKeyboardState (keymap_orig);
1864 goto defproc; 2204 goto defproc;
1865 } 2205 }
2206
2207 SetKeyboardState (keymap_orig);
1866 } /* else */ 2208 } /* else */
1867 } 2209 }
2210
1868 if (key_needs_default_processing_p (wParam)) 2211 if (key_needs_default_processing_p (wParam))
1869 goto defproc; 2212 goto defproc;
1870 else 2213 else
1871 break; 2214 break;
1872 2215
2387 widget_brush = CreateSolidBrush 2730 widget_brush = CreateSolidBrush
2388 (COLOR_INSTANCE_MSWINDOWS_COLOR 2731 (COLOR_INSTANCE_MSWINDOWS_COLOR
2389 (XCOLOR_INSTANCE 2732 (XCOLOR_INSTANCE
2390 (FACE_BACKGROUND 2733 (FACE_BACKGROUND
2391 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), 2734 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2392 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); 2735 XIMAGE_INSTANCE_FRAME (image_instance)))));
2393 } 2736 }
2394 last_widget_brushed = ii; 2737 last_widget_brushed = ii;
2395 SetTextColor 2738 SetTextColor
2396 (hdc, 2739 (hdc,
2397 COLOR_INSTANCE_MSWINDOWS_COLOR 2740 COLOR_INSTANCE_MSWINDOWS_COLOR
2398 (XCOLOR_INSTANCE 2741 (XCOLOR_INSTANCE
2399 (FACE_FOREGROUND 2742 (FACE_FOREGROUND
2400 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), 2743 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2401 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); 2744 XIMAGE_INSTANCE_FRAME (image_instance)))));
2402 SetBkMode (hdc, OPAQUE); 2745 SetBkMode (hdc, OPAQUE);
2403 SetBkColor 2746 SetBkColor
2404 (hdc, 2747 (hdc,
2405 COLOR_INSTANCE_MSWINDOWS_COLOR 2748 COLOR_INSTANCE_MSWINDOWS_COLOR
2406 (XCOLOR_INSTANCE 2749 (XCOLOR_INSTANCE
2407 (FACE_BACKGROUND 2750 (FACE_BACKGROUND
2408 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), 2751 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2409 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); 2752 XIMAGE_INSTANCE_FRAME (image_instance)))));
2410 return (LRESULT)widget_brush; 2753 return (LRESULT)widget_brush;
2411 } 2754 }
2412 } 2755 }
2413 } 2756 }
2414 goto defproc; 2757 goto defproc;
2580 } 2923 }
2581 2924
2582 2925
2583 /* Returns the state of the modifier keys in the format expected by the 2926 /* Returns the state of the modifier keys in the format expected by the
2584 * Lisp_Event key_data, button_data and motion_data modifiers member */ 2927 * Lisp_Event key_data, button_data and motion_data modifiers member */
2585 int mswindows_modifier_state (BYTE* keymap, int has_AltGr) 2928 static int
2929 mswindows_modifier_state (BYTE* keymap, int has_AltGr)
2586 { 2930 {
2587 int mods = 0; 2931 int mods = 0;
2932 BYTE keymap2[256];
2588 2933
2589 if (keymap == NULL) 2934 if (keymap == NULL)
2590 { 2935 {
2591 keymap = (BYTE*) alloca(256); 2936 keymap = keymap2;
2592 GetKeyboardState (keymap); 2937 GetKeyboardState (keymap);
2593 has_AltGr = mswindows_current_layout_has_AltGr (); 2938 has_AltGr = mswindows_current_layout_has_AltGr ();
2594 } 2939 }
2595 2940
2596 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) 2941 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80))
2837 { 3182 {
2838 Lisp_Object frame = EVENT_CHANNEL (emacs_event); 3183 Lisp_Object frame = EVENT_CHANNEL (emacs_event);
2839 struct frame *f = XFRAME (frame); 3184 struct frame *f = XFRAME (frame);
2840 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS); 3185 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS);
2841 Lisp_Object conser; 3186 Lisp_Object conser;
2842 3187 struct gcpro gcpro1;
2843 /* struct gcpro gcpro1; */ 3188
2844 3189 /* On focus change, clear all memory of sticky modifiers
2845 /* Clear sticky modifiers here (if we had any) */ 3190 to avoid non-intuitive behavior. */
3191 clear_sticky_modifiers ();
2846 3192
2847 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); 3193 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
2848 /* GCPRO1 (conser); XXX Not necessary? */ 3194 GCPRO1 (conser);
2849 emacs_handle_focus_change_preliminary (conser); 3195 emacs_handle_focus_change_preliminary (conser);
2850 /* Under X the stuff up to here is done in the X event handler. 3196 /* Under X the stuff up to here is done in the X event handler.
2851 I Don't know why */ 3197 I Don't know why */
2852 emacs_handle_focus_change_final (conser); 3198 emacs_handle_focus_change_final (conser);
2853 /* UNGCPRO; */ 3199 UNGCPRO;
2854 3200
2855 } 3201 }
2856 break; 3202 break;
2857 3203
2858 case XM_MAPFRAME: 3204 case XM_MAPFRAME:
3163 pdump_wire (&mswindows_s_dispatch_event_queue_tail); 3509 pdump_wire (&mswindows_s_dispatch_event_queue_tail);
3164 3510
3165 mswindows_error_caught_in_modal_loop = Qnil; 3511 mswindows_error_caught_in_modal_loop = Qnil;
3166 staticpro (&mswindows_error_caught_in_modal_loop); 3512 staticpro (&mswindows_error_caught_in_modal_loop);
3167 3513
3514
3515 #ifdef DEBUG_XEMACS
3516 DEFVAR_INT ("mswindows-debug-events", &mswindows_debug_events /*
3517 If non-zero, display debug information about Windows events that XEmacs sees.
3518 Information is displayed in a console window. Currently defined values are:
3519
3520 1 == non-verbose output
3521 2 == verbose output
3522
3523 #### Unfortunately, not yet implemented.
3524 */ );
3525 mswindows_debug_events = 0;
3526 #endif
3527
3168 DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu", 3528 DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu",
3169 &mswindows_alt_by_itself_activates_menu /* 3529 &mswindows_alt_by_itself_activates_menu /*
3170 *Controls whether pressing and releasing the Alt key activates the menubar. 3530 *Controls whether pressing and releasing the Alt key activates the menubar.
3171 This applies only if no intervening key was pressed. See also 3531 This applies only if no intervening key was pressed. See also
3172 `menu-accelerator-enabled', which is probably the behavior you actually want. 3532 `menu-accelerator-enabled', which is probably the behavior you actually want.