Mercurial > hg > xemacs-beta
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. |