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 }