diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/w32term.c | 877 |
1 files changed, 682 insertions, 195 deletions
diff --git a/src/w32term.c b/src/w32term.c index 75e53a1216f..a433abc6bb4 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 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" |
| @@ -95,6 +95,38 @@ 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. */ |
| @@ -105,6 +137,12 @@ Lisp_Object Vw32_num_mouse_buttons; | |||
| 105 | 137 | ||
| 106 | Lisp_Object Vw32_swap_mouse_buttons; | 138 | Lisp_Object Vw32_swap_mouse_buttons; |
| 107 | 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; | ||
| 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 |
| @@ -324,6 +362,7 @@ 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 | { |
| @@ -332,6 +371,7 @@ w32_frame_up_to_date (f) | |||
| 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. |
| @@ -875,14 +915,12 @@ do_line_dance () | |||
| 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), |
| @@ -890,6 +928,8 @@ do_line_dance () | |||
| 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. */ |
| @@ -1265,6 +1305,25 @@ construct_mouse_click (result, msg, 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. |
| @@ -1606,8 +1665,8 @@ show_mouse_face (dpyinfo, hl) | |||
| 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; |
| @@ -1690,6 +1749,7 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time) | |||
| 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 | { |
| @@ -1803,34 +1863,31 @@ 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; |
| @@ -1842,6 +1899,15 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter, | |||
| 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; |
| @@ -1878,8 +1944,25 @@ x_scroll_bar_create (window, top, left, width, height) | |||
| 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 | ||
| @@ -1924,11 +2007,48 @@ x_scroll_bar_set_handle (bar, start, end, rebuild) | |||
| 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 | } |
| @@ -1943,12 +2063,40 @@ x_scroll_bar_move (bar, top, left, width, height) | |||
| 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); |
| @@ -2014,22 +2162,20 @@ w32_set_vertical_scroll_bar (window, portion, whole, position) | |||
| 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 | { | ||
| 2021 | int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height); | ||
| 2022 | 2168 | ||
| 2023 | if (whole == 0) | 2169 | if (whole == 0) |
| 2024 | x_scroll_bar_set_handle (bar, 0, top_range, 0); | 2170 | x_scroll_bar_set_handle (bar, 0, top_range, 0); |
| 2025 | else | 2171 | else |
| 2026 | { | 2172 | { |
| 2027 | int start = (int) (((double) position * top_range) / whole); | 2173 | int start = (int) (((double) position * top_range) / whole); |
| 2028 | int end = (int) (((double) (position + portion) * top_range) / whole); | 2174 | int end = (int) (((double) (position + portion) * top_range) / whole); |
| 2029 | 2175 | ||
| 2030 | x_scroll_bar_set_handle (bar, start, end, 0); | 2176 | x_scroll_bar_set_handle (bar, start, end, 0); |
| 2031 | } | 2177 | } |
| 2032 | } | 2178 | } |
| 2033 | 2179 | ||
| 2034 | XSETVECTOR (window->vertical_scroll_bar, bar); | 2180 | XSETVECTOR (window->vertical_scroll_bar, bar); |
| 2035 | } | 2181 | } |
| @@ -2159,19 +2305,27 @@ x_scroll_bar_handle_click (bar, msg, emacs_event) | |||
| 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; |
| @@ -2192,12 +2346,76 @@ x_scroll_bar_handle_click (bar, msg, emacs_event) | |||
| 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 | ||
| @@ -2222,13 +2440,26 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) | |||
| 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 | { |
| @@ -2248,7 +2479,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) | |||
| 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; |
| @@ -2275,11 +2506,16 @@ x_scroll_bar_clear (f) | |||
| 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 | ||
| @@ -2293,7 +2529,7 @@ show_scroll_bars (f, how) | |||
| 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 | ||
| @@ -2310,7 +2546,7 @@ static Time enter_timestamp; | |||
| 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 |
| @@ -2369,12 +2605,9 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | ||
| @@ -2398,16 +2631,34 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | { |
| @@ -2416,12 +2667,12 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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); |
| @@ -2433,7 +2684,8 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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++; |
| @@ -2441,6 +2693,7 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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); |
| @@ -2450,13 +2703,14 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | { |
| @@ -2470,12 +2724,7 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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; |
| @@ -2488,6 +2737,7 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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)) |
| @@ -2501,6 +2751,7 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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: |
| @@ -2540,12 +2791,34 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | { |
| @@ -2556,19 +2829,48 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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; | ||
| 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; | ||
| 2571 | break; | 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 | ||
| @@ -2582,12 +2884,14 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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); |
| 2590 | 2892 | ||
| 2893 | /* TODO: Clip size to the screen dimensions. */ | ||
| 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. */ |
| @@ -2607,45 +2911,14 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | { | ||
| 2618 | x_new_focus_frame (dpyinfo, f); | ||
| 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 | { | 2917 | { |
| 2627 | case SC_CLOSE: | 2918 | switch (msg.msg.wParam) |
| 2628 | f = x_window_to_frame (dpyinfo, msg.msg.hwnd); | ||
| 2629 | |||
| 2630 | if (f) | ||
| 2631 | { | ||
| 2632 | if (numchars == 0) | ||
| 2633 | abort (); | ||
| 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 | { | 2919 | { |
| 2648 | f->async_visible = 1; | 2920 | case SIZE_MINIMIZED: |
| 2921 | f->async_visible = 0; | ||
| 2649 | f->async_iconified = 1; | 2922 | f->async_iconified = 1; |
| 2650 | 2923 | ||
| 2651 | bufp->kind = iconify_event; | 2924 | bufp->kind = iconify_event; |
| @@ -2653,15 +2926,10 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | ||
| @@ -2682,12 +2950,29 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | ||
| @@ -2702,11 +2987,28 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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); | ||
| 2994 | |||
| 2995 | if (f) | ||
| 2996 | { | ||
| 2997 | if (numchars == 0) | ||
| 2998 | abort (); | ||
| 2705 | 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) |
| @@ -2743,6 +3045,24 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 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 | } |
| @@ -2756,6 +3076,62 @@ w32_read_socket (sd, bufp, numchars, expected) | |||
| 2756 | pending_autoraise_frame = 0; | 3076 | pending_autoraise_frame = 0; |
| 2757 | } | 3077 | } |
| 2758 | 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 | } | ||
| 3133 | } | ||
| 3134 | |||
| 2759 | UNBLOCK_INPUT; | 3135 | UNBLOCK_INPUT; |
| 2760 | return count; | 3136 | return count; |
| 2761 | } | 3137 | } |
| @@ -2838,14 +3214,6 @@ x_display_bar_cursor (f, on) | |||
| 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 |
| @@ -2905,14 +3273,6 @@ x_display_box_cursor (f, on) | |||
| 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!) |
| @@ -2930,14 +3290,12 @@ x_display_box_cursor (f, on) | |||
| 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. */ |
| @@ -2991,12 +3349,26 @@ x_display_box_cursor (f, on) | |||
| 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; |
| 2999 | 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 | } | ||
| 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) |
| @@ -3122,6 +3494,9 @@ x_new_font (f, fontname) | |||
| 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 | { |
| @@ -3207,17 +3582,20 @@ x_set_offset (f, xoff, yoff, change_gravity) | |||
| 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 | ||
| @@ -3232,6 +3610,8 @@ x_set_window_size (f, change_gravity, cols, rows) | |||
| 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 | ||
| @@ -3258,14 +3638,12 @@ x_set_window_size (f, change_gravity, cols, rows) | |||
| 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, |
| @@ -3282,6 +3660,12 @@ x_set_window_size (f, change_gravity, cols, rows) | |||
| 3282 | PIXEL_WIDTH (f) = pixelwidth; | 3660 | PIXEL_WIDTH (f) = pixelwidth; |
| 3283 | PIXEL_HEIGHT (f) = pixelheight; | 3661 | PIXEL_HEIGHT (f) = pixelheight; |
| 3284 | 3662 | ||
| 3663 | /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to | ||
| 3664 | receive in the ConfigureNotify event; if we get what we asked | ||
| 3665 | for, then the event won't cause the screen to become garbaged, so | ||
| 3666 | we have to make sure to do it here. */ | ||
| 3667 | SET_FRAME_GARBAGED (f); | ||
| 3668 | |||
| 3285 | /* If cursor was outside the new size, mark it as off. */ | 3669 | /* If cursor was outside the new size, mark it as off. */ |
| 3286 | if (f->phys_cursor_y >= rows | 3670 | if (f->phys_cursor_y >= rows |
| 3287 | || f->phys_cursor_x >= cols) | 3671 | || f->phys_cursor_x >= cols) |
| @@ -3290,11 +3674,17 @@ x_set_window_size (f, change_gravity, cols, rows) | |||
| 3290 | f->phys_cursor_y = -1; | 3674 | f->phys_cursor_y = -1; |
| 3291 | } | 3675 | } |
| 3292 | 3676 | ||
| 3293 | /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to | 3677 | /* Clear out any recollection of where the mouse highlighting was, |
| 3294 | receive in the ConfigureNotify event; if we get what we asked | 3678 | since it might be in a place that's outside the new frame size. |
| 3295 | for, then the event won't cause the screen to become garbaged, so | 3679 | Actually checking whether it is outside is a pain in the neck, |
| 3296 | we have to make sure to do it here. */ | 3680 | so don't try--just let the highlighting be done afresh with new size. */ |
| 3297 | SET_FRAME_GARBAGED (f); | 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 | } |
| @@ -3306,12 +3696,17 @@ 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; |
| 3706 | pt.y = rect.top + pix_y; | ||
| 3707 | ClientToScreen (FRAME_W32_WINDOW (f), &pt); | ||
| 3313 | 3708 | ||
| 3314 | SetCursorPos (pix_x, pix_y); | 3709 | SetCursorPos (pt.x, pt.y); |
| 3315 | 3710 | ||
| 3316 | UNBLOCK_INPUT; | 3711 | UNBLOCK_INPUT; |
| 3317 | } | 3712 | } |
| @@ -3340,6 +3735,18 @@ x_set_mouse_position (f, x, y) | |||
| 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) |
| @@ -3352,15 +3759,59 @@ x_unfocus_frame (f) | |||
| 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; |
| 3763 | |||
| 3764 | /* Strictly speaking, raise-frame should only change the frame's Z | ||
| 3765 | order, leaving input focus unchanged. This is reasonable behaviour | ||
| 3766 | on X where the usual policy is point-to-focus. However, this | ||
| 3767 | behaviour would be very odd on Windows where the usual policy is | ||
| 3768 | click-to-focus. | ||
| 3769 | |||
| 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)) | ||
| 3356 | { | 3784 | { |
| 3357 | BLOCK_INPUT; | 3785 | /* The obvious call to my_set_window_pos doesn't work if Emacs is |
| 3358 | my_set_window_pos (FRAME_W32_WINDOW (f), | 3786 | not already the foreground application: the frame is raised |
| 3359 | HWND_TOP, | 3787 | above all other frames belonging to us, but not above the |
| 3360 | 0, 0, 0, 0, | 3788 | current top window. To achieve that, we have to resort to this |
| 3361 | SWP_NOSIZE | SWP_NOMOVE); | 3789 | more cumbersome method. */ |
| 3362 | UNBLOCK_INPUT; | 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 | } | ||
| 3363 | } | 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. */ |
| @@ -3368,15 +3819,12 @@ x_raise_frame (f) | |||
| 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 |
| @@ -3412,14 +3860,12 @@ x_make_frame_visible (f) | |||
| 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 |
| @@ -3482,7 +3928,7 @@ x_make_frame_invisible (f) | |||
| 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. |
| @@ -3514,9 +3960,8 @@ x_iconify_frame (f) | |||
| 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 | ||
| @@ -3578,8 +4023,10 @@ x_wm_set_size_hint (f, flags, user_position) | |||
| 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 | } |
| @@ -3794,7 +4241,7 @@ x_delete_display (dpyinfo) | |||
| 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 | { |
| @@ -3831,8 +4278,9 @@ w32_initialize () | |||
| 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 | ||
| @@ -3850,7 +4298,7 @@ w32_initialize () | |||
| 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); |
| @@ -3867,6 +4315,31 @@ w32_initialize () | |||
| 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 |
| @@ -3891,4 +4364,18 @@ syms_of_w32term () | |||
| 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; |
| 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; | ||
| 3894 | } | 4381 | } |