Mercurial > emacs
comparison src/w32term.c @ 19713:043ccce224fb
(SIF_*): Win95 macros defined for NT.
(struct tagSCROLLINFO): Win95 struct defined for NT.
(vertical_scroll_bar_min_handle, vertical_scroll_bar_top_border,
vertical_scroll_bar_bottom_border, last_scroll_bar_drag_pos,
Vw32_gab_focus_on_raise, Vw32_capslock_is_shiftlock): New
variables.
(w32_frame_up_to_date): Block input.
(do_line_dance): Use DC while erasing, release at end.
(show_mouse_face): Use column and endcolumn calculated at start of
loop.
(my_create_scrollbar, my_show_window, my_set_window_pos,
my_set_focus) [! ATTACH_THREADS]: Send message to window instead
of invoking Windows procedure.
(x_scroll_bar_create, x_scroll_bar_move, x_scroll_bar_handle_click,
x_scroll_bar_report_motion): Use SCROLLINFO for proportional handle.
(x_scroll_bar_set_handle): Create proportional sized scroll handle.
(w32_set_vertical_scroll_bar): Size handle according to how much
is showing in window.
(x_scroll_bar_set_report_motion): Use top_range, calculated above.
(x_scroll_bar_clear): Hide scroll bar until ready to repaint.
(show_scroll_bars): Pass in frame to my_show_window.
(w32_read_socket): Distinguish between invisible and obscured frames
when handling PAINT messages.
Fixup off-by-one calculation for PAINT and SIZE.
Pass in new parameter to w32_kbd_mods_to_emacs.
Handle WM_DISPLAYCHANGE, WINDOWPOSCHANGED, ACTIVATE, SHOWWINDOW,
INITMENU, and ACTIVATEAPP messages.
Explicitly check for visibile and obscured frames, and to see if
any event should cause a redisplay.
(x_display_bar_cursor): Don't check whether frame is updating here.
(x_display_cursor): Check it here instead.
(x_set_offset) [HAVE_NTGUI]: Don't add border widths.
Set NOACTIVATE when setting window position.
(x_set_window_size): Fixup off-by-one calculation when setting
window position. Mark frame garbaged earlier. Clear mouse
highlighting state.
(x_focus_on_frame): Set focus by making frame the foreground window.
(x_raise_frame): Support frames to be raised without grabbing focus.
(x_lower_frame): Set NOACTIVATE flag when setting window position.
(x_make_frame_visible, x_make_frame_invisible): Pass in frame
to my_show_window.
to my_show_window.
(x_iconify_frame): Send a MINIMIZE message to the window.
(x_wm_set_size_hint): Set font width, line height, border,
and scroll bar indexes instead of X and Y unit indexes.
(w32_initialize): Set input mode. Use w32_msg_worker instead
of windows_msg_worker. Dynamically link proportional scroll bar
functions and intialize proportional scroll bar variables.
(syms_of_w32term): DEFVAR new variables.
(construct_mouse_wheel): New function. Constructs an
input event from a WM_MOUSEWHEEL message.
(w32_read_socket): Handle WM_MOUSEWHEEL.
(w32_read_socket): Pass in new parameter to key_event.
Let key_event determine whether key is dead.
For MOVE, use x_real_positions to map to client coords.
(x_set_mouse_pixel_position): Offset to use client area as origin.
author | Geoff Voelker <voelker@cs.washington.edu> |
---|---|
date | Wed, 03 Sep 1997 01:07:37 +0000 |
parents | d3e5a5f5fe02 |
children | b4fe0e8ac819 |
comparison
equal
deleted
inserted
replaced
19712:9a6e50f6b471 | 19713:043ccce224fb |
---|---|
25 #include <stdio.h> | 25 #include <stdio.h> |
26 #include "lisp.h" | 26 #include "lisp.h" |
27 #include "charset.h" | 27 #include "charset.h" |
28 #include "blockinput.h" | 28 #include "blockinput.h" |
29 | 29 |
30 #include <w32term.h> | 30 #include "w32term.h" |
31 | 31 |
32 #include "systty.h" | 32 #include "systty.h" |
33 #include "systime.h" | 33 #include "systime.h" |
34 | 34 |
35 #include <ctype.h> | 35 #include <ctype.h> |
93 DWORD dwWindowsThreadId = 0; | 93 DWORD dwWindowsThreadId = 0; |
94 HANDLE hWindowsThread = NULL; | 94 HANDLE hWindowsThread = NULL; |
95 DWORD dwMainThreadId = 0; | 95 DWORD dwMainThreadId = 0; |
96 HANDLE hMainThread = NULL; | 96 HANDLE hMainThread = NULL; |
97 | 97 |
98 #ifndef SIF_ALL | |
99 /* These definitions are new with Windows 95. */ | |
100 #define SIF_RANGE 0x0001 | |
101 #define SIF_PAGE 0x0002 | |
102 #define SIF_POS 0x0004 | |
103 #define SIF_DISABLENOSCROLL 0x0008 | |
104 #define SIF_TRACKPOS 0x0010 | |
105 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS) | |
106 | |
107 typedef struct tagSCROLLINFO | |
108 { | |
109 UINT cbSize; | |
110 UINT fMask; | |
111 int nMin; | |
112 int nMax; | |
113 UINT nPage; | |
114 int nPos; | |
115 int nTrackPos; | |
116 } SCROLLINFO, FAR *LPSCROLLINFO; | |
117 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO; | |
118 #endif /* SIF_ALL */ | |
119 | |
120 /* Dynamic linking to new proportional scroll bar functions. */ | |
121 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw); | |
122 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi); | |
123 | |
124 int vertical_scroll_bar_min_handle; | |
125 int vertical_scroll_bar_top_border; | |
126 int vertical_scroll_bar_bottom_border; | |
127 | |
128 int last_scroll_bar_drag_pos; | |
129 | |
98 /* Mouse movement. */ | 130 /* Mouse movement. */ |
99 | 131 |
100 /* Where the mouse was last time we reported a mouse event. */ | 132 /* Where the mouse was last time we reported a mouse event. */ |
101 static FRAME_PTR last_mouse_frame; | 133 static FRAME_PTR last_mouse_frame; |
102 static RECT last_mouse_glyph; | 134 static RECT last_mouse_glyph; |
103 | 135 |
104 Lisp_Object Vw32_num_mouse_buttons; | 136 Lisp_Object Vw32_num_mouse_buttons; |
105 | 137 |
106 Lisp_Object Vw32_swap_mouse_buttons; | 138 Lisp_Object Vw32_swap_mouse_buttons; |
139 | |
140 /* Control whether x_raise_frame also sets input focus. */ | |
141 Lisp_Object Vw32_grab_focus_on_raise; | |
142 | |
143 /* Control whether Caps Lock affects non-ascii characters. */ | |
144 Lisp_Object Vw32_capslock_is_shiftlock; | |
107 | 145 |
108 /* The scroll bar in which the last motion event occurred. | 146 /* The scroll bar in which the last motion event occurred. |
109 | 147 |
110 If the last motion event occurred in a scroll bar, we set this | 148 If the last motion event occurred in a scroll bar, we set this |
111 so w32_mouse_position can know whether to report a scroll bar motion or | 149 so w32_mouse_position can know whether to report a scroll bar motion or |
322 | 360 |
323 static | 361 static |
324 w32_frame_up_to_date (f) | 362 w32_frame_up_to_date (f) |
325 FRAME_PTR f; | 363 FRAME_PTR f; |
326 { | 364 { |
365 BLOCK_INPUT; | |
327 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc | 366 if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc |
328 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame) | 367 || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame) |
329 { | 368 { |
330 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame, | 369 note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame, |
331 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x, | 370 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x, |
332 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y); | 371 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y); |
333 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0; | 372 FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0; |
334 } | 373 } |
374 UNBLOCK_INPUT; | |
335 } | 375 } |
336 | 376 |
337 /* External interface to control of standout mode. | 377 /* External interface to control of standout mode. |
338 Call this when about to modify line at position VPOS | 378 Call this when about to modify line at position VPOS |
339 and not change whether it is highlighted. */ | 379 and not change whether it is highlighted. */ |
873 intborder, CHAR_TO_PIXEL_ROW (f, j+1), | 913 intborder, CHAR_TO_PIXEL_ROW (f, j+1), |
874 SRCCOPY); | 914 SRCCOPY); |
875 i = j+1; | 915 i = j+1; |
876 } | 916 } |
877 | 917 |
878 release_frame_dc (f, hdc); | |
879 | |
880 for (i = 0; i < ht; ++i) | 918 for (i = 0; i < ht; ++i) |
881 if (line_dance[i] == -1) | 919 if (line_dance[i] == -1) |
882 { | 920 { |
883 for (j = i; j < ht && line_dance[j] == -1; ++j); | 921 for (j = i; j < ht && line_dance[j] == -1; ++j); |
884 /* Clear [i,j) */ | 922 /* Clear [i,j) */ |
885 w32_clear_area (f, NULL, | 923 w32_clear_area (f, hdc, |
886 intborder, | 924 intborder, |
887 CHAR_TO_PIXEL_ROW (f, i), | 925 CHAR_TO_PIXEL_ROW (f, i), |
888 f->width * FONT_WIDTH (f->output_data.w32->font), | 926 f->width * FONT_WIDTH (f->output_data.w32->font), |
889 (j-i) * f->output_data.w32->line_height); | 927 (j-i) * f->output_data.w32->line_height); |
890 i = j-1; | 928 i = j-1; |
891 } | 929 } |
892 line_dance_in_progress = 0; | 930 line_dance_in_progress = 0; |
931 | |
932 release_frame_dc (f, hdc); | |
893 } | 933 } |
894 | 934 |
895 /* Support routines for exposure events. */ | 935 /* Support routines for exposure events. */ |
896 static void clear_cursor (); | 936 static void clear_cursor (); |
897 | 937 |
1263 XSETINT (result->y, HIWORD (msg->msg.lParam)); | 1303 XSETINT (result->y, HIWORD (msg->msg.lParam)); |
1264 XSETFRAME (result->frame_or_window, f); | 1304 XSETFRAME (result->frame_or_window, f); |
1265 } | 1305 } |
1266 } | 1306 } |
1267 | 1307 |
1308 static void | |
1309 construct_mouse_wheel (result, msg, f) | |
1310 struct input_event *result; | |
1311 W32Msg *msg; | |
1312 struct frame *f; | |
1313 { | |
1314 POINT p; | |
1315 result->kind = mouse_wheel; | |
1316 result->code = (short) HIWORD (msg->msg.wParam); | |
1317 result->timestamp = msg->msg.time; | |
1318 result->modifiers = msg->dwModifiers; | |
1319 p.x = LOWORD (msg->msg.lParam); | |
1320 p.y = HIWORD (msg->msg.lParam); | |
1321 ScreenToClient(msg->msg.hwnd, &p); | |
1322 XSETINT (result->x, p.x); | |
1323 XSETINT (result->y, p.y); | |
1324 XSETFRAME (result->frame_or_window, f); | |
1325 } | |
1326 | |
1268 | 1327 |
1269 /* Function to report a mouse movement to the mainstream Emacs code. | 1328 /* Function to report a mouse movement to the mainstream Emacs code. |
1270 The input handler calls this. | 1329 The input handler calls this. |
1271 | 1330 |
1272 We have received a mouse movement event, which is given in *event. | 1331 We have received a mouse movement event, which is given in *event. |
1604 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); | 1663 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]); |
1605 | 1664 |
1606 /* If the cursor's in the text we are about to rewrite, | 1665 /* If the cursor's in the text we are about to rewrite, |
1607 turn the cursor off. */ | 1666 turn the cursor off. */ |
1608 if (i == curs_y | 1667 if (i == curs_y |
1609 && curs_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col - 1 | 1668 && curs_x >= column - 1 |
1610 && curs_x <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col) | 1669 && curs_x <= endcolumn) |
1611 { | 1670 { |
1612 x_display_cursor (f, 0); | 1671 x_display_cursor (f, 0); |
1613 cursor_off = 1; | 1672 cursor_off = 1; |
1614 } | 1673 } |
1615 | 1674 |
1688 FRAME_PTR f1; | 1747 FRAME_PTR f1; |
1689 | 1748 |
1690 BLOCK_INPUT; | 1749 BLOCK_INPUT; |
1691 | 1750 |
1692 if (! NILP (last_mouse_scroll_bar)) | 1751 if (! NILP (last_mouse_scroll_bar)) |
1752 /* This is never called at the moment. */ | |
1693 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); | 1753 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); |
1694 else | 1754 else |
1695 { | 1755 { |
1696 POINT pt; | 1756 POINT pt; |
1697 | 1757 |
1801 HWND | 1861 HWND |
1802 my_create_scrollbar (f, bar) | 1862 my_create_scrollbar (f, bar) |
1803 struct frame * f; | 1863 struct frame * f; |
1804 struct scroll_bar * bar; | 1864 struct scroll_bar * bar; |
1805 { | 1865 { |
1806 MSG msg; | 1866 return (HWND) SendMessage (FRAME_W32_WINDOW (f), |
1807 | 1867 WM_EMACS_CREATESCROLLBAR, (WPARAM) f, |
1808 PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATESCROLLBAR, (WPARAM) f, | 1868 (LPARAM) bar); |
1809 (LPARAM) bar); | |
1810 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); | |
1811 | |
1812 return ((HWND) msg.wParam); | |
1813 } | 1869 } |
1814 | 1870 |
1815 //#define ATTACH_THREADS | 1871 //#define ATTACH_THREADS |
1816 | 1872 |
1817 void | 1873 BOOL |
1818 my_show_window (HWND hwnd, int how) | 1874 my_show_window (FRAME_PTR f, HWND hwnd, int how) |
1819 { | 1875 { |
1820 #ifndef ATTACH_THREADS | 1876 #ifndef ATTACH_THREADS |
1821 SendMessage (hwnd, WM_EMACS_SHOWWINDOW, (WPARAM) how, 0); | 1877 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW, |
1878 (WPARAM) hwnd, (LPARAM) how); | |
1822 #else | 1879 #else |
1823 ShowWindow (hwnd , how); | 1880 return ShowWindow (hwnd, how); |
1824 #endif | 1881 #endif |
1825 } | 1882 } |
1826 | 1883 |
1827 void | 1884 void |
1828 my_set_window_pos (HWND hwnd, HWND hwndAfter, | 1885 my_set_window_pos (HWND hwnd, HWND hwndAfter, |
1829 int x, int y, int cx, int cy, int flags) | 1886 int x, int y, int cx, int cy, UINT flags) |
1830 { | 1887 { |
1831 #ifndef ATTACH_THREADS | 1888 #ifndef ATTACH_THREADS |
1832 W32WindowPos pos; | 1889 WINDOWPOS pos; |
1833 pos.hwndAfter = hwndAfter; | 1890 pos.hwndInsertAfter = hwndAfter; |
1834 pos.x = x; | 1891 pos.x = x; |
1835 pos.y = y; | 1892 pos.y = y; |
1836 pos.cx = cx; | 1893 pos.cx = cx; |
1837 pos.cy = cy; | 1894 pos.cy = cy; |
1838 pos.flags = flags; | 1895 pos.flags = flags; |
1840 #else | 1897 #else |
1841 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags); | 1898 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags); |
1842 #endif | 1899 #endif |
1843 } | 1900 } |
1844 | 1901 |
1902 BOOL | |
1903 my_set_focus (f, hwnd) | |
1904 struct frame * f; | |
1905 HWND hwnd; | |
1906 { | |
1907 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS, | |
1908 (WPARAM) hwnd, 0); | |
1909 } | |
1910 | |
1845 void | 1911 void |
1846 my_destroy_window (f, hwnd) | 1912 my_destroy_window (f, hwnd) |
1847 struct frame * f; | 1913 struct frame * f; |
1848 HWND hwnd; | 1914 HWND hwnd; |
1849 { | 1915 { |
1876 | 1942 |
1877 /* Requires geometry to be set before call to create the real window */ | 1943 /* Requires geometry to be set before call to create the real window */ |
1878 | 1944 |
1879 hwnd = my_create_scrollbar (f, bar); | 1945 hwnd = my_create_scrollbar (f, bar); |
1880 | 1946 |
1881 SetScrollRange (hwnd, SB_CTL, 0, height, FALSE); | 1947 if (pfnSetScrollInfo) |
1882 SetScrollPos (hwnd, SB_CTL, 0, TRUE); | 1948 { |
1949 SCROLLINFO si; | |
1950 | |
1951 si.cbSize = sizeof (si); | |
1952 si.fMask = SIF_ALL; | |
1953 si.nMin = 0; | |
1954 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height) | |
1955 + VERTICAL_SCROLL_BAR_MIN_HANDLE; | |
1956 si.nPage = si.nMax; | |
1957 si.nPos = 0; | |
1958 | |
1959 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE); | |
1960 } | |
1961 else | |
1962 { | |
1963 SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE); | |
1964 SetScrollPos (hwnd, SB_CTL, 0, FALSE); | |
1965 } | |
1883 | 1966 |
1884 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd); | 1967 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd); |
1885 | 1968 |
1886 /* Add bar to its frame's list of scroll bars. */ | 1969 /* Add bar to its frame's list of scroll bars. */ |
1887 bar->next = FRAME_SCROLL_BARS (f); | 1970 bar->next = FRAME_SCROLL_BARS (f); |
1922 && end == XINT (bar->end)) | 2005 && end == XINT (bar->end)) |
1923 return; | 2006 return; |
1924 | 2007 |
1925 BLOCK_INPUT; | 2008 BLOCK_INPUT; |
1926 | 2009 |
2010 { | |
2011 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); | |
2012 | |
2013 /* Make sure the values are reasonable, and try to preserve | |
2014 the distance between start and end. */ | |
2015 { | |
2016 int length = end - start; | |
2017 | |
2018 if (start < 0) | |
2019 start = 0; | |
2020 else if (start > top_range) | |
2021 start = top_range; | |
2022 end = start + length; | |
2023 | |
2024 if (end < start) | |
2025 end = start; | |
2026 else if (end > top_range && ! dragging) | |
2027 end = top_range; | |
2028 } | |
2029 } | |
2030 | |
1927 /* Store the adjusted setting in the scroll bar. */ | 2031 /* Store the adjusted setting in the scroll bar. */ |
1928 XSETINT (bar->start, start); | 2032 XSETINT (bar->start, start); |
1929 XSETINT (bar->end, end); | 2033 XSETINT (bar->end, end); |
1930 | 2034 |
1931 SetScrollPos (w, SB_CTL, start, TRUE); | 2035 /* If being dragged, let scroll bar update itself. */ |
2036 if (!dragging) | |
2037 { | |
2038 if (pfnSetScrollInfo) | |
2039 { | |
2040 SCROLLINFO si; | |
2041 | |
2042 si.cbSize = sizeof (si); | |
2043 si.fMask = SIF_PAGE | SIF_POS; | |
2044 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE; | |
2045 si.nPos = start; | |
2046 | |
2047 pfnSetScrollInfo (w, SB_CTL, &si, TRUE); | |
2048 } | |
2049 else | |
2050 SetScrollPos (w, SB_CTL, start, TRUE); | |
2051 } | |
1932 | 2052 |
1933 UNBLOCK_INPUT; | 2053 UNBLOCK_INPUT; |
1934 } | 2054 } |
1935 | 2055 |
1936 /* Move a scroll bar around on the screen, to accommodate changing | 2056 /* Move a scroll bar around on the screen, to accommodate changing |
1941 int top, left, width, height; | 2061 int top, left, width, height; |
1942 { | 2062 { |
1943 Window w = SCROLL_BAR_W32_WINDOW (bar); | 2063 Window w = SCROLL_BAR_W32_WINDOW (bar); |
1944 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 2064 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
1945 | 2065 |
2066 /* If already correctly positioned, do nothing. */ | |
2067 if ( XINT (bar->left) == left | |
2068 && XINT (bar->top) == top | |
2069 && XINT (bar->width) == width | |
2070 && XINT (bar->height) == height ) | |
2071 { | |
2072 /* Redraw after clear_frame. */ | |
2073 if (!my_show_window (f, w, SW_NORMAL)) | |
2074 InvalidateRect (w, NULL, FALSE); | |
2075 return; | |
2076 } | |
2077 | |
1946 BLOCK_INPUT; | 2078 BLOCK_INPUT; |
1947 | 2079 |
2080 /* Make sure scroll bar is "visible" before moving, to ensure the | |
2081 area of the parent window now exposed will be refreshed. */ | |
2082 my_show_window (f, w, SW_HIDE); | |
1948 MoveWindow (w, left, top, width, height, TRUE); | 2083 MoveWindow (w, left, top, width, height, TRUE); |
1949 SetScrollRange (w, SB_CTL, 0, height, FALSE); | 2084 if (pfnSetScrollInfo) |
1950 InvalidateRect (w, NULL, FALSE); | 2085 { |
1951 my_show_window (w, SW_NORMAL); | 2086 SCROLLINFO si; |
2087 | |
2088 si.cbSize = sizeof (si); | |
2089 si.fMask = SIF_RANGE; | |
2090 si.nMin = 0; | |
2091 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height) | |
2092 + VERTICAL_SCROLL_BAR_MIN_HANDLE; | |
2093 | |
2094 pfnSetScrollInfo (w, SB_CTL, &si, FALSE); | |
2095 } | |
2096 else | |
2097 SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE); | |
2098 my_show_window (f, w, SW_NORMAL); | |
2099 // InvalidateRect (w, NULL, FALSE); | |
1952 | 2100 |
1953 XSETINT (bar->left, left); | 2101 XSETINT (bar->left, left); |
1954 XSETINT (bar->top, top); | 2102 XSETINT (bar->top, top); |
1955 XSETINT (bar->width, width); | 2103 XSETINT (bar->width, width); |
1956 XSETINT (bar->height, height); | 2104 XSETINT (bar->height, height); |
2012 /* It may just need to be moved and resized. */ | 2160 /* It may just need to be moved and resized. */ |
2013 bar = XSCROLL_BAR (window->vertical_scroll_bar); | 2161 bar = XSCROLL_BAR (window->vertical_scroll_bar); |
2014 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | 2162 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); |
2015 } | 2163 } |
2016 | 2164 |
2017 /* Set the scroll bar's current state, unless we're currently being | 2165 /* Set the scroll bar's current state. */ |
2018 dragged. */ | 2166 { |
2019 if (NILP (bar->dragging)) | 2167 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height); |
2020 { | 2168 |
2021 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height); | 2169 if (whole == 0) |
2022 | 2170 x_scroll_bar_set_handle (bar, 0, top_range, 0); |
2023 if (whole == 0) | 2171 else |
2024 x_scroll_bar_set_handle (bar, 0, top_range, 0); | 2172 { |
2025 else | 2173 int start = (int) (((double) position * top_range) / whole); |
2026 { | 2174 int end = (int) (((double) (position + portion) * top_range) / whole); |
2027 int start = (int) (((double) position * top_range) / whole); | 2175 |
2028 int end = (int) (((double) (position + portion) * top_range) / whole); | 2176 x_scroll_bar_set_handle (bar, start, end, 0); |
2029 | 2177 } |
2030 x_scroll_bar_set_handle (bar, start, end, 0); | 2178 } |
2031 } | |
2032 } | |
2033 | 2179 |
2034 XSETVECTOR (window->vertical_scroll_bar, bar); | 2180 XSETVECTOR (window->vertical_scroll_bar, bar); |
2035 } | 2181 } |
2036 | 2182 |
2037 | 2183 |
2157 emacs_event->modifiers = msg->dwModifiers; | 2303 emacs_event->modifiers = msg->dwModifiers; |
2158 emacs_event->frame_or_window = bar->window; | 2304 emacs_event->frame_or_window = bar->window; |
2159 emacs_event->timestamp = msg->msg.time; | 2305 emacs_event->timestamp = msg->msg.time; |
2160 | 2306 |
2161 { | 2307 { |
2162 int internal_height | 2308 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); |
2163 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height)); | 2309 int y; |
2164 int top_range | 2310 int dragging = !NILP (bar->dragging); |
2165 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); | 2311 |
2166 int y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL); | 2312 if (pfnGetScrollInfo) |
2313 { | |
2314 SCROLLINFO si; | |
2315 | |
2316 si.cbSize = sizeof (si); | |
2317 si.fMask = SIF_POS; | |
2318 | |
2319 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si); | |
2320 y = si.nPos; | |
2321 } | |
2322 else | |
2323 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL); | |
2324 | |
2325 bar->dragging = Qnil; | |
2167 | 2326 |
2168 switch (LOWORD (msg->msg.wParam)) | 2327 switch (LOWORD (msg->msg.wParam)) |
2169 { | 2328 { |
2170 case SB_THUMBTRACK: | |
2171 emacs_event->part = scroll_bar_handle; | |
2172 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff) | |
2173 y = HIWORD (msg->msg.wParam); | |
2174 break; | |
2175 case SB_LINEDOWN: | 2329 case SB_LINEDOWN: |
2176 emacs_event->part = scroll_bar_down_arrow; | 2330 emacs_event->part = scroll_bar_down_arrow; |
2177 break; | 2331 break; |
2178 case SB_LINEUP: | 2332 case SB_LINEUP: |
2179 emacs_event->part = scroll_bar_up_arrow; | 2333 emacs_event->part = scroll_bar_up_arrow; |
2190 break; | 2344 break; |
2191 case SB_BOTTOM: | 2345 case SB_BOTTOM: |
2192 emacs_event->part = scroll_bar_handle; | 2346 emacs_event->part = scroll_bar_handle; |
2193 y = top_range; | 2347 y = top_range; |
2194 break; | 2348 break; |
2349 case SB_THUMBTRACK: | |
2195 case SB_THUMBPOSITION: | 2350 case SB_THUMBPOSITION: |
2351 if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff) | |
2352 y = HIWORD (msg->msg.wParam); | |
2353 bar->dragging = Qt; | |
2196 emacs_event->part = scroll_bar_handle; | 2354 emacs_event->part = scroll_bar_handle; |
2355 | |
2356 /* "Silently" update current position. */ | |
2357 if (pfnSetScrollInfo) | |
2358 { | |
2359 SCROLLINFO si; | |
2360 | |
2361 si.cbSize = sizeof (si); | |
2362 si.fMask = SIF_POS; | |
2363 | |
2364 #if 0 | |
2365 /* Shrink handle if necessary to allow full range for position. */ | |
2366 { | |
2367 int start = XINT (bar->start); | |
2368 int end = XINT (bar->end); | |
2369 int len = end - start; | |
2370 | |
2371 /* If new end is nearly hitting bottom, we must shrink | |
2372 handle. How much we shrink it depends on the relative | |
2373 sizes of len and top_range. */ | |
2374 if (y + len > top_range - 2) | |
2375 { | |
2376 len -= min (top_range / 10, (len / 3) + 2); | |
2377 if (len < 0) | |
2378 len = 0; | |
2379 } | |
2380 si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE; | |
2381 si.fMask |= SIF_PAGE; | |
2382 } | |
2383 #endif | |
2384 si.nPos = y; | |
2385 /* Remember apparent position (we actually lag behind the real | |
2386 position, so don't set that directly. */ | |
2387 last_scroll_bar_drag_pos = y; | |
2388 | |
2389 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE); | |
2390 } | |
2391 else | |
2392 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE); | |
2197 break; | 2393 break; |
2198 case SB_ENDSCROLL: | 2394 case SB_ENDSCROLL: |
2395 /* If this is the end of a drag sequence, then reset the scroll | |
2396 handle size to normal and do a final redraw. Otherwise do | |
2397 nothing. */ | |
2398 if (dragging) | |
2399 { | |
2400 if (pfnSetScrollInfo) | |
2401 { | |
2402 SCROLLINFO si; | |
2403 int start = XINT (bar->start); | |
2404 int end = XINT (bar->end); | |
2405 | |
2406 si.cbSize = sizeof (si); | |
2407 si.fMask = SIF_PAGE | SIF_POS; | |
2408 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE; | |
2409 si.nPos = last_scroll_bar_drag_pos; | |
2410 | |
2411 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE); | |
2412 } | |
2413 else | |
2414 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE); | |
2415 } | |
2416 /* fall through */ | |
2199 default: | 2417 default: |
2200 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE); | 2418 emacs_event->kind = no_event; |
2201 return FALSE; | 2419 return FALSE; |
2202 } | 2420 } |
2203 | 2421 |
2204 XSETINT (emacs_event->x, y); | 2422 XSETINT (emacs_event->x, y); |
2205 XSETINT (emacs_event->y, top_range); | 2423 XSETINT (emacs_event->y, top_range); |
2220 { | 2438 { |
2221 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar); | 2439 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar); |
2222 Window w = SCROLL_BAR_W32_WINDOW (bar); | 2440 Window w = SCROLL_BAR_W32_WINDOW (bar); |
2223 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | 2441 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); |
2224 int pos; | 2442 int pos; |
2443 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)); | |
2225 | 2444 |
2226 BLOCK_INPUT; | 2445 BLOCK_INPUT; |
2227 | 2446 |
2228 *fp = f; | 2447 *fp = f; |
2229 *bar_window = bar->window; | 2448 *bar_window = bar->window; |
2230 | 2449 |
2231 pos = GetScrollPos (w, SB_CTL); | 2450 if (pfnGetScrollInfo) |
2451 { | |
2452 SCROLLINFO si; | |
2453 | |
2454 si.cbSize = sizeof (si); | |
2455 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE; | |
2456 | |
2457 pfnGetScrollInfo (w, SB_CTL, &si); | |
2458 pos = si.nPos; | |
2459 top_range = si.nMax - si.nPage + 1; | |
2460 } | |
2461 else | |
2462 pos = GetScrollPos (w, SB_CTL); | |
2232 | 2463 |
2233 switch (LOWORD (last_mouse_scroll_bar_pos)) | 2464 switch (LOWORD (last_mouse_scroll_bar_pos)) |
2234 { | 2465 { |
2235 case SB_THUMBPOSITION: | 2466 case SB_THUMBPOSITION: |
2236 case SB_THUMBTRACK: | 2467 case SB_THUMBTRACK: |
2246 *part = scroll_bar_handle; | 2477 *part = scroll_bar_handle; |
2247 break; | 2478 break; |
2248 } | 2479 } |
2249 | 2480 |
2250 XSETINT(*x, pos); | 2481 XSETINT(*x, pos); |
2251 XSETINT(*y, VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height))); | 2482 XSETINT(*y, top_range); |
2252 | 2483 |
2253 f->mouse_moved = 0; | 2484 f->mouse_moved = 0; |
2254 last_mouse_scroll_bar = Qnil; | 2485 last_mouse_scroll_bar = Qnil; |
2255 | 2486 |
2256 *time = last_mouse_movement_time; | 2487 *time = last_mouse_movement_time; |
2273 { | 2504 { |
2274 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)); | 2505 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)); |
2275 HDC hdc = GetDC (window); | 2506 HDC hdc = GetDC (window); |
2276 RECT rect; | 2507 RECT rect; |
2277 | 2508 |
2278 my_show_window (window, SW_HIDE); | 2509 /* Hide scroll bar until ready to repaint. x_scroll_bar_move |
2510 arranges to refresh the scroll bar if hidden. */ | |
2511 my_show_window (f, window, SW_HIDE); | |
2512 | |
2279 GetClientRect (window, &rect); | 2513 GetClientRect (window, &rect); |
2280 select_palette (f, hdc); | 2514 select_palette (f, hdc); |
2281 w32_clear_rect (f, hdc, &rect); | 2515 w32_clear_rect (f, hdc, &rect); |
2282 deselect_palette (f, hdc); | 2516 deselect_palette (f, hdc); |
2517 | |
2518 ReleaseDC (window, hdc); | |
2283 } | 2519 } |
2284 } | 2520 } |
2285 | 2521 |
2286 show_scroll_bars (f, how) | 2522 show_scroll_bars (f, how) |
2287 FRAME_PTR f; | 2523 FRAME_PTR f; |
2291 | 2527 |
2292 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); | 2528 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar); |
2293 bar = XSCROLL_BAR (bar)->next) | 2529 bar = XSCROLL_BAR (bar)->next) |
2294 { | 2530 { |
2295 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)); | 2531 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)); |
2296 my_show_window (window, how); | 2532 my_show_window (f, window, how); |
2297 } | 2533 } |
2298 } | 2534 } |
2299 | 2535 |
2300 | 2536 |
2301 /* The main W32 event-reading loop - w32_read_socket. */ | 2537 /* The main W32 event-reading loop - w32_read_socket. */ |
2308 /* Record the last 100 characters stored | 2544 /* Record the last 100 characters stored |
2309 to help debug the loss-of-chars-during-GC problem. */ | 2545 to help debug the loss-of-chars-during-GC problem. */ |
2310 int temp_index; | 2546 int temp_index; |
2311 short temp_buffer[100]; | 2547 short temp_buffer[100]; |
2312 | 2548 |
2313 extern int key_event (KEY_EVENT_RECORD *, struct input_event *); | 2549 extern int key_event (KEY_EVENT_RECORD *, struct input_event *, int *isdead); |
2314 | 2550 |
2315 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that | 2551 /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that |
2316 we can use the same routines to handle input in both console | 2552 we can use the same routines to handle input in both console |
2317 and window modes. */ | 2553 and window modes. */ |
2318 | 2554 |
2367 register struct input_event *bufp; | 2603 register struct input_event *bufp; |
2368 register int numchars; | 2604 register int numchars; |
2369 int expected; | 2605 int expected; |
2370 { | 2606 { |
2371 int count = 0; | 2607 int count = 0; |
2372 int nbytes = 0; | 2608 int check_visibility = 0; |
2373 int items_pending; /* How many items are in the X queue. */ | |
2374 W32Msg msg; | 2609 W32Msg msg; |
2375 struct frame *f; | 2610 struct frame *f; |
2376 int event_found = 0; | |
2377 int prefix; | |
2378 Lisp_Object part; | 2611 Lisp_Object part; |
2379 struct w32_display_info *dpyinfo = &one_w32_display_info; | 2612 struct w32_display_info *dpyinfo = &one_w32_display_info; |
2380 | 2613 |
2381 if (interrupt_input_blocked) | 2614 if (interrupt_input_blocked) |
2382 { | 2615 { |
2396 while (get_next_msg (&msg, FALSE)) | 2629 while (get_next_msg (&msg, FALSE)) |
2397 { | 2630 { |
2398 switch (msg.msg.message) | 2631 switch (msg.msg.message) |
2399 { | 2632 { |
2400 case WM_PAINT: | 2633 case WM_PAINT: |
2401 { | |
2402 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2634 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2403 | 2635 |
2404 if (f) | 2636 if (f) |
2405 { | 2637 { |
2406 if (f->async_visible == 0) | 2638 if (f->async_visible != 1) |
2407 { | 2639 { |
2640 /* Definitely not obscured, so mark as visible. */ | |
2408 f->async_visible = 1; | 2641 f->async_visible = 1; |
2409 f->async_iconified = 0; | 2642 f->async_iconified = 0; |
2410 SET_FRAME_GARBAGED (f); | 2643 SET_FRAME_GARBAGED (f); |
2644 DebPrint (("frame %04x (%s) reexposed\n", f, | |
2645 XSTRING (f->name)->data)); | |
2646 | |
2647 /* WM_PAINT serves as MapNotify as well, so report | |
2648 visibility changes properly. */ | |
2649 if (f->iconified) | |
2650 { | |
2651 bufp->kind = deiconify_event; | |
2652 XSETFRAME (bufp->frame_or_window, f); | |
2653 bufp++; | |
2654 count++; | |
2655 numchars--; | |
2656 } | |
2657 else if (! NILP(Vframe_list) | |
2658 && ! NILP (XCONS (Vframe_list)->cdr)) | |
2659 /* Force a redisplay sooner or later to update the | |
2660 frame titles in case this is the second frame. */ | |
2661 record_asynch_buffer_change (); | |
2411 } | 2662 } |
2412 else | 2663 else |
2413 { | 2664 { |
2414 /* Erase background again for safety. */ | 2665 /* Erase background again for safety. */ |
2415 w32_clear_rect (f, NULL, &msg.rect); | 2666 w32_clear_rect (f, NULL, &msg.rect); |
2416 dumprectangle (f, | 2667 dumprectangle (f, |
2417 msg.rect.left, | 2668 msg.rect.left, |
2418 msg.rect.top, | 2669 msg.rect.top, |
2419 msg.rect.right-msg.rect.left+1, | 2670 msg.rect.right - msg.rect.left, |
2420 msg.rect.bottom-msg.rect.top+1); | 2671 msg.rect.bottom - msg.rect.top); |
2421 } | 2672 } |
2422 } | 2673 } |
2423 } | |
2424 break; | 2674 break; |
2675 | |
2425 case WM_KEYDOWN: | 2676 case WM_KEYDOWN: |
2426 case WM_SYSKEYDOWN: | 2677 case WM_SYSKEYDOWN: |
2427 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2678 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2428 | 2679 |
2429 if (f && !f->iconified) | 2680 if (f && !f->iconified) |
2431 if (temp_index == sizeof temp_buffer / sizeof (short)) | 2682 if (temp_index == sizeof temp_buffer / sizeof (short)) |
2432 temp_index = 0; | 2683 temp_index = 0; |
2433 temp_buffer[temp_index++] = msg.msg.wParam; | 2684 temp_buffer[temp_index++] = msg.msg.wParam; |
2434 bufp->kind = non_ascii_keystroke; | 2685 bufp->kind = non_ascii_keystroke; |
2435 bufp->code = msg.msg.wParam; | 2686 bufp->code = msg.msg.wParam; |
2436 bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers); | 2687 bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers, |
2688 msg.msg.wParam); | |
2437 XSETFRAME (bufp->frame_or_window, f); | 2689 XSETFRAME (bufp->frame_or_window, f); |
2438 bufp->timestamp = msg.msg.time; | 2690 bufp->timestamp = msg.msg.time; |
2439 bufp++; | 2691 bufp++; |
2440 numchars--; | 2692 numchars--; |
2441 count++; | 2693 count++; |
2442 } | 2694 } |
2443 break; | 2695 break; |
2696 | |
2444 case WM_SYSCHAR: | 2697 case WM_SYSCHAR: |
2445 case WM_CHAR: | 2698 case WM_CHAR: |
2446 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2699 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2447 | 2700 |
2448 if (f && !f->iconified) | 2701 if (f && !f->iconified) |
2449 { | 2702 { |
2450 if (numchars > 1) | 2703 if (numchars > 1) |
2451 { | 2704 { |
2452 int add; | 2705 int add; |
2706 int isdead = 0; | |
2453 KEY_EVENT_RECORD key, *keyp = &key; | 2707 KEY_EVENT_RECORD key, *keyp = &key; |
2454 | 2708 |
2455 if (temp_index == sizeof temp_buffer / sizeof (short)) | 2709 if (temp_index == sizeof temp_buffer / sizeof (short)) |
2456 temp_index = 0; | 2710 temp_index = 0; |
2457 | 2711 |
2458 convert_to_key_event (&msg, keyp); | 2712 convert_to_key_event (&msg, keyp); |
2459 add = key_event (keyp, bufp); | 2713 add = key_event (keyp, bufp, &isdead); |
2460 XSETFRAME (bufp->frame_or_window, f); | 2714 XSETFRAME (bufp->frame_or_window, f); |
2461 if (add == -1) | 2715 if (add == -1) |
2462 { | 2716 { |
2463 /* The key pressed generated two characters, most likely | 2717 /* The key pressed generated two characters, most likely |
2464 an accent character and a key that could not be | 2718 an accent character and a key that could not be |
2468 the first character now. */ | 2722 the first character now. */ |
2469 prepend_msg (&msg); | 2723 prepend_msg (&msg); |
2470 add = 1; | 2724 add = 1; |
2471 } | 2725 } |
2472 | 2726 |
2473 /* Throw dead keys away. However, be sure not to | 2727 if (isdead) |
2474 throw away the dead key if it was produced using | |
2475 AltGr and there is a valid AltGr scan code for | |
2476 this key. */ | |
2477 if (is_dead_key (msg.msg.wParam) | |
2478 && !((VkKeyScan ((char) bufp->code) & 0xff00) == 0x600)) | |
2479 break; | 2728 break; |
2480 | 2729 |
2481 bufp += add; | 2730 bufp += add; |
2482 numchars -= add; | 2731 numchars -= add; |
2483 count += add; | 2732 count += add; |
2486 { | 2735 { |
2487 abort (); | 2736 abort (); |
2488 } | 2737 } |
2489 } | 2738 } |
2490 break; | 2739 break; |
2740 | |
2491 case WM_MOUSEMOVE: | 2741 case WM_MOUSEMOVE: |
2492 if (dpyinfo->grabbed && last_mouse_frame | 2742 if (dpyinfo->grabbed && last_mouse_frame |
2493 && FRAME_LIVE_P (last_mouse_frame)) | 2743 && FRAME_LIVE_P (last_mouse_frame)) |
2494 f = last_mouse_frame; | 2744 f = last_mouse_frame; |
2495 else | 2745 else |
2499 note_mouse_movement (f, &msg.msg); | 2749 note_mouse_movement (f, &msg.msg); |
2500 else | 2750 else |
2501 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f)); | 2751 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f)); |
2502 | 2752 |
2503 break; | 2753 break; |
2754 | |
2504 case WM_LBUTTONDOWN: | 2755 case WM_LBUTTONDOWN: |
2505 case WM_LBUTTONUP: | 2756 case WM_LBUTTONUP: |
2506 case WM_MBUTTONDOWN: | 2757 case WM_MBUTTONDOWN: |
2507 case WM_MBUTTONUP: | 2758 case WM_MBUTTONUP: |
2508 case WM_RBUTTONDOWN: | 2759 case WM_RBUTTONDOWN: |
2538 else | 2789 else |
2539 { | 2790 { |
2540 dpyinfo->grabbed |= (1 << button); | 2791 dpyinfo->grabbed |= (1 << button); |
2541 last_mouse_frame = f; | 2792 last_mouse_frame = f; |
2542 } | 2793 } |
2794 break; | |
2543 } | 2795 } |
2544 | 2796 |
2797 case WM_MOUSEWHEEL: | |
2798 if (dpyinfo->grabbed && last_mouse_frame | |
2799 && FRAME_LIVE_P (last_mouse_frame)) | |
2800 f = last_mouse_frame; | |
2801 else | |
2802 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2803 | |
2804 if (f) | |
2805 { | |
2806 if ((!dpyinfo->w32_focus_frame | |
2807 || f == dpyinfo->w32_focus_frame) | |
2808 && (numchars >= 1)) | |
2809 { | |
2810 construct_mouse_wheel (bufp, &msg, f); | |
2811 bufp++; | |
2812 count++; | |
2813 numchars--; | |
2814 } | |
2815 } | |
2545 break; | 2816 break; |
2817 | |
2546 case WM_VSCROLL: | 2818 case WM_VSCROLL: |
2547 { | 2819 { |
2548 struct scroll_bar *bar = x_window_to_scroll_bar ((HWND)msg.msg.lParam); | 2820 struct scroll_bar *bar = |
2821 x_window_to_scroll_bar ((HWND)msg.msg.lParam); | |
2549 | 2822 |
2550 if (bar && numchars >= 1) | 2823 if (bar && numchars >= 1) |
2551 { | 2824 { |
2552 if (x_scroll_bar_handle_click (bar, &msg, bufp)) | 2825 if (x_scroll_bar_handle_click (bar, &msg, bufp)) |
2553 { | 2826 { |
2554 bufp++; | 2827 bufp++; |
2555 count++; | 2828 count++; |
2556 numchars--; | 2829 numchars--; |
2557 } | 2830 } |
2558 } | 2831 } |
2832 break; | |
2559 } | 2833 } |
2560 | 2834 |
2835 case WM_WINDOWPOSCHANGED: | |
2836 case WM_ACTIVATE: | |
2837 case WM_ACTIVATEAPP: | |
2838 check_visibility = 1; | |
2561 break; | 2839 break; |
2840 | |
2562 case WM_MOVE: | 2841 case WM_MOVE: |
2563 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2842 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2564 | 2843 |
2565 if (f && !f->async_iconified) | 2844 if (f && !f->async_iconified) |
2566 { | 2845 { |
2567 f->output_data.w32->left_pos = LOWORD (msg.msg.lParam); | 2846 int x, y; |
2568 f->output_data.w32->top_pos = HIWORD (msg.msg.lParam); | 2847 |
2848 x_real_positions (f, &x, &y); | |
2849 f->output_data.w32->left_pos = x; | |
2850 f->output_data.w32->top_pos = y; | |
2569 } | 2851 } |
2570 | 2852 |
2853 check_visibility = 1; | |
2571 break; | 2854 break; |
2855 | |
2856 case WM_SHOWWINDOW: | |
2857 /* If window has been obscured or exposed by another window | |
2858 being maximised or minimised/restored, then recheck | |
2859 visibility of all frames. Direct changes to our own | |
2860 windows get handled by WM_SIZE. */ | |
2861 #if 0 | |
2862 if (msg.msg.lParam != 0) | |
2863 check_visibility = 1; | |
2864 else | |
2865 { | |
2866 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2867 f->async_visible = msg.msg.wParam; | |
2868 } | |
2869 #endif | |
2870 | |
2871 check_visibility = 1; | |
2872 break; | |
2873 | |
2572 case WM_SIZE: | 2874 case WM_SIZE: |
2573 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2875 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2574 | 2876 |
2575 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED) | 2877 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED) |
2576 { | 2878 { |
2580 int width; | 2882 int width; |
2581 int height; | 2883 int height; |
2582 | 2884 |
2583 GetClientRect(msg.msg.hwnd, &rect); | 2885 GetClientRect(msg.msg.hwnd, &rect); |
2584 | 2886 |
2585 height = rect.bottom - rect.top + 1; | 2887 height = rect.bottom - rect.top; |
2586 width = rect.right - rect.left + 1; | 2888 width = rect.right - rect.left; |
2587 | 2889 |
2588 rows = PIXEL_TO_CHAR_HEIGHT (f, height); | 2890 rows = PIXEL_TO_CHAR_HEIGHT (f, height); |
2589 columns = PIXEL_TO_CHAR_WIDTH (f, width); | 2891 columns = PIXEL_TO_CHAR_WIDTH (f, width); |
2892 | |
2893 /* TODO: Clip size to the screen dimensions. */ | |
2590 | 2894 |
2591 /* Even if the number of character rows and columns has | 2895 /* Even if the number of character rows and columns has |
2592 not changed, the font size may have changed, so we need | 2896 not changed, the font size may have changed, so we need |
2593 to check the pixel dimensions as well. */ | 2897 to check the pixel dimensions as well. */ |
2594 | 2898 |
2605 f->output_data.w32->pixel_width = width; | 2909 f->output_data.w32->pixel_width = width; |
2606 f->output_data.w32->pixel_height = height; | 2910 f->output_data.w32->pixel_height = height; |
2607 f->output_data.w32->win_gravity = NorthWestGravity; | 2911 f->output_data.w32->win_gravity = NorthWestGravity; |
2608 } | 2912 } |
2609 } | 2913 } |
2610 | 2914 |
2611 break; | 2915 /* Inform lisp of whether frame has been iconified etc. */ |
2612 case WM_SETFOCUS: | 2916 if (f) |
2613 case WM_KILLFOCUS: | |
2614 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2615 | |
2616 if (msg.msg.message == WM_SETFOCUS) | |
2617 { | 2917 { |
2618 x_new_focus_frame (dpyinfo, f); | 2918 switch (msg.msg.wParam) |
2619 } | |
2620 else if (f == dpyinfo->w32_focus_frame) | |
2621 x_new_focus_frame (dpyinfo, 0); | |
2622 | |
2623 break; | |
2624 case WM_SYSCOMMAND: | |
2625 switch (msg.msg.wParam & 0xfff0) /* Lower 4 bits used by Windows. */ | |
2626 { | |
2627 case SC_CLOSE: | |
2628 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2629 | |
2630 if (f) | |
2631 { | 2919 { |
2632 if (numchars == 0) | 2920 case SIZE_MINIMIZED: |
2633 abort (); | 2921 f->async_visible = 0; |
2634 | |
2635 bufp->kind = delete_window_event; | |
2636 XSETFRAME (bufp->frame_or_window, f); | |
2637 bufp++; | |
2638 count++; | |
2639 numchars--; | |
2640 } | |
2641 | |
2642 break; | |
2643 case SC_MINIMIZE: | |
2644 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2645 | |
2646 if (f) | |
2647 { | |
2648 f->async_visible = 1; | |
2649 f->async_iconified = 1; | 2922 f->async_iconified = 1; |
2650 | 2923 |
2651 bufp->kind = iconify_event; | 2924 bufp->kind = iconify_event; |
2652 XSETFRAME (bufp->frame_or_window, f); | 2925 XSETFRAME (bufp->frame_or_window, f); |
2653 bufp++; | 2926 bufp++; |
2654 count++; | 2927 count++; |
2655 numchars--; | 2928 numchars--; |
2656 } | 2929 break; |
2657 | 2930 |
2658 break; | 2931 case SIZE_MAXIMIZED: |
2659 case SC_MAXIMIZE: | 2932 case SIZE_RESTORED: |
2660 case SC_RESTORE: | |
2661 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2662 | |
2663 if (f) | |
2664 { | |
2665 f->async_visible = 1; | 2933 f->async_visible = 1; |
2666 f->async_iconified = 0; | 2934 f->async_iconified = 0; |
2667 | 2935 |
2668 /* wait_reading_process_input will notice this and update | 2936 /* wait_reading_process_input will notice this and update |
2669 the frame's display structures. */ | 2937 the frame's display structures. */ |
2680 else | 2948 else |
2681 /* Force a redisplay sooner or later | 2949 /* Force a redisplay sooner or later |
2682 to update the frame titles | 2950 to update the frame titles |
2683 in case this is the second frame. */ | 2951 in case this is the second frame. */ |
2684 record_asynch_buffer_change (); | 2952 record_asynch_buffer_change (); |
2953 break; | |
2685 } | 2954 } |
2686 | |
2687 break; | |
2688 } | 2955 } |
2956 | |
2957 check_visibility = 1; | |
2958 break; | |
2959 | |
2960 case WM_SETFOCUS: | |
2961 case WM_KILLFOCUS: | |
2962 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2689 | 2963 |
2964 if (msg.msg.message == WM_SETFOCUS) | |
2965 { | |
2966 x_new_focus_frame (dpyinfo, f); | |
2967 } | |
2968 else if (f == dpyinfo->w32_focus_frame) | |
2969 { | |
2970 x_new_focus_frame (dpyinfo, 0); | |
2971 } | |
2972 | |
2973 check_visibility = 1; | |
2690 break; | 2974 break; |
2975 | |
2691 case WM_CLOSE: | 2976 case WM_CLOSE: |
2692 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 2977 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2693 | 2978 |
2694 if (f) | 2979 if (f) |
2695 { | 2980 { |
2700 XSETFRAME (bufp->frame_or_window, f); | 2985 XSETFRAME (bufp->frame_or_window, f); |
2701 bufp++; | 2986 bufp++; |
2702 count++; | 2987 count++; |
2703 numchars--; | 2988 numchars--; |
2704 } | 2989 } |
2990 break; | |
2991 | |
2992 case WM_INITMENU: | |
2993 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
2705 | 2994 |
2995 if (f) | |
2996 { | |
2997 if (numchars == 0) | |
2998 abort (); | |
2999 | |
3000 bufp->kind = menu_bar_activate_event; | |
3001 XSETFRAME (bufp->frame_or_window, f); | |
3002 bufp++; | |
3003 count++; | |
3004 numchars--; | |
3005 } | |
2706 break; | 3006 break; |
3007 | |
2707 case WM_COMMAND: | 3008 case WM_COMMAND: |
2708 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | 3009 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); |
2709 | 3010 |
3011 #if 1 | |
2710 if (f) | 3012 if (f) |
2711 { | 3013 { |
2712 if (msg.msg.lParam == 0) | 3014 if (msg.msg.lParam == 0) |
2713 { | 3015 { |
2714 /* Came from window menu */ | 3016 /* Came from window menu */ |
2741 else | 3043 else |
2742 { | 3044 { |
2743 /* Came from popup menu */ | 3045 /* Came from popup menu */ |
2744 } | 3046 } |
2745 } | 3047 } |
3048 #endif | |
3049 | |
3050 check_visibility = 1; | |
3051 break; | |
3052 | |
3053 case WM_DISPLAYCHANGE: | |
3054 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | |
3055 | |
3056 if (f) | |
3057 { | |
3058 dpyinfo->width = (short) LOWORD (msg.msg.lParam); | |
3059 dpyinfo->height = (short) HIWORD (msg.msg.lParam); | |
3060 dpyinfo->n_cbits = msg.msg.wParam; | |
3061 DebPrint (("display change: %d %d\n", dpyinfo->width, | |
3062 dpyinfo->height)); | |
3063 } | |
3064 | |
3065 check_visibility = 1; | |
2746 break; | 3066 break; |
2747 } | 3067 } |
2748 } | 3068 } |
2749 | 3069 |
2750 /* If the focus was just given to an autoraising frame, | 3070 /* If the focus was just given to an autoraising frame, |
2752 /* ??? This ought to be able to handle more than one such frame. */ | 3072 /* ??? This ought to be able to handle more than one such frame. */ |
2753 if (pending_autoraise_frame) | 3073 if (pending_autoraise_frame) |
2754 { | 3074 { |
2755 x_raise_frame (pending_autoraise_frame); | 3075 x_raise_frame (pending_autoraise_frame); |
2756 pending_autoraise_frame = 0; | 3076 pending_autoraise_frame = 0; |
3077 } | |
3078 | |
3079 /* Check which frames are still visisble, if we have enqueued any user | |
3080 events or been notified of events that may affect visibility. We | |
3081 do this here because there doesn't seem to be any direct | |
3082 notification from Windows that the visibility of a window has | |
3083 changed (at least, not in all cases). */ | |
3084 if (count > 0 || check_visibility) | |
3085 { | |
3086 Lisp_Object tail, frame; | |
3087 | |
3088 FOR_EACH_FRAME (tail, frame) | |
3089 { | |
3090 FRAME_PTR f = XFRAME (frame); | |
3091 /* Check "visible" frames and mark each as obscured or not. | |
3092 Note that async_visible is nonzero for unobscured and | |
3093 obscured frames, but zero for hidden and iconified frames. */ | |
3094 if (FRAME_W32_P (f) && f->async_visible) | |
3095 { | |
3096 RECT clipbox; | |
3097 HDC hdc = get_frame_dc (f); | |
3098 GetClipBox (hdc, &clipbox); | |
3099 release_frame_dc (f, hdc); | |
3100 | |
3101 if (clipbox.right == clipbox.left | |
3102 || clipbox.bottom == clipbox.top) | |
3103 { | |
3104 /* Frame has become completely obscured so mark as | |
3105 such (we do this by setting async_visible to 2 so | |
3106 that FRAME_VISIBLE_P is still true, but redisplay | |
3107 will skip it). */ | |
3108 f->async_visible = 2; | |
3109 | |
3110 if (!FRAME_OBSCURED_P (f)) | |
3111 { | |
3112 DebPrint (("frame %04x (%s) obscured\n", f, | |
3113 XSTRING (f->name)->data)); | |
3114 } | |
3115 } | |
3116 else | |
3117 { | |
3118 /* Frame is not obscured, so mark it as such. */ | |
3119 f->async_visible = 1; | |
3120 | |
3121 if (FRAME_OBSCURED_P (f)) | |
3122 { | |
3123 SET_FRAME_GARBAGED (f); | |
3124 DebPrint (("frame %04x (%s) reexposed\n", f, | |
3125 XSTRING (f->name)->data)); | |
3126 | |
3127 /* Force a redisplay sooner or later. */ | |
3128 record_asynch_buffer_change (); | |
3129 } | |
3130 } | |
3131 } | |
3132 } | |
2757 } | 3133 } |
2758 | 3134 |
2759 UNBLOCK_INPUT; | 3135 UNBLOCK_INPUT; |
2760 return count; | 3136 return count; |
2761 } | 3137 } |
2836 return; | 3212 return; |
2837 | 3213 |
2838 if (! on && f->phys_cursor_x < 0) | 3214 if (! on && f->phys_cursor_x < 0) |
2839 return; | 3215 return; |
2840 | 3216 |
2841 /* If we're not updating, then we want to use the current frame's | |
2842 cursor position, not our local idea of where the cursor ought to be. */ | |
2843 if (f != updating_frame) | |
2844 { | |
2845 curs_x = FRAME_CURSOR_X (f); | |
2846 curs_y = FRAME_CURSOR_Y (f); | |
2847 } | |
2848 | |
2849 /* If there is anything wrong with the current cursor state, remove it. */ | 3217 /* If there is anything wrong with the current cursor state, remove it. */ |
2850 if (f->phys_cursor_x >= 0 | 3218 if (f->phys_cursor_x >= 0 |
2851 && (!on | 3219 && (!on |
2852 || f->phys_cursor_x != curs_x | 3220 || f->phys_cursor_x != curs_x |
2853 || f->phys_cursor_y != curs_y | 3221 || f->phys_cursor_y != curs_y |
2903 | 3271 |
2904 /* If cursor is off and we want it off, return quickly. */ | 3272 /* If cursor is off and we want it off, return quickly. */ |
2905 if (!on && f->phys_cursor_x < 0) | 3273 if (!on && f->phys_cursor_x < 0) |
2906 return; | 3274 return; |
2907 | 3275 |
2908 /* If we're not updating, then we want to use the current frame's | |
2909 cursor position, not our local idea of where the cursor ought to be. */ | |
2910 if (f != updating_frame) | |
2911 { | |
2912 curs_x = FRAME_CURSOR_X (f); | |
2913 curs_y = FRAME_CURSOR_Y (f); | |
2914 } | |
2915 | |
2916 /* If cursor is currently being shown and we don't want it to be | 3276 /* If cursor is currently being shown and we don't want it to be |
2917 or it is in the wrong place, | 3277 or it is in the wrong place, |
2918 or we want a hollow box and it's not so, (pout!) | 3278 or we want a hollow box and it's not so, (pout!) |
2919 erase it. */ | 3279 erase it. */ |
2920 if (f->phys_cursor_x >= 0 | 3280 if (f->phys_cursor_x >= 0 |
2928 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f); | 3288 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f); |
2929 | 3289 |
2930 /* If the cursor is in the mouse face area, redisplay that when | 3290 /* If the cursor is in the mouse face area, redisplay that when |
2931 we clear the cursor. */ | 3291 we clear the cursor. */ |
2932 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame | 3292 if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame |
2933 && | 3293 && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row |
2934 (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row | 3294 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row |
2935 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row | 3295 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)) |
2936 && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)) | 3296 && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row |
2937 && | 3297 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row |
2938 (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row | 3298 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col)) |
2939 || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row | |
2940 && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col)) | |
2941 /* Don't redraw the cursor's spot in mouse face | 3299 /* Don't redraw the cursor's spot in mouse face |
2942 if it is at the end of a line (on a newline). | 3300 if it is at the end of a line (on a newline). |
2943 The cursor appears there, but mouse highlighting does not. */ | 3301 The cursor appears there, but mouse highlighting does not. */ |
2944 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x) | 3302 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x) |
2945 mouse_face_here = 1; | 3303 mouse_face_here = 1; |
2989 f->phys_cursor_x = curs_x; | 3347 f->phys_cursor_x = curs_x; |
2990 f->phys_cursor_y = curs_y; | 3348 f->phys_cursor_y = curs_y; |
2991 } | 3349 } |
2992 } | 3350 } |
2993 | 3351 |
3352 /* Display the cursor on frame F, or clear it, according to ON. | |
3353 Use the position specified by curs_x and curs_y | |
3354 if we are doing an update of frame F now. | |
3355 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields | |
3356 of F. */ | |
3357 | |
2994 x_display_cursor (f, on) | 3358 x_display_cursor (f, on) |
2995 struct frame *f; | 3359 struct frame *f; |
2996 int on; | 3360 int on; |
2997 { | 3361 { |
2998 BLOCK_INPUT; | 3362 BLOCK_INPUT; |
3363 | |
3364 /* If we're not updating, then we want to use the current frame's | |
3365 cursor position, not our local idea of where the cursor ought to be. */ | |
3366 if (f != updating_frame) | |
3367 { | |
3368 curs_x = FRAME_CURSOR_X (f); | |
3369 curs_y = FRAME_CURSOR_Y (f); | |
3370 } | |
2999 | 3371 |
3000 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor) | 3372 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor) |
3001 x_display_box_cursor (f, on); | 3373 x_display_box_cursor (f, on); |
3002 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor) | 3374 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor) |
3003 x_display_bar_cursor (f, on); | 3375 x_display_bar_cursor (f, on); |
3120 | 3492 |
3121 return lispy_name; | 3493 return lispy_name; |
3122 } | 3494 } |
3123 } | 3495 } |
3124 | 3496 |
3497 /* Calculate the absolute position in frame F | |
3498 from its current recorded position values and gravity. */ | |
3499 | |
3125 x_calc_absolute_position (f) | 3500 x_calc_absolute_position (f) |
3126 struct frame *f; | 3501 struct frame *f; |
3127 { | 3502 { |
3128 Window win, child; | 3503 Window win, child; |
3129 POINT pt; | 3504 POINT pt; |
3205 | 3580 |
3206 /* It is a mystery why we need to add the border_width here | 3581 /* It is a mystery why we need to add the border_width here |
3207 when the frame is already visible, but experiment says we do. */ | 3582 when the frame is already visible, but experiment says we do. */ |
3208 modified_left = f->output_data.w32->left_pos; | 3583 modified_left = f->output_data.w32->left_pos; |
3209 modified_top = f->output_data.w32->top_pos; | 3584 modified_top = f->output_data.w32->top_pos; |
3585 #ifndef HAVE_NTGUI | |
3586 /* Do not add in border widths under W32. */ | |
3210 if (change_gravity != 0) | 3587 if (change_gravity != 0) |
3211 { | 3588 { |
3212 modified_left += f->output_data.w32->border_width; | 3589 modified_left += f->output_data.w32->border_width; |
3213 modified_top += f->output_data.w32->border_width; | 3590 modified_top += f->output_data.w32->border_width; |
3214 } | 3591 } |
3592 #endif | |
3215 | 3593 |
3216 my_set_window_pos (FRAME_W32_WINDOW (f), | 3594 my_set_window_pos (FRAME_W32_WINDOW (f), |
3217 NULL, | 3595 NULL, |
3218 modified_left, modified_top, | 3596 modified_left, modified_top, |
3219 0,0, | 3597 0,0, |
3220 SWP_NOZORDER | SWP_NOSIZE); | 3598 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); |
3221 UNBLOCK_INPUT; | 3599 UNBLOCK_INPUT; |
3222 } | 3600 } |
3223 | 3601 |
3224 /* Call this to change the size of frame F's x-window. | 3602 /* Call this to change the size of frame F's x-window. |
3225 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity | 3603 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity |
3230 struct frame *f; | 3608 struct frame *f; |
3231 int change_gravity; | 3609 int change_gravity; |
3232 int cols, rows; | 3610 int cols, rows; |
3233 { | 3611 { |
3234 int pixelwidth, pixelheight; | 3612 int pixelwidth, pixelheight; |
3613 Lisp_Object window; | |
3614 struct w32_display_info *dpyinfo = &one_w32_display_info; | |
3235 | 3615 |
3236 BLOCK_INPUT; | 3616 BLOCK_INPUT; |
3237 | 3617 |
3238 check_frame_size (f, &rows, &cols); | 3618 check_frame_size (f, &rows, &cols); |
3239 f->output_data.w32->vertical_scroll_bar_extra | 3619 f->output_data.w32->vertical_scroll_bar_extra |
3256 rect.bottom = pixelheight; | 3636 rect.bottom = pixelheight; |
3257 | 3637 |
3258 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, | 3638 AdjustWindowRect(&rect, f->output_data.w32->dwStyle, |
3259 FRAME_EXTERNAL_MENU_BAR (f)); | 3639 FRAME_EXTERNAL_MENU_BAR (f)); |
3260 | 3640 |
3261 /* All windows have an extra pixel */ | |
3262 | |
3263 my_set_window_pos (FRAME_W32_WINDOW (f), | 3641 my_set_window_pos (FRAME_W32_WINDOW (f), |
3264 NULL, | 3642 NULL, |
3265 0, 0, | 3643 0, 0, |
3266 rect.right - rect.left + 1, | 3644 rect.right - rect.left, |
3267 rect.bottom - rect.top + 1, | 3645 rect.bottom - rect.top, |
3268 SWP_NOZORDER | SWP_NOMOVE); | 3646 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); |
3269 } | 3647 } |
3270 | 3648 |
3271 /* Now, strictly speaking, we can't be sure that this is accurate, | 3649 /* Now, strictly speaking, we can't be sure that this is accurate, |
3272 but the window manager will get around to dealing with the size | 3650 but the window manager will get around to dealing with the size |
3273 change request eventually, and we'll hear how it went when the | 3651 change request eventually, and we'll hear how it went when the |
3280 point in the future when the ConfigureNotify event arrives. */ | 3658 point in the future when the ConfigureNotify event arrives. */ |
3281 change_frame_size (f, rows, cols, 0, 0); | 3659 change_frame_size (f, rows, cols, 0, 0); |
3282 PIXEL_WIDTH (f) = pixelwidth; | 3660 PIXEL_WIDTH (f) = pixelwidth; |
3283 PIXEL_HEIGHT (f) = pixelheight; | 3661 PIXEL_HEIGHT (f) = pixelheight; |
3284 | 3662 |
3285 /* If cursor was outside the new size, mark it as off. */ | |
3286 if (f->phys_cursor_y >= rows | |
3287 || f->phys_cursor_x >= cols) | |
3288 { | |
3289 f->phys_cursor_x = -1; | |
3290 f->phys_cursor_y = -1; | |
3291 } | |
3292 | |
3293 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to | 3663 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to |
3294 receive in the ConfigureNotify event; if we get what we asked | 3664 receive in the ConfigureNotify event; if we get what we asked |
3295 for, then the event won't cause the screen to become garbaged, so | 3665 for, then the event won't cause the screen to become garbaged, so |
3296 we have to make sure to do it here. */ | 3666 we have to make sure to do it here. */ |
3297 SET_FRAME_GARBAGED (f); | 3667 SET_FRAME_GARBAGED (f); |
3668 | |
3669 /* If cursor was outside the new size, mark it as off. */ | |
3670 if (f->phys_cursor_y >= rows | |
3671 || f->phys_cursor_x >= cols) | |
3672 { | |
3673 f->phys_cursor_x = -1; | |
3674 f->phys_cursor_y = -1; | |
3675 } | |
3676 | |
3677 /* Clear out any recollection of where the mouse highlighting was, | |
3678 since it might be in a place that's outside the new frame size. | |
3679 Actually checking whether it is outside is a pain in the neck, | |
3680 so don't try--just let the highlighting be done afresh with new size. */ | |
3681 window = dpyinfo->mouse_face_window; | |
3682 if (! NILP (window) && XFRAME (window) == f) | |
3683 { | |
3684 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; | |
3685 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; | |
3686 dpyinfo->mouse_face_window = Qnil; | |
3687 } | |
3298 | 3688 |
3299 UNBLOCK_INPUT; | 3689 UNBLOCK_INPUT; |
3300 } | 3690 } |
3301 | 3691 |
3302 /* Mouse warping. */ | 3692 /* Mouse warping. */ |
3304 void | 3694 void |
3305 x_set_mouse_pixel_position (f, pix_x, pix_y) | 3695 x_set_mouse_pixel_position (f, pix_x, pix_y) |
3306 struct frame *f; | 3696 struct frame *f; |
3307 int pix_x, pix_y; | 3697 int pix_x, pix_y; |
3308 { | 3698 { |
3699 RECT rect; | |
3700 POINT pt; | |
3701 | |
3309 BLOCK_INPUT; | 3702 BLOCK_INPUT; |
3310 | 3703 |
3311 pix_x += f->output_data.w32->left_pos; | 3704 GetClientRect (FRAME_W32_WINDOW (f), &rect); |
3312 pix_y += f->output_data.w32->top_pos; | 3705 pt.x = rect.left + pix_x; |
3313 | 3706 pt.y = rect.top + pix_y; |
3314 SetCursorPos (pix_x, pix_y); | 3707 ClientToScreen (FRAME_W32_WINDOW (f), &pt); |
3708 | |
3709 SetCursorPos (pt.x, pt.y); | |
3315 | 3710 |
3316 UNBLOCK_INPUT; | 3711 UNBLOCK_INPUT; |
3317 } | 3712 } |
3318 | 3713 |
3319 void | 3714 void |
3338 /* focus shifting, raising and lowering. */ | 3733 /* focus shifting, raising and lowering. */ |
3339 | 3734 |
3340 x_focus_on_frame (f) | 3735 x_focus_on_frame (f) |
3341 struct frame *f; | 3736 struct frame *f; |
3342 { | 3737 { |
3738 struct w32_display_info *dpyinfo = &one_w32_display_info; | |
3739 | |
3740 /* Give input focus to frame. */ | |
3741 BLOCK_INPUT; | |
3742 #if 0 | |
3743 /* Try not to change its Z-order if possible. */ | |
3744 if (x_window_to_frame (dpyinfo, GetForegroundWindow ())) | |
3745 my_set_focus (f, FRAME_W32_WINDOW (f)); | |
3746 else | |
3747 #endif | |
3748 SetForegroundWindow (FRAME_W32_WINDOW (f)); | |
3749 UNBLOCK_INPUT; | |
3343 } | 3750 } |
3344 | 3751 |
3345 x_unfocus_frame (f) | 3752 x_unfocus_frame (f) |
3346 struct frame *f; | 3753 struct frame *f; |
3347 { | 3754 { |
3350 /* Raise frame F. */ | 3757 /* Raise frame F. */ |
3351 | 3758 |
3352 x_raise_frame (f) | 3759 x_raise_frame (f) |
3353 struct frame *f; | 3760 struct frame *f; |
3354 { | 3761 { |
3355 // if (f->async_visible) | 3762 BLOCK_INPUT; |
3356 { | 3763 |
3357 BLOCK_INPUT; | 3764 /* Strictly speaking, raise-frame should only change the frame's Z |
3358 my_set_window_pos (FRAME_W32_WINDOW (f), | 3765 order, leaving input focus unchanged. This is reasonable behaviour |
3359 HWND_TOP, | 3766 on X where the usual policy is point-to-focus. However, this |
3360 0, 0, 0, 0, | 3767 behaviour would be very odd on Windows where the usual policy is |
3361 SWP_NOSIZE | SWP_NOMOVE); | 3768 click-to-focus. |
3362 UNBLOCK_INPUT; | 3769 |
3363 } | 3770 On X, if the mouse happens to be over the raised frame, it gets |
3771 input focus anyway (so the window with focus will never be | |
3772 completely obscured) - if not, then just moving the mouse over it | |
3773 is sufficient to give it focus. On Windows, the user must actually | |
3774 click on the frame (preferrably the title bar so as not to move | |
3775 point), which is more awkward. Also, no other Windows program | |
3776 raises a window to the top but leaves another window (possibly now | |
3777 completely obscured) with input focus. | |
3778 | |
3779 Because there is a system setting on Windows that allows the user | |
3780 to choose the point to focus policy, we make the strict semantics | |
3781 optional, but by default we grab focus when raising. */ | |
3782 | |
3783 if (NILP (Vw32_grab_focus_on_raise)) | |
3784 { | |
3785 /* The obvious call to my_set_window_pos doesn't work if Emacs is | |
3786 not already the foreground application: the frame is raised | |
3787 above all other frames belonging to us, but not above the | |
3788 current top window. To achieve that, we have to resort to this | |
3789 more cumbersome method. */ | |
3790 | |
3791 HDWP handle = BeginDeferWindowPos (2); | |
3792 if (handle) | |
3793 { | |
3794 DeferWindowPos (handle, | |
3795 FRAME_W32_WINDOW (f), | |
3796 HWND_TOP, | |
3797 0, 0, 0, 0, | |
3798 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); | |
3799 | |
3800 DeferWindowPos (handle, | |
3801 GetForegroundWindow (), | |
3802 FRAME_W32_WINDOW (f), | |
3803 0, 0, 0, 0, | |
3804 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); | |
3805 | |
3806 EndDeferWindowPos (handle); | |
3807 } | |
3808 } | |
3809 else | |
3810 { | |
3811 SetForegroundWindow (FRAME_W32_WINDOW (f)); | |
3812 } | |
3813 | |
3814 UNBLOCK_INPUT; | |
3364 } | 3815 } |
3365 | 3816 |
3366 /* Lower frame F. */ | 3817 /* Lower frame F. */ |
3367 | 3818 |
3368 x_lower_frame (f) | 3819 x_lower_frame (f) |
3369 struct frame *f; | 3820 struct frame *f; |
3370 { | 3821 { |
3371 // if (f->async_visible) | 3822 BLOCK_INPUT; |
3372 { | 3823 my_set_window_pos (FRAME_W32_WINDOW (f), |
3373 BLOCK_INPUT; | 3824 HWND_BOTTOM, |
3374 my_set_window_pos (FRAME_W32_WINDOW (f), | 3825 0, 0, 0, 0, |
3375 HWND_BOTTOM, | 3826 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); |
3376 0, 0, 0, 0, | 3827 UNBLOCK_INPUT; |
3377 SWP_NOSIZE | SWP_NOMOVE); | |
3378 UNBLOCK_INPUT; | |
3379 } | |
3380 } | 3828 } |
3381 | 3829 |
3382 static void | 3830 static void |
3383 w32_frame_raise_lower (f, raise) | 3831 w32_frame_raise_lower (f, raise) |
3384 FRAME_PTR f; | 3832 FRAME_PTR f; |
3410 call x_set_offset a second time | 3858 call x_set_offset a second time |
3411 if we get to x_make_frame_visible a second time | 3859 if we get to x_make_frame_visible a second time |
3412 before the window gets really visible. */ | 3860 before the window gets really visible. */ |
3413 if (! FRAME_ICONIFIED_P (f) | 3861 if (! FRAME_ICONIFIED_P (f) |
3414 && ! f->output_data.w32->asked_for_visible) | 3862 && ! f->output_data.w32->asked_for_visible) |
3415 { | |
3416 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0); | 3863 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0); |
3417 // SetForegroundWindow (FRAME_W32_WINDOW (f)); | |
3418 } | |
3419 | 3864 |
3420 f->output_data.w32->asked_for_visible = 1; | 3865 f->output_data.w32->asked_for_visible = 1; |
3421 | 3866 |
3422 my_show_window (FRAME_W32_WINDOW (f), SW_SHOWNORMAL); | 3867 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW); |
3868 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL); | |
3423 } | 3869 } |
3424 | 3870 |
3425 /* Synchronize to ensure Emacs knows the frame is visible | 3871 /* Synchronize to ensure Emacs knows the frame is visible |
3426 before we do anything else. We do this loop with input not blocked | 3872 before we do anything else. We do this loop with input not blocked |
3427 so that incoming events are handled. */ | 3873 so that incoming events are handled. */ |
3480 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f) | 3926 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f) |
3481 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0; | 3927 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0; |
3482 | 3928 |
3483 BLOCK_INPUT; | 3929 BLOCK_INPUT; |
3484 | 3930 |
3485 my_show_window (FRAME_W32_WINDOW (f), SW_HIDE); | 3931 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE); |
3486 | 3932 |
3487 /* We can't distinguish this from iconification | 3933 /* We can't distinguish this from iconification |
3488 just by the event that we get from the server. | 3934 just by the event that we get from the server. |
3489 So we can't win using the usual strategy of letting | 3935 So we can't win using the usual strategy of letting |
3490 FRAME_SAMPLE_VISIBILITY set this. So do it by hand, | 3936 FRAME_SAMPLE_VISIBILITY set this. So do it by hand, |
3512 if (f->async_iconified) | 3958 if (f->async_iconified) |
3513 return; | 3959 return; |
3514 | 3960 |
3515 BLOCK_INPUT; | 3961 BLOCK_INPUT; |
3516 | 3962 |
3517 my_show_window (FRAME_W32_WINDOW (f), SW_SHOWMINIMIZED); | 3963 /* Simulate the user minimizing the frame. */ |
3518 /* The frame doesn't seem to be lowered automatically. */ | 3964 PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0); |
3519 x_lower_frame (f); | |
3520 | 3965 |
3521 f->async_iconified = 1; | 3966 f->async_iconified = 1; |
3522 | 3967 |
3523 UNBLOCK_INPUT; | 3968 UNBLOCK_INPUT; |
3524 } | 3969 } |
3576 | 4021 |
3577 flexlines = f->height; | 4022 flexlines = f->height; |
3578 | 4023 |
3579 enter_crit (); | 4024 enter_crit (); |
3580 | 4025 |
3581 SetWindowLong (window, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.w32->font)); | 4026 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font)); |
3582 SetWindowLong (window, WND_Y_UNITS_INDEX, f->output_data.w32->line_height); | 4027 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height); |
4028 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width); | |
4029 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra); | |
3583 | 4030 |
3584 leave_crit (); | 4031 leave_crit (); |
3585 } | 4032 } |
3586 | 4033 |
3587 /* Window manager things */ | 4034 /* Window manager things */ |
3792 xfree (dpyinfo->w32_id_name); | 4239 xfree (dpyinfo->w32_id_name); |
3793 } | 4240 } |
3794 | 4241 |
3795 /* Set up use of W32. */ | 4242 /* Set up use of W32. */ |
3796 | 4243 |
3797 DWORD windows_msg_worker (); | 4244 DWORD w32_msg_worker (); |
3798 | 4245 |
3799 w32_initialize () | 4246 w32_initialize () |
3800 { | 4247 { |
3801 clear_frame_hook = w32_clear_frame; | 4248 clear_frame_hook = w32_clear_frame; |
3802 clear_end_of_line_hook = w32_clear_end_of_line; | 4249 clear_end_of_line_hook = w32_clear_end_of_line; |
3829 fast_clear_end_of_line = 1; /* X does this well */ | 4276 fast_clear_end_of_line = 1; /* X does this well */ |
3830 memory_below_frame = 0; /* we don't remember what scrolls | 4277 memory_below_frame = 0; /* we don't remember what scrolls |
3831 off the bottom */ | 4278 off the bottom */ |
3832 baud_rate = 19200; | 4279 baud_rate = 19200; |
3833 | 4280 |
3834 /* Try to use interrupt input; if we can't, then start polling. */ | 4281 /* Initialize input mode: interrupt_input off, no flow control, allow |
3835 Fset_input_mode (Qt, Qnil, Qt, Qnil); | 4282 8 bit character input, standard quit char. */ |
4283 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil); | |
3836 | 4284 |
3837 /* Create the window thread - it will terminate itself or when the app terminates */ | 4285 /* Create the window thread - it will terminate itself or when the app terminates */ |
3838 | 4286 |
3839 init_crit (); | 4287 init_crit (); |
3840 | 4288 |
3848 MSG msg; | 4296 MSG msg; |
3849 | 4297 |
3850 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE); | 4298 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE); |
3851 | 4299 |
3852 hWindowsThread = CreateThread (NULL, 0, | 4300 hWindowsThread = CreateThread (NULL, 0, |
3853 (LPTHREAD_START_ROUTINE) windows_msg_worker, | 4301 (LPTHREAD_START_ROUTINE) w32_msg_worker, |
3854 0, 0, &dwWindowsThreadId); | 4302 0, 0, &dwWindowsThreadId); |
3855 | 4303 |
3856 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); | 4304 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE); |
3857 } | 4305 } |
3858 | 4306 |
3865 calls for us (ones that affect, or depend on, the active/focus | 4313 calls for us (ones that affect, or depend on, the active/focus |
3866 window state. */ | 4314 window state. */ |
3867 #ifdef ATTACH_THREADS | 4315 #ifdef ATTACH_THREADS |
3868 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE); | 4316 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE); |
3869 #endif | 4317 #endif |
4318 | |
4319 /* Dynamically link to optional system components. */ | |
4320 { | |
4321 HANDLE user_lib = LoadLibrary ("user32.dll"); | |
4322 | |
4323 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn) | |
4324 | |
4325 /* New proportional scroll bar functions. */ | |
4326 LOAD_PROC( SetScrollInfo ); | |
4327 LOAD_PROC( GetScrollInfo ); | |
4328 | |
4329 #undef LOAD_PROC | |
4330 | |
4331 FreeLibrary (user_lib); | |
4332 | |
4333 /* If using proportional scroll bars, ensure handle is at least 5 pixels; | |
4334 otherwise use the fixed height. */ | |
4335 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 : | |
4336 GetSystemMetrics (SM_CYVTHUMB); | |
4337 | |
4338 /* For either kind of scroll bar, take account of the arrows; these | |
4339 effectively form the border of the main scroll bar range. */ | |
4340 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border | |
4341 = GetSystemMetrics (SM_CYVSCROLL); | |
4342 } | |
3870 } | 4343 } |
3871 | 4344 |
3872 void | 4345 void |
3873 syms_of_w32term () | 4346 syms_of_w32term () |
3874 { | 4347 { |
3889 DEFVAR_LISP ("w32-swap-mouse-buttons", | 4362 DEFVAR_LISP ("w32-swap-mouse-buttons", |
3890 &Vw32_swap_mouse_buttons, | 4363 &Vw32_swap_mouse_buttons, |
3891 "Swap the mapping of middle and right mouse buttons.\n\ | 4364 "Swap the mapping of middle and right mouse buttons.\n\ |
3892 When nil, middle button is mouse-2 and right button is mouse-3."); | 4365 When nil, middle button is mouse-2 and right button is mouse-3."); |
3893 Vw32_swap_mouse_buttons = Qnil; | 4366 Vw32_swap_mouse_buttons = Qnil; |
3894 } | 4367 |
4368 DEFVAR_LISP ("w32-grab-focus-on-raise", | |
4369 &Vw32_grab_focus_on_raise, | |
4370 "Raised frame grabs input focus.\n\ | |
4371 When t, `raise-frame' grabs input focus as well. This fits well\n\ | |
4372 with the normal Windows click-to-focus policy, but might not be\n\ | |
4373 desirable when using a point-to-focus policy."); | |
4374 Vw32_grab_focus_on_raise = Qt; | |
4375 | |
4376 DEFVAR_LISP ("w32-capslock-is-shiftlock", | |
4377 &Vw32_capslock_is_shiftlock, | |
4378 "Apply CapsLock state to non character input keys.\n\ | |
4379 When nil, CapsLock only affects normal character input keys."); | |
4380 Vw32_capslock_is_shiftlock = Qnil; | |
4381 } |