Mercurial > hg > xemacs-beta
comparison src/event-msw.c @ 404:2f8bb876ab1d r21-2-32
Import from CVS: tag r21-2-32
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:16:07 +0200 |
parents | a86b2b5e0111 |
children | b8cc9ab3f761 |
comparison
equal
deleted
inserted
replaced
403:9f011ab08d48 | 404:2f8bb876ab1d |
---|---|
1 /* The mswindows event_stream interface. | 1 /* The mswindows event_stream interface. |
2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. | 2 Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. |
3 Copyright (C) 1995 Sun Microsystems, Inc. | 3 Copyright (C) 1995 Sun Microsystems, Inc. |
4 Copyright (C) 1996 Ben Wing. | 4 Copyright (C) 1996, 2000 Ben Wing. |
5 Copyright (C) 1997 Jonathan Harris. | 5 Copyright (C) 1997 Jonathan Harris. |
6 | 6 |
7 This file is part of XEmacs. | 7 This file is part of XEmacs. |
8 | 8 |
9 XEmacs is free software; you can redistribute it and/or modify it | 9 XEmacs is free software; you can redistribute it and/or modify it |
39 #ifdef HAVE_SCROLLBARS | 39 #ifdef HAVE_SCROLLBARS |
40 # include "scrollbar-msw.h" | 40 # include "scrollbar-msw.h" |
41 #endif | 41 #endif |
42 | 42 |
43 #ifdef HAVE_MENUBARS | 43 #ifdef HAVE_MENUBARS |
44 # include "menubar.h" | |
44 # include "menubar-msw.h" | 45 # include "menubar-msw.h" |
45 #endif | 46 #endif |
46 | 47 |
47 #ifdef HAVE_DRAGNDROP | 48 #ifdef HAVE_DRAGNDROP |
48 # include "dragdrop.h" | 49 # include "dragdrop.h" |
71 typedef unsigned int SOCKET; | 72 typedef unsigned int SOCKET; |
72 #endif | 73 #endif |
73 #include <io.h> | 74 #include <io.h> |
74 #include <errno.h> | 75 #include <errno.h> |
75 | 76 |
77 #if !(defined(__CYGWIN32__) || defined(__MINGW32__)) | |
78 # include <shlobj.h> /* For IShellLink */ | |
79 #endif | |
80 | |
76 #if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20) | 81 #if defined (__CYGWIN32__) && (CYGWIN_VERSION_DLL_MAJOR < 20) |
77 typedef NMHDR *LPNMHDR; | 82 typedef NMHDR *LPNMHDR; |
78 #endif | 83 #endif |
79 | 84 |
80 #ifdef HAVE_MENUBARS | 85 #ifdef HAVE_MENUBARS |
138 Decremented in mswindows_dequeue_dispatch_event() */ | 143 Decremented in mswindows_dequeue_dispatch_event() */ |
139 int mswindows_quit_chars_count = 0; | 144 int mswindows_quit_chars_count = 0; |
140 | 145 |
141 /* These are Lisp integers; see DEFVARS in this file for description. */ | 146 /* These are Lisp integers; see DEFVARS in this file for description. */ |
142 int mswindows_dynamic_frame_resize; | 147 int mswindows_dynamic_frame_resize; |
143 int mswindows_meta_activates_menu; | 148 int mswindows_alt_by_itself_activates_menu; |
144 int mswindows_num_mouse_buttons; | 149 int mswindows_num_mouse_buttons; |
145 int mswindows_mouse_button_max_skew_x; | 150 int mswindows_mouse_button_max_skew_x; |
146 int mswindows_mouse_button_max_skew_y; | 151 int mswindows_mouse_button_max_skew_y; |
147 int mswindows_mouse_button_tolerance; | 152 int mswindows_mouse_button_tolerance; |
148 | 153 |
177 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */ | 182 deallocated in this case, ntpipe_slurp_stream_shared_data are not. */ |
178 | 183 |
179 struct ntpipe_slurp_stream_shared_data | 184 struct ntpipe_slurp_stream_shared_data |
180 { | 185 { |
181 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ | 186 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ |
182 /* This is a manual-reset object. */ | 187 /* This is a manual-reset object. */ |
183 HANDLE hev_caller; /* Caller blocks on this, and we signal it */ | 188 HANDLE hev_caller; /* Caller blocks on this, and we signal it */ |
184 /* This is a manual-reset object. */ | 189 /* This is a manual-reset object. */ |
185 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */ | 190 HANDLE hev_unsleep; /* Pipe read delay is canceled if this is set */ |
186 /* This is a manual-reset object. */ | 191 /* This is a manual-reset object. */ |
187 HANDLE hpipe; /* Pipe read end handle. */ | 192 HANDLE hpipe; /* Pipe read end handle. */ |
188 LONG die_p; /* Thread must exit ASAP if non-zero */ | 193 LONG die_p; /* Thread must exit ASAP if non-zero */ |
189 BOOL eof_p : 1; /* Set when thread saw EOF */ | 194 BOOL eof_p : 1; /* Set when thread saw EOF */ |
190 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ | 195 BOOL error_p : 1; /* Read error other than EOF/broken pipe */ |
191 BOOL inuse_p : 1; /* this structure is in use */ | 196 BOOL inuse_p : 1; /* this structure is in use */ |
220 s->inuse_p = 0; | 225 s->inuse_p = 0; |
221 } | 226 } |
222 } | 227 } |
223 | 228 |
224 static struct ntpipe_slurp_stream_shared_data* | 229 static struct ntpipe_slurp_stream_shared_data* |
225 slurper_allocate_shared_data() | 230 slurper_allocate_shared_data (void) |
226 { | 231 { |
227 int i=0; | 232 int i=0; |
228 for (i=0; i<MAX_SLURP_STREAMS; i++) | 233 for (i=0; i<MAX_SLURP_STREAMS; i++) |
229 { | 234 { |
230 if (!shared_data_block[i].inuse_p) | 235 if (!shared_data_block[i].inuse_p) |
467 | 472 |
468 struct ntpipe_shove_stream | 473 struct ntpipe_shove_stream |
469 { | 474 { |
470 LPARAM user_data; /* Any user data stored in the stream object */ | 475 LPARAM user_data; /* Any user data stored in the stream object */ |
471 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ | 476 HANDLE hev_thread; /* Our thread blocks on this, signaled by caller */ |
472 /* This is an auto-reset object. */ | 477 /* This is an auto-reset object. */ |
473 HANDLE hpipe; /* Pipe write end handle. */ | 478 HANDLE hpipe; /* Pipe write end handle. */ |
474 HANDLE hthread; /* Reader thread handle. */ | 479 HANDLE hthread; /* Reader thread handle. */ |
475 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */ | 480 char buffer[MAX_SHOVE_BUFFER_SIZE]; /* Buffer being written */ |
476 DWORD size; /* Number of bytes to write */ | 481 DWORD size; /* Number of bytes to write */ |
477 LONG die_p; /* Thread must exit ASAP if non-zero */ | 482 LONG die_p; /* Thread must exit ASAP if non-zero */ |
869 mswindows_enqueue_dispatch_event (Lisp_Object event) | 874 mswindows_enqueue_dispatch_event (Lisp_Object event) |
870 { | 875 { |
871 int user_p = mswindows_user_event_p (XEVENT(event)); | 876 int user_p = mswindows_user_event_p (XEVENT(event)); |
872 enqueue_event (event, | 877 enqueue_event (event, |
873 user_p ? &mswindows_u_dispatch_event_queue : | 878 user_p ? &mswindows_u_dispatch_event_queue : |
874 &mswindows_s_dispatch_event_queue, | 879 &mswindows_s_dispatch_event_queue, |
875 user_p ? &mswindows_u_dispatch_event_queue_tail : | 880 user_p ? &mswindows_u_dispatch_event_queue_tail : |
876 &mswindows_s_dispatch_event_queue_tail); | 881 &mswindows_s_dispatch_event_queue_tail); |
877 | 882 |
878 /* Avoid blocking on WaitMessage */ | 883 /* Avoid blocking on WaitMessage */ |
879 PostMessage (NULL, XM_BUMPQUEUE, 0, 0); | 884 PostMessage (NULL, XM_BUMPQUEUE, 0, 0); |
880 } | 885 } |
881 | 886 |
989 /* | 994 /* |
990 * Remove and return the first emacs event on the dispatch queue. | 995 * Remove and return the first emacs event on the dispatch queue. |
991 * Give a preference to user events over non-user ones. | 996 * Give a preference to user events over non-user ones. |
992 */ | 997 */ |
993 static Lisp_Object | 998 static Lisp_Object |
994 mswindows_dequeue_dispatch_event () | 999 mswindows_dequeue_dispatch_event (void) |
995 { | 1000 { |
996 Lisp_Object event; | 1001 Lisp_Object event; |
997 Lisp_Event* sevt; | 1002 Lisp_Event* sevt; |
998 | 1003 |
999 assert (!NILP(mswindows_u_dispatch_event_queue) || | 1004 assert (!NILP(mswindows_u_dispatch_event_queue) || |
1000 !NILP(mswindows_s_dispatch_event_queue)); | 1005 !NILP(mswindows_s_dispatch_event_queue)); |
1001 | 1006 |
1002 event = dequeue_event ( | 1007 event = dequeue_event ( |
1003 NILP(mswindows_u_dispatch_event_queue) ? | 1008 NILP(mswindows_u_dispatch_event_queue) ? |
1004 &mswindows_s_dispatch_event_queue : | 1009 &mswindows_s_dispatch_event_queue : |
1005 &mswindows_u_dispatch_event_queue, | 1010 &mswindows_u_dispatch_event_queue, |
1006 NILP(mswindows_u_dispatch_event_queue) ? | 1011 NILP(mswindows_u_dispatch_event_queue) ? |
1007 &mswindows_s_dispatch_event_queue_tail : | 1012 &mswindows_s_dispatch_event_queue_tail : |
1008 &mswindows_u_dispatch_event_queue_tail); | 1013 &mswindows_u_dispatch_event_queue_tail); |
1009 | 1014 |
1010 sevt = XEVENT(event); | 1015 sevt = XEVENT(event); |
1011 if (sevt->event_type == key_press_event | 1016 if (sevt->event_type == key_press_event |
1032 { | 1037 { |
1033 Lisp_Object event; | 1038 Lisp_Object event; |
1034 Lisp_Object previous_event = Qnil; | 1039 Lisp_Object previous_event = Qnil; |
1035 int user_p = mswindows_user_event_p (match); | 1040 int user_p = mswindows_user_event_p (match); |
1036 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : | 1041 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : |
1037 &mswindows_s_dispatch_event_queue; | 1042 &mswindows_s_dispatch_event_queue; |
1038 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : | 1043 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : |
1039 &mswindows_s_dispatch_event_queue_tail; | 1044 &mswindows_s_dispatch_event_queue_tail; |
1040 | 1045 |
1041 assert (match->event_type == timeout_event | 1046 assert (match->event_type == timeout_event |
1042 || match->event_type == key_press_event); | 1047 || match->event_type == key_press_event); |
1043 | 1048 |
1044 EVENT_CHAIN_LOOP (event, *head) | 1049 EVENT_CHAIN_LOOP (event, *head) |
1219 Lisp_Object result = Qt; | 1224 Lisp_Object result = Qt; |
1220 struct gcpro gcpro1; | 1225 struct gcpro gcpro1; |
1221 GCPRO1 (result); | 1226 GCPRO1 (result); |
1222 | 1227 |
1223 if (NILP(mswindows_error_caught_in_modal_loop)) | 1228 if (NILP(mswindows_error_caught_in_modal_loop)) |
1224 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil); | 1229 result = mswindows_protect_modal_loop (mswindows_unsafe_pump_events, Qnil); |
1225 UNGCPRO; | 1230 UNGCPRO; |
1226 return result; | 1231 return result; |
1227 } | 1232 } |
1228 | 1233 |
1229 /* | 1234 /* |
1230 * KEYBOARD_ONLY_P is set to non-zero when we are called from | 1235 * KEYBOARD_ONLY_P is set to non-zero when we are called from |
1231 * QUITP, and are interesting in keyboard messages only. | 1236 * QUITP, and are interesting in keyboard messages only. |
1232 */ | 1237 */ |
1233 static void | 1238 static void |
1234 mswindows_drain_windows_queue () | 1239 mswindows_drain_windows_queue (void) |
1235 { | 1240 { |
1236 MSG msg; | 1241 MSG msg; |
1237 | 1242 |
1238 /* should call mswindows_need_event_in_modal_loop() if in modal loop */ | 1243 /* should call mswindows_need_event_in_modal_loop() if in modal loop */ |
1239 assert (!mswindows_in_modal_loop); | 1244 assert (!mswindows_in_modal_loop); |
1241 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) | 1246 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) |
1242 { | 1247 { |
1243 /* We have to translate messages that are not sent to the main | 1248 /* We have to translate messages that are not sent to the main |
1244 window. This is so that key presses work ok in things like | 1249 window. This is so that key presses work ok in things like |
1245 edit fields. However, we *musn't* translate message for the | 1250 edit fields. However, we *musn't* translate message for the |
1246 main window as this is handled in the wnd proc. */ | 1251 main window as this is handled in the wnd proc. |
1247 if (GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD) | 1252 We also have to avoid generating paint magic events for windows |
1253 that aren't XEmacs frames */ | |
1254 if (GetWindowLong (msg.hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP)) | |
1248 { | 1255 { |
1249 TranslateMessage (&msg); | 1256 TranslateMessage (&msg); |
1250 } | 1257 } |
1251 else if (msg.message == WM_PAINT) | 1258 else if (msg.message == WM_PAINT) |
1252 { | 1259 { |
1260 struct mswindows_frame* msframe; | |
1261 | |
1253 /* hdc will be NULL unless this is a subwindow - in which case we | 1262 /* hdc will be NULL unless this is a subwindow - in which case we |
1254 shouldn't have received a paint message for it here. */ | 1263 shouldn't have received a paint message for it here. */ |
1255 assert (msg.wParam == 0); | 1264 assert (msg.wParam == 0); |
1256 | 1265 |
1257 /* Queue a magic event for handling when safe */ | 1266 /* Queue a magic event for handling when safe */ |
1258 mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT); | 1267 msframe = FRAME_MSWINDOWS_DATA ( |
1259 | 1268 XFRAME (mswindows_find_frame (msg.hwnd))); |
1269 if (!msframe->paint_pending) | |
1270 { | |
1271 msframe->paint_pending = 1; | |
1272 mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT); | |
1273 } | |
1260 /* Don't dispatch. WM_PAINT is always the last message in the | 1274 /* Don't dispatch. WM_PAINT is always the last message in the |
1261 queue so it's OK to just return. */ | 1275 queue so it's OK to just return. */ |
1262 return; | 1276 return; |
1263 } | 1277 } |
1264 DispatchMessage (&msg); | 1278 DispatchMessage (&msg); |
1353 { | 1367 { |
1354 if (FD_ISSET (windows_fd, &temp_mask)) | 1368 if (FD_ISSET (windows_fd, &temp_mask)) |
1355 { | 1369 { |
1356 mswindows_drain_windows_queue (); | 1370 mswindows_drain_windows_queue (); |
1357 } | 1371 } |
1372 else | |
1373 { | |
1358 #ifdef HAVE_TTY | 1374 #ifdef HAVE_TTY |
1359 /* Look for a TTY event */ | 1375 /* Look for a TTY event */ |
1360 for (i = 0; i < MAXDESC-1; i++) | 1376 for (i = 0; i < MAXDESC-1; i++) |
1361 { | |
1362 /* To avoid race conditions (among other things, an infinite | |
1363 loop when called from Fdiscard_input()), we must return | |
1364 user events ahead of process events. */ | |
1365 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) | |
1366 { | 1377 { |
1367 struct console *c = tty_find_console_from_fd (i); | 1378 /* To avoid race conditions (among other things, an infinite |
1368 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); | 1379 loop when called from Fdiscard_input()), we must return |
1369 Lisp_Event* event = XEVENT (emacs_event); | 1380 user events ahead of process events. */ |
1370 | 1381 if (FD_ISSET (i, &temp_mask) && FD_ISSET (i, &tty_only_mask)) |
1371 assert (c); | |
1372 if (read_event_from_tty_or_stream_desc (event, c, i)) | |
1373 { | 1382 { |
1374 mswindows_enqueue_dispatch_event (emacs_event); | 1383 struct console *c = tty_find_console_from_fd (i); |
1375 return; | 1384 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); |
1385 Lisp_Event* event = XEVENT (emacs_event); | |
1386 | |
1387 assert (c); | |
1388 if (read_event_from_tty_or_stream_desc (event, c, i)) | |
1389 { | |
1390 mswindows_enqueue_dispatch_event (emacs_event); | |
1391 return; | |
1392 } | |
1376 } | 1393 } |
1377 } | 1394 } |
1378 } | 1395 #endif |
1379 #endif | 1396 /* Look for a process event */ |
1380 /* Look for a process event */ | 1397 for (i = 0; i < MAXDESC-1; i++) |
1381 for (i = 0; i < MAXDESC-1; i++) | |
1382 { | |
1383 if (FD_ISSET (i, &temp_mask)) | |
1384 { | 1398 { |
1385 if (FD_ISSET (i, &process_only_mask)) | 1399 if (FD_ISSET (i, &temp_mask)) |
1386 { | 1400 { |
1387 Lisp_Process *p = | 1401 if (FD_ISSET (i, &process_only_mask)) |
1388 get_process_from_usid (FD_TO_USID(i)); | 1402 { |
1389 | 1403 Lisp_Process *p = |
1390 mswindows_enqueue_process_event (p); | 1404 get_process_from_usid (FD_TO_USID(i)); |
1391 } | 1405 |
1392 else | 1406 mswindows_enqueue_process_event (p); |
1393 { | 1407 } |
1394 /* We might get here when a fake event came | 1408 else |
1395 through a signal. Return a dummy event, so | 1409 { |
1396 that a cycle of the command loop will | 1410 /* We might get here when a fake event came |
1397 occur. */ | 1411 through a signal. Return a dummy event, so |
1398 drain_signal_event_pipe (); | 1412 that a cycle of the command loop will |
1399 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | 1413 occur. */ |
1414 drain_signal_event_pipe (); | |
1415 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | |
1416 } | |
1400 } | 1417 } |
1401 } | 1418 } |
1402 } | 1419 } |
1403 } | 1420 } |
1404 else if (active==-1) | 1421 else if (active==-1) |
1413 { | 1430 { |
1414 assert(0); | 1431 assert(0); |
1415 } | 1432 } |
1416 #else | 1433 #else |
1417 /* Now try getting a message or process event */ | 1434 /* Now try getting a message or process event */ |
1418 active = MsgWaitForMultipleObjects (mswindows_waitable_count, | 1435 active = MsgWaitForMultipleObjects (mswindows_waitable_count, |
1419 mswindows_waitable_handles, | 1436 mswindows_waitable_handles, |
1420 FALSE, badly_p ? INFINITE : 0, | 1437 FALSE, badly_p ? INFINITE : 0, |
1421 QS_ALLINPUT); | 1438 QS_ALLINPUT); |
1422 | 1439 |
1423 /* This will assert if handle being waited for becomes abandoned. | 1440 /* This will assert if handle being waited for becomes abandoned. |
1424 Not the case currently tho */ | 1441 Not the case currently tho */ |
1425 assert ((!badly_p && active == WAIT_TIMEOUT) || | 1442 assert ((!badly_p && active == WAIT_TIMEOUT) || |
1426 (active >= WAIT_OBJECT_0 && | 1443 (active >= WAIT_OBJECT_0 && |
1427 active <= WAIT_OBJECT_0 + mswindows_waitable_count)); | 1444 active <= WAIT_OBJECT_0 + mswindows_waitable_count)); |
1428 | 1445 |
1429 if (active == WAIT_TIMEOUT) | 1446 if (active == WAIT_TIMEOUT) |
1430 { | 1447 { |
1431 /* No luck trying - just return what we've already got */ | 1448 /* No luck trying - just return what we've already got */ |
1432 return; | 1449 return; |
1433 } | 1450 } |
1434 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count) | 1451 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count) |
1435 { | 1452 { |
1436 /* Got your message, thanks */ | 1453 /* Got your message, thanks */ |
1437 mswindows_drain_windows_queue (); | 1454 mswindows_drain_windows_queue (); |
1438 } | 1455 } |
1439 else | 1456 else |
1440 { | 1457 { |
1441 int ix = active - WAIT_OBJECT_0; | 1458 int ix = active - WAIT_OBJECT_0; |
1442 /* First, try to find which process' output has signaled */ | 1459 /* First, try to find which process' output has signaled */ |
1443 Lisp_Process *p = | 1460 Lisp_Process *p = |
1444 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix])); | 1461 get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix])); |
1445 if (p != NULL) | 1462 if (p != NULL) |
1446 { | 1463 { |
1447 /* Found a signaled process input handle */ | 1464 /* Found a signaled process input handle */ |
1448 mswindows_enqueue_process_event (p); | 1465 mswindows_enqueue_process_event (p); |
1449 } | 1466 } |
1450 else | 1467 else |
1451 { | 1468 { |
1452 /* None. This means that the process handle itself has signaled. | 1469 /* None. This means that the process handle itself has signaled. |
1453 Remove the handle from the wait vector, and make status_notify | 1470 Remove the handle from the wait vector, and make status_notify |
1454 note the exited process */ | 1471 note the exited process */ |
1455 mswindows_waitable_handles [ix] = | 1472 mswindows_waitable_handles [ix] = |
1456 mswindows_waitable_handles [--mswindows_waitable_count]; | 1473 mswindows_waitable_handles [--mswindows_waitable_count]; |
1457 kick_status_notify (); | 1474 kick_status_notify (); |
1458 /* Have to return something: there may be no accompanying | 1475 /* Have to return something: there may be no accompanying |
1459 process event */ | 1476 process event */ |
1460 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | 1477 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); |
1461 } | 1478 } |
1462 } | 1479 } |
1463 #endif | 1480 #endif |
1464 } /* while */ | 1481 } /* while */ |
1465 } | 1482 } |
1466 | 1483 |
1467 /************************************************************************/ | 1484 /************************************************************************/ |
1468 /* Event generators */ | 1485 /* Event generators */ |
1469 /************************************************************************/ | 1486 /************************************************************************/ |
1612 | 1629 |
1613 /* | 1630 /* |
1614 * Helper to do repainting - repaints can happen both from the windows | 1631 * Helper to do repainting - repaints can happen both from the windows |
1615 * procedure and from magic events | 1632 * procedure and from magic events |
1616 */ | 1633 */ |
1617 void | 1634 static void |
1618 mswindows_handle_paint (struct frame *frame) | 1635 mswindows_handle_paint (struct frame *frame) |
1619 { | 1636 { |
1620 HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame); | 1637 HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame); |
1621 | 1638 |
1622 /* According to the docs we need to check GetUpdateRect() before | 1639 /* According to the docs we need to check GetUpdateRect() before |
1623 actually doing a WM_PAINT */ | 1640 actually doing a WM_PAINT */ |
1624 if (GetUpdateRect (hwnd, NULL, FALSE)) | 1641 if (GetUpdateRect (hwnd, NULL, FALSE)) |
1625 { | 1642 { |
1626 PAINTSTRUCT paintStruct; | 1643 PAINTSTRUCT paintStruct; |
1627 int x, y, width, height; | 1644 int x, y, width, height; |
1628 | 1645 |
1629 BeginPaint (hwnd, &paintStruct); | 1646 BeginPaint (hwnd, &paintStruct); |
1630 x = paintStruct.rcPaint.left; | 1647 x = paintStruct.rcPaint.left; |
1631 y = paintStruct.rcPaint.top; | 1648 y = paintStruct.rcPaint.top; |
1632 width = paintStruct.rcPaint.right - paintStruct.rcPaint.left; | 1649 width = paintStruct.rcPaint.right - paintStruct.rcPaint.left; |
1633 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top; | 1650 height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top; |
1634 /* Normally we want to ignore expose events when child | 1651 /* Normally we want to ignore expose events when child |
1635 windows are unmapped, however once we are in the guts of | 1652 windows are unmapped, however once we are in the guts of |
1636 WM_PAINT we need to make sure that we don't register | 1653 WM_PAINT we need to make sure that we don't register |
1637 unmaps then because they will not actually occur. */ | 1654 unmaps then because they will not actually occur. */ |
1638 if (!check_for_ignored_expose (frame, x, y, width, height)) | 1655 if (!check_for_ignored_expose (frame, x, y, width, height)) |
1639 { | 1656 { |
1640 hold_ignored_expose_registration = 1; | 1657 hold_ignored_expose_registration = 1; |
1641 mswindows_redraw_exposed_area (frame, x, y, width, height); | 1658 mswindows_redraw_exposed_area (frame, x, y, width, height); |
1642 hold_ignored_expose_registration = 0; | 1659 hold_ignored_expose_registration = 0; |
1643 } | 1660 } |
1644 EndPaint (hwnd, &paintStruct); | 1661 EndPaint (hwnd, &paintStruct); |
1645 } | 1662 } |
1646 } | 1663 } |
1647 | 1664 |
1648 /* | 1665 /* |
1649 * Returns 1 if a key is a real modifier or special key, which | 1666 * Returns 1 if a key is a real modifier or special key, which |
1650 * is better handled by DefWindowProc | 1667 * is better handled by DefWindowProc |
1651 */ | 1668 */ |
1652 static int | 1669 static int |
1653 key_needs_default_processing_p (UINT vkey) | 1670 key_needs_default_processing_p (UINT vkey) |
1654 { | 1671 { |
1655 if (mswindows_meta_activates_menu && vkey == VK_MENU) | 1672 if (mswindows_alt_by_itself_activates_menu && vkey == VK_MENU) |
1656 return 1; | 1673 return 1; |
1657 | 1674 |
1658 return 0; | 1675 return 0; |
1659 } | 1676 } |
1660 | 1677 |
1671 | 1688 |
1672 Lisp_Event *event; | 1689 Lisp_Event *event; |
1673 struct frame *frame; | 1690 struct frame *frame; |
1674 struct mswindows_frame* msframe; | 1691 struct mswindows_frame* msframe; |
1675 | 1692 |
1693 assert (!GetWindowLong (hwnd, GWL_USERDATA)); | |
1676 switch (message) | 1694 switch (message) |
1677 { | 1695 { |
1678 case WM_DESTROYCLIPBOARD: | 1696 case WM_DESTROYCLIPBOARD: |
1679 /* We own the clipboard and someone else wants it. Delete our | 1697 /* We own the clipboard and someone else wants it. Delete our |
1680 cached copy of the clipboard contents so we'll ask for it from | 1698 cached copy of the clipboard contents so we'll ask for it from |
1681 Windows again when someone does a paste. */ | 1699 Windows again when someone does a paste. */ |
1682 handle_selection_clear(QCLIPBOARD); | 1700 handle_selection_clear(QCLIPBOARD); |
1683 break; | 1701 break; |
1684 | 1702 |
1685 case WM_ERASEBKGND: | 1703 case WM_ERASEBKGND: |
1686 /* Erase background only during non-dynamic sizing */ | 1704 /* Erase background only during non-dynamic sizing */ |
1687 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | 1705 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
1688 if (msframe->sizing && !mswindows_dynamic_frame_resize) | 1706 if (msframe->sizing && !mswindows_dynamic_frame_resize) |
1689 goto defproc; | 1707 goto defproc; |
1690 return 1; | 1708 return 1; |
1691 | 1709 |
1692 case WM_CLOSE: | 1710 case WM_CLOSE: |
1693 fobj = mswindows_find_frame (hwnd); | 1711 fobj = mswindows_find_frame (hwnd); |
1694 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt)); | 1712 mswindows_enqueue_misc_user_event (fobj, Qeval, list3 (Qdelete_frame, fobj, Qt)); |
1695 break; | 1713 break; |
1696 | 1714 |
1697 case WM_KEYUP: | 1715 case WM_KEYUP: |
1698 case WM_SYSKEYUP: | 1716 case WM_SYSKEYUP: |
1699 /* See Win95 comment under WM_KEYDOWN */ | 1717 /* See Win95 comment under WM_KEYDOWN */ |
1700 { | 1718 { |
1701 BYTE keymap[256]; | 1719 BYTE keymap[256]; |
1702 | 1720 int should_set_keymap = 0; |
1703 if (wParam == VK_CONTROL) | 1721 |
1704 { | 1722 if (wParam == VK_CONTROL) |
1705 GetKeyboardState (keymap); | 1723 { |
1706 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80; | 1724 GetKeyboardState (keymap); |
1725 keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] &= ~0x80; | |
1726 should_set_keymap = 1; | |
1727 } | |
1728 else if (wParam == VK_MENU) | |
1729 { | |
1730 GetKeyboardState (keymap); | |
1731 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80; | |
1732 should_set_keymap = 1; | |
1733 } | |
1734 | |
1735 if (should_set_keymap | |
1736 && (message != WM_SYSKEYUP | |
1737 || NILP (Vmenu_accelerator_enabled))) | |
1707 SetKeyboardState (keymap); | 1738 SetKeyboardState (keymap); |
1708 } | 1739 |
1709 else if (wParam == VK_MENU) | 1740 } |
1710 { | 1741 if (key_needs_default_processing_p (wParam)) |
1711 GetKeyboardState (keymap); | 1742 goto defproc; |
1712 keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] &= ~0x80; | 1743 else |
1713 SetKeyboardState (keymap); | 1744 break; |
1714 } | 1745 |
1715 }; | 1746 case WM_KEYDOWN: |
1716 if (key_needs_default_processing_p (wParam)) | 1747 case WM_SYSKEYDOWN: |
1717 goto defproc; | 1748 /* In some locales the right-hand Alt key is labelled AltGr. This key |
1718 else | 1749 * should produce alternative charcaters when combined with another key. |
1750 * eg on a German keyboard pressing AltGr+q should produce '@'. | |
1751 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if | |
1752 * TranslateMessage() is called with *any* combination of Ctrl+Alt down, | |
1753 * it translates as if AltGr were down. | |
1754 * We get round this by removing all modifiers from the keymap before | |
1755 * calling TranslateMessage() unless AltGr is *really* down. */ | |
1756 { | |
1757 BYTE keymap[256]; | |
1758 int has_AltGr = mswindows_current_layout_has_AltGr (); | |
1759 int mods; | |
1760 int extendedp = lParam & 0x1000000; | |
1761 Lisp_Object keysym; | |
1762 | |
1763 frame = XFRAME (mswindows_find_frame (hwnd)); | |
1764 GetKeyboardState (keymap); | |
1765 mods = mswindows_modifier_state (keymap, has_AltGr); | |
1766 | |
1767 /* Handle non-printables */ | |
1768 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods, | |
1769 extendedp))) | |
1770 mswindows_enqueue_keypress_event (hwnd, keysym, mods); | |
1771 else /* Normal keys & modifiers */ | |
1772 { | |
1773 Emchar quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); | |
1774 BYTE keymap_orig[256]; | |
1775 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; | |
1776 MSG msg, tranmsg; | |
1777 int potential_accelerator = 0; | |
1778 int got_accelerator = 0; | |
1779 | |
1780 msg.hwnd = hwnd; | |
1781 msg.message = message; | |
1782 msg.wParam = wParam; | |
1783 msg.lParam = lParam; | |
1784 msg.time = GetMessageTime(); | |
1785 msg.pt = pnt; | |
1786 | |
1787 /* GetKeyboardState() does not work as documented on Win95. We have | |
1788 * to loosely track Left and Right modifiers on behalf of the OS, | |
1789 * without screwing up Windows NT which tracks them properly. */ | |
1790 if (wParam == VK_CONTROL) | |
1791 keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; | |
1792 else if (wParam == VK_MENU) | |
1793 keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80; | |
1794 | |
1795 memcpy (keymap_orig, keymap, 256); | |
1796 | |
1797 if (!NILP (Vmenu_accelerator_enabled) && | |
1798 !(mods & XEMACS_MOD_SHIFT) && message == WM_SYSKEYDOWN) | |
1799 potential_accelerator = 1; | |
1800 | |
1801 /* Remove shift modifier from an ascii character */ | |
1802 mods &= ~XEMACS_MOD_SHIFT; | |
1803 | |
1804 /* Clear control and alt modifiers unless AltGr is pressed */ | |
1805 keymap [VK_RCONTROL] = 0; | |
1806 keymap [VK_LMENU] = 0; | |
1807 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) | |
1808 || !(keymap [VK_RMENU] & 0x80)) | |
1809 { | |
1810 keymap [VK_LCONTROL] = 0; | |
1811 keymap [VK_CONTROL] = 0; | |
1812 keymap [VK_RMENU] = 0; | |
1813 keymap [VK_MENU] = 0; | |
1814 } | |
1815 SetKeyboardState (keymap); | |
1816 | |
1817 /* Maybe generate some WM_[SYS]CHARs in the queue */ | |
1818 TranslateMessage (&msg); | |
1819 | |
1820 while (PeekMessage (&tranmsg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) | |
1821 || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) | |
1822 { | |
1823 int mods1 = mods; | |
1824 WPARAM ch = tranmsg.wParam; | |
1825 | |
1826 /* If a quit char with no modifiers other than control and | |
1827 shift, then mark it with a fake modifier, which is removed | |
1828 upon dequeueing the event */ | |
1829 /* #### This might also not withstand localization, if | |
1830 quit character is not a latin-1 symbol */ | |
1831 if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL) && quit_ch + 'a' - 1 == ch) | |
1832 || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL) && quit_ch == ch)) | |
1833 && ((mods & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT)) == 0)) | |
1834 { | |
1835 mods1 |= FAKE_MOD_QUIT; | |
1836 ++mswindows_quit_chars_count; | |
1837 } | |
1838 else if (potential_accelerator && !got_accelerator && | |
1839 msw_char_is_accelerator (frame, ch)) | |
1840 { | |
1841 got_accelerator = 1; | |
1842 break; | |
1843 } | |
1844 mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1); | |
1845 } /* while */ | |
1846 SetKeyboardState (keymap_orig); | |
1847 /* This generates WM_SYSCHAR messages, which are interpreted | |
1848 by DefWindowProc as the menu selections. */ | |
1849 if (got_accelerator) | |
1850 { | |
1851 TranslateMessage (&msg); | |
1852 goto defproc; | |
1853 } | |
1854 } /* else */ | |
1855 } | |
1856 if (key_needs_default_processing_p (wParam)) | |
1857 goto defproc; | |
1858 else | |
1859 break; | |
1860 | |
1861 case WM_MBUTTONDOWN: | |
1862 case WM_MBUTTONUP: | |
1863 /* Real middle mouse button has nothing to do with emulated one: | |
1864 if one wants to exercise fingers playing chords on the mouse, | |
1865 he is allowed to do that! */ | |
1866 mswindows_enqueue_mouse_button_event (hwnd, message, | |
1867 MAKEPOINTS (lParam), GetMessageTime()); | |
1719 break; | 1868 break; |
1720 | 1869 |
1721 case WM_KEYDOWN: | 1870 case WM_LBUTTONUP: |
1722 case WM_SYSKEYDOWN: | 1871 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
1723 /* In some locales the right-hand Alt key is labelled AltGr. This key | 1872 msframe->last_click_time = GetMessageTime(); |
1724 * should produce alternative charcaters when combined with another key. | 1873 |
1725 * eg on a German keyboard pressing AltGr+q should produce '@'. | 1874 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
1726 * AltGr generates exactly the same keystrokes as LCtrl+RAlt. But if | 1875 msframe->button2_need_lbutton = 0; |
1727 * TranslateMessage() is called with *any* combination of Ctrl+Alt down, | 1876 if (msframe->ignore_next_lbutton_up) |
1728 * it translates as if AltGr were down. | 1877 { |
1729 * We get round this by removing all modifiers from the keymap before | 1878 msframe->ignore_next_lbutton_up = 0; |
1730 * calling TranslateMessage() unless AltGr is *really* down. */ | 1879 } |
1731 { | 1880 else if (msframe->button2_is_down) |
1732 BYTE keymap[256]; | 1881 { |
1733 int has_AltGr = mswindows_current_layout_has_AltGr (); | 1882 msframe->button2_is_down = 0; |
1734 int mods; | 1883 msframe->ignore_next_rbutton_up = 1; |
1735 int extendedp = lParam & 0x1000000; | 1884 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, |
1736 Lisp_Object keysym; | 1885 MAKEPOINTS (lParam), GetMessageTime()); |
1737 | 1886 } |
1738 GetKeyboardState (keymap); | 1887 else |
1739 mods = mswindows_modifier_state (keymap, has_AltGr); | 1888 { |
1740 | 1889 if (msframe->button2_need_rbutton) |
1741 /* Handle non-printables */ | |
1742 if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods, | |
1743 extendedp))) | |
1744 mswindows_enqueue_keypress_event (hwnd, keysym, mods); | |
1745 else /* Normal keys & modifiers */ | |
1746 { | |
1747 int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); | |
1748 BYTE keymap_orig[256]; | |
1749 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) }; | |
1750 MSG msg; | |
1751 | |
1752 msg.hwnd = hwnd; | |
1753 msg.message = message; | |
1754 msg.wParam = wParam; | |
1755 msg.lParam = lParam; | |
1756 msg.time = GetMessageTime(); | |
1757 msg.pt = pnt; | |
1758 | |
1759 /* GetKeyboardState() does not work as documented on Win95. We have | |
1760 * to loosely track Left and Right modifiers on behalf of the OS, | |
1761 * without screwing up Windows NT which tracks them properly. */ | |
1762 if (wParam == VK_CONTROL) | |
1763 keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; | |
1764 else if (wParam == VK_MENU) | |
1765 keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80; | |
1766 | |
1767 memcpy (keymap_orig, keymap, 256); | |
1768 | |
1769 /* Remove shift modifier from an ascii character */ | |
1770 mods &= ~MOD_SHIFT; | |
1771 | |
1772 /* Clear control and alt modifiers unless AltGr is pressed */ | |
1773 keymap [VK_RCONTROL] = 0; | |
1774 keymap [VK_LMENU] = 0; | |
1775 if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) | |
1776 || !(keymap [VK_RMENU] & 0x80)) | |
1777 { | 1890 { |
1778 keymap [VK_LCONTROL] = 0; | 1891 msframe->button2_need_rbutton = 0; |
1779 keymap [VK_CONTROL] = 0; | 1892 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, |
1780 keymap [VK_RMENU] = 0; | 1893 MAKEPOINTS (lParam), GetMessageTime()); |
1781 keymap [VK_MENU] = 0; | |
1782 } | 1894 } |
1783 SetKeyboardState (keymap); | 1895 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP, |
1784 | 1896 MAKEPOINTS (lParam), GetMessageTime()); |
1785 /* Maybe generate some WM_[SYS]CHARs in the queue */ | 1897 } |
1786 TranslateMessage (&msg); | 1898 break; |
1787 | 1899 |
1788 while (PeekMessage (&msg, hwnd, WM_CHAR, WM_CHAR, PM_REMOVE) | 1900 case WM_RBUTTONUP: |
1789 || PeekMessage (&msg, hwnd, WM_SYSCHAR, WM_SYSCHAR, PM_REMOVE)) | 1901 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
1902 msframe->last_click_time = GetMessageTime(); | |
1903 | |
1904 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1905 msframe->button2_need_rbutton = 0; | |
1906 if (msframe->ignore_next_rbutton_up) | |
1907 { | |
1908 msframe->ignore_next_rbutton_up = 0; | |
1909 } | |
1910 else if (msframe->button2_is_down) | |
1911 { | |
1912 msframe->button2_is_down = 0; | |
1913 msframe->ignore_next_lbutton_up = 1; | |
1914 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, | |
1915 MAKEPOINTS (lParam), GetMessageTime()); | |
1916 } | |
1917 else | |
1918 { | |
1919 if (msframe->button2_need_lbutton) | |
1790 { | 1920 { |
1791 int mods1 = mods; | 1921 msframe->button2_need_lbutton = 0; |
1792 WPARAM ch = msg.wParam; | 1922 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, |
1793 | 1923 MAKEPOINTS (lParam), GetMessageTime()); |
1794 /* If a quit char with no modifiers other than control and | 1924 } |
1795 shift, then mark it with a fake modifier, which is removed | 1925 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP, |
1796 upon dequeueing the event */ | 1926 MAKEPOINTS (lParam), GetMessageTime()); |
1797 /* #### This might also not withstand localization, if | 1927 } |
1798 quit character is not a latin-1 symbol */ | |
1799 if (((quit_ch < ' ' && (mods & MOD_CONTROL) && quit_ch + 'a' - 1 == ch) | |
1800 || (quit_ch >= ' ' && !(mods & MOD_CONTROL) && quit_ch == ch)) | |
1801 && ((mods & ~(MOD_CONTROL | MOD_SHIFT)) == 0)) | |
1802 { | |
1803 mods1 |= FAKE_MOD_QUIT; | |
1804 ++mswindows_quit_chars_count; | |
1805 } | |
1806 | |
1807 mswindows_enqueue_keypress_event (hwnd, make_char(ch), mods1); | |
1808 } /* while */ | |
1809 SetKeyboardState (keymap_orig); | |
1810 } /* else */ | |
1811 } | |
1812 if (key_needs_default_processing_p (wParam)) | |
1813 goto defproc; | |
1814 else | |
1815 break; | 1928 break; |
1816 | 1929 |
1817 case WM_MBUTTONDOWN: | 1930 case WM_LBUTTONDOWN: |
1818 case WM_MBUTTONUP: | 1931 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); |
1819 /* Real middle mouse button has nothing to do with emulated one: | 1932 |
1820 if one wants to exercise fingers playing chords on the mouse, | 1933 if (msframe->button2_need_lbutton) |
1821 he is allowed to do that! */ | |
1822 mswindows_enqueue_mouse_button_event (hwnd, message, | |
1823 MAKEPOINTS (lParam), GetMessageTime()); | |
1824 break; | |
1825 | |
1826 case WM_LBUTTONUP: | |
1827 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1828 msframe->last_click_time = GetMessageTime(); | |
1829 | |
1830 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1831 msframe->button2_need_lbutton = 0; | |
1832 if (msframe->ignore_next_lbutton_up) | |
1833 { | |
1834 msframe->ignore_next_lbutton_up = 0; | |
1835 } | |
1836 else if (msframe->button2_is_down) | |
1837 { | |
1838 msframe->button2_is_down = 0; | |
1839 msframe->ignore_next_rbutton_up = 1; | |
1840 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, | |
1841 MAKEPOINTS (lParam), GetMessageTime()); | |
1842 } | |
1843 else | |
1844 { | |
1845 if (msframe->button2_need_rbutton) | |
1846 { | |
1847 msframe->button2_need_rbutton = 0; | |
1848 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
1849 MAKEPOINTS (lParam), GetMessageTime()); | |
1850 } | |
1851 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONUP, | |
1852 MAKEPOINTS (lParam), GetMessageTime()); | |
1853 } | |
1854 break; | |
1855 | |
1856 case WM_RBUTTONUP: | |
1857 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1858 msframe->last_click_time = GetMessageTime(); | |
1859 | |
1860 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1861 msframe->button2_need_rbutton = 0; | |
1862 if (msframe->ignore_next_rbutton_up) | |
1863 { | |
1864 msframe->ignore_next_rbutton_up = 0; | |
1865 } | |
1866 else if (msframe->button2_is_down) | |
1867 { | |
1868 msframe->button2_is_down = 0; | |
1869 msframe->ignore_next_lbutton_up = 1; | |
1870 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONUP, | |
1871 MAKEPOINTS (lParam), GetMessageTime()); | |
1872 } | |
1873 else | |
1874 { | |
1875 if (msframe->button2_need_lbutton) | |
1876 { | |
1877 msframe->button2_need_lbutton = 0; | |
1878 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
1879 MAKEPOINTS (lParam), GetMessageTime()); | |
1880 } | |
1881 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONUP, | |
1882 MAKEPOINTS (lParam), GetMessageTime()); | |
1883 } | |
1884 break; | |
1885 | |
1886 case WM_LBUTTONDOWN: | |
1887 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1888 | |
1889 if (msframe->button2_need_lbutton) | |
1890 { | |
1891 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1892 msframe->button2_need_lbutton = 0; | |
1893 msframe->button2_need_rbutton = 0; | |
1894 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) | |
1895 { | |
1896 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, | |
1897 MAKEPOINTS (lParam), GetMessageTime()); | |
1898 msframe->button2_is_down = 1; | |
1899 } | |
1900 else | |
1901 { | |
1902 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
1903 msframe->last_click_point, msframe->last_click_time); | |
1904 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
1905 MAKEPOINTS (lParam), GetMessageTime()); | |
1906 } | |
1907 } | |
1908 else | |
1909 { | |
1910 mswindows_set_chord_timer (hwnd); | |
1911 msframe->button2_need_rbutton = 1; | |
1912 msframe->last_click_point = MAKEPOINTS (lParam); | |
1913 } | |
1914 msframe->last_click_time = GetMessageTime(); | |
1915 break; | |
1916 | |
1917 case WM_RBUTTONDOWN: | |
1918 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1919 | |
1920 if (msframe->button2_need_rbutton) | |
1921 { | |
1922 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1923 msframe->button2_need_lbutton = 0; | |
1924 msframe->button2_need_rbutton = 0; | |
1925 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) | |
1926 { | |
1927 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, | |
1928 MAKEPOINTS (lParam), GetMessageTime()); | |
1929 msframe->button2_is_down = 1; | |
1930 } | |
1931 else | |
1932 { | |
1933 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
1934 msframe->last_click_point, msframe->last_click_time); | |
1935 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
1936 MAKEPOINTS (lParam), GetMessageTime()); | |
1937 } | |
1938 } | |
1939 else | |
1940 { | |
1941 mswindows_set_chord_timer (hwnd); | |
1942 msframe->button2_need_lbutton = 1; | |
1943 msframe->last_click_point = MAKEPOINTS (lParam); | |
1944 } | |
1945 msframe->last_click_time = GetMessageTime(); | |
1946 break; | |
1947 | |
1948 case WM_TIMER: | |
1949 if (wParam == BUTTON_2_TIMER_ID) | |
1950 { | |
1951 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1952 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1953 | |
1954 if (msframe->button2_need_lbutton) | |
1955 { | |
1956 msframe->button2_need_lbutton = 0; | |
1957 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
1958 msframe->last_click_point, msframe->last_click_time); | |
1959 } | |
1960 else if (msframe->button2_need_rbutton) | |
1961 { | |
1962 msframe->button2_need_rbutton = 0; | |
1963 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
1964 msframe->last_click_point, msframe->last_click_time); | |
1965 } | |
1966 } | |
1967 else | |
1968 assert ("Spurious timer fired" == 0); | |
1969 break; | |
1970 | |
1971 case WM_MOUSEMOVE: | |
1972 /* Optimization: don't report mouse movement while size is changing */ | |
1973 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1974 if (!msframe->sizing) | |
1975 { | |
1976 /* When waiting for the second mouse button to finish | |
1977 button2 emulation, and have moved too far, just pretend | |
1978 as if timer has expired. This improves drag-select feedback */ | |
1979 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton) | |
1980 && !mswindows_button2_near_enough (msframe->last_click_point, | |
1981 MAKEPOINTS (lParam))) | |
1982 { | 1934 { |
1983 KillTimer (hwnd, BUTTON_2_TIMER_ID); | 1935 KillTimer (hwnd, BUTTON_2_TIMER_ID); |
1984 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); | 1936 msframe->button2_need_lbutton = 0; |
1985 } | 1937 msframe->button2_need_rbutton = 0; |
1986 | 1938 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) |
1987 emacs_event = Fmake_event (Qnil, Qnil); | |
1988 event = XEVENT(emacs_event); | |
1989 | |
1990 event->channel = mswindows_find_frame(hwnd); | |
1991 event->timestamp = GetMessageTime(); | |
1992 event->event_type = pointer_motion_event; | |
1993 event->event.motion.x = MAKEPOINTS(lParam).x; | |
1994 event->event.motion.y = MAKEPOINTS(lParam).y; | |
1995 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0); | |
1996 | |
1997 mswindows_enqueue_dispatch_event (emacs_event); | |
1998 } | |
1999 break; | |
2000 | |
2001 case WM_CANCELMODE: | |
2002 ReleaseCapture (); | |
2003 /* Queue a `cancel-mode-internal' misc user event, so mouse | |
2004 selection would be canceled if any */ | |
2005 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd), | |
2006 Qcancel_mode_internal, Qnil); | |
2007 break; | |
2008 | |
2009 case WM_NOTIFY: | |
2010 { | |
2011 LPNMHDR nmhdr = (LPNMHDR)lParam; | |
2012 | |
2013 if (nmhdr->code == TTN_NEEDTEXT) | |
2014 { | |
2015 #ifdef HAVE_TOOLBARS | |
2016 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam; | |
2017 Lisp_Object btext; | |
2018 | |
2019 /* find out which toolbar */ | |
2020 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2021 btext = mswindows_get_toolbar_button_text ( frame, | |
2022 nmhdr->idFrom ); | |
2023 | |
2024 tttext->lpszText = NULL; | |
2025 tttext->hinst = NULL; | |
2026 | |
2027 if (!NILP(btext)) | |
2028 { | 1939 { |
2029 /* I think this is safe since the text will only go away | 1940 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, |
2030 when the toolbar does...*/ | 1941 MAKEPOINTS (lParam), GetMessageTime()); |
2031 TO_EXTERNAL_FORMAT (LISP_STRING, btext, | 1942 msframe->button2_is_down = 1; |
2032 C_STRING_ALLOCA, tttext->lpszText, | |
2033 Qnative); | |
2034 } | |
2035 #endif | |
2036 } | |
2037 /* handle tree view callbacks */ | |
2038 else if (nmhdr->code == TVN_SELCHANGED) | |
2039 { | |
2040 NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam; | |
2041 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2042 mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam); | |
2043 } | |
2044 /* handle tab control callbacks */ | |
2045 else if (nmhdr->code == TCN_SELCHANGE) | |
2046 { | |
2047 TC_ITEM item; | |
2048 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0); | |
2049 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2050 | |
2051 item.mask = TCIF_PARAM; | |
2052 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx, | |
2053 (LPARAM)&item); | |
2054 | |
2055 mswindows_handle_gui_wm_command (frame, 0, item.lParam); | |
2056 } | |
2057 } | |
2058 break; | |
2059 | |
2060 case WM_PAINT: | |
2061 /* hdc will be NULL unless this is a subwindow - in which case we | |
2062 shouldn't have received a paint message for it here. */ | |
2063 assert (wParam == 0); | |
2064 | |
2065 /* Can't queue a magic event because windows goes modal and sends paint | |
2066 messages directly to the windows procedure when doing solid drags | |
2067 and the message queue doesn't get processed. */ | |
2068 mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd))); | |
2069 break; | |
2070 | |
2071 case WM_SIZE: | |
2072 /* We only care about this message if our size has really changed */ | |
2073 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED) | |
2074 { | |
2075 RECT rect; | |
2076 int columns, rows; | |
2077 | |
2078 fobj = mswindows_find_frame (hwnd); | |
2079 frame = XFRAME (fobj); | |
2080 msframe = FRAME_MSWINDOWS_DATA (frame); | |
2081 | |
2082 /* We cannot handle frame map and unmap hooks right in | |
2083 this routine, because these may throw. We queue | |
2084 magic events to run these hooks instead - kkm */ | |
2085 | |
2086 if (wParam==SIZE_MINIMIZED) | |
2087 { | |
2088 /* Iconified */ | |
2089 FRAME_VISIBLE_P (frame) = 0; | |
2090 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME); | |
2091 } | |
2092 else | |
2093 { | |
2094 GetClientRect(hwnd, &rect); | |
2095 FRAME_PIXWIDTH(frame) = rect.right; | |
2096 FRAME_PIXHEIGHT(frame) = rect.bottom; | |
2097 | |
2098 pixel_to_real_char_size (frame, rect.right, rect.bottom, | |
2099 &FRAME_MSWINDOWS_CHARWIDTH (frame), | |
2100 &FRAME_MSWINDOWS_CHARHEIGHT (frame)); | |
2101 | |
2102 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows); | |
2103 change_frame_size (frame, rows, columns, 1); | |
2104 | |
2105 /* If we are inside frame creation, we have to apply geometric | |
2106 properties now. */ | |
2107 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | |
2108 { | |
2109 /* Yes, we have to size again */ | |
2110 mswindows_size_frame_internal ( frame, | |
2111 FRAME_MSWINDOWS_TARGET_RECT | |
2112 (frame)); | |
2113 /* Reset so we do not get here again. The SetWindowPos call in | |
2114 * mswindows_size_frame_internal can cause recursion here. */ | |
2115 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | |
2116 { | |
2117 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame)); | |
2118 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0; | |
2119 } | |
2120 } | 1943 } |
2121 else | 1944 else |
2122 { | 1945 { |
2123 if (!msframe->sizing && !FRAME_VISIBLE_P (frame)) | 1946 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, |
2124 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME); | 1947 msframe->last_click_point, msframe->last_click_time); |
2125 FRAME_VISIBLE_P (frame) = 1; | 1948 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, |
2126 | 1949 MAKEPOINTS (lParam), GetMessageTime()); |
2127 if (!msframe->sizing || mswindows_dynamic_frame_resize) | |
2128 redisplay (); | |
2129 } | 1950 } |
2130 } | 1951 } |
1952 else | |
1953 { | |
1954 mswindows_set_chord_timer (hwnd); | |
1955 msframe->button2_need_rbutton = 1; | |
1956 msframe->last_click_point = MAKEPOINTS (lParam); | |
1957 } | |
1958 msframe->last_click_time = GetMessageTime(); | |
1959 break; | |
1960 | |
1961 case WM_RBUTTONDOWN: | |
1962 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1963 | |
1964 if (msframe->button2_need_rbutton) | |
1965 { | |
1966 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1967 msframe->button2_need_lbutton = 0; | |
1968 msframe->button2_need_rbutton = 0; | |
1969 if (mswindows_button2_near_enough (msframe->last_click_point, MAKEPOINTS (lParam))) | |
1970 { | |
1971 mswindows_enqueue_mouse_button_event (hwnd, WM_MBUTTONDOWN, | |
1972 MAKEPOINTS (lParam), GetMessageTime()); | |
1973 msframe->button2_is_down = 1; | |
1974 } | |
1975 else | |
1976 { | |
1977 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
1978 msframe->last_click_point, msframe->last_click_time); | |
1979 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
1980 MAKEPOINTS (lParam), GetMessageTime()); | |
1981 } | |
1982 } | |
1983 else | |
1984 { | |
1985 mswindows_set_chord_timer (hwnd); | |
1986 msframe->button2_need_lbutton = 1; | |
1987 msframe->last_click_point = MAKEPOINTS (lParam); | |
1988 } | |
1989 msframe->last_click_time = GetMessageTime(); | |
1990 break; | |
1991 | |
1992 case WM_TIMER: | |
1993 if (wParam == BUTTON_2_TIMER_ID) | |
1994 { | |
1995 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
1996 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
1997 | |
1998 if (msframe->button2_need_lbutton) | |
1999 { | |
2000 msframe->button2_need_lbutton = 0; | |
2001 mswindows_enqueue_mouse_button_event (hwnd, WM_RBUTTONDOWN, | |
2002 msframe->last_click_point, msframe->last_click_time); | |
2003 } | |
2004 else if (msframe->button2_need_rbutton) | |
2005 { | |
2006 msframe->button2_need_rbutton = 0; | |
2007 mswindows_enqueue_mouse_button_event (hwnd, WM_LBUTTONDOWN, | |
2008 msframe->last_click_point, msframe->last_click_time); | |
2009 } | |
2010 } | |
2011 else | |
2012 assert ("Spurious timer fired" == 0); | |
2013 break; | |
2014 | |
2015 case WM_MOUSEMOVE: | |
2016 /* Optimization: don't report mouse movement while size is changing */ | |
2017 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2018 if (!msframe->sizing) | |
2019 { | |
2020 /* When waiting for the second mouse button to finish | |
2021 button2 emulation, and have moved too far, just pretend | |
2022 as if timer has expired. This improves drag-select feedback */ | |
2023 if ((msframe->button2_need_lbutton || msframe->button2_need_rbutton) | |
2024 && !mswindows_button2_near_enough (msframe->last_click_point, | |
2025 MAKEPOINTS (lParam))) | |
2026 { | |
2027 KillTimer (hwnd, BUTTON_2_TIMER_ID); | |
2028 SendMessage (hwnd, WM_TIMER, BUTTON_2_TIMER_ID, 0); | |
2029 } | |
2030 | |
2031 emacs_event = Fmake_event (Qnil, Qnil); | |
2032 event = XEVENT(emacs_event); | |
2033 | |
2034 event->channel = mswindows_find_frame(hwnd); | |
2035 event->timestamp = GetMessageTime(); | |
2036 event->event_type = pointer_motion_event; | |
2037 event->event.motion.x = MAKEPOINTS(lParam).x; | |
2038 event->event.motion.y = MAKEPOINTS(lParam).y; | |
2039 event->event.motion.modifiers = mswindows_modifier_state (NULL, 0); | |
2040 | |
2041 mswindows_enqueue_dispatch_event (emacs_event); | |
2042 } | |
2043 break; | |
2044 | |
2045 case WM_CANCELMODE: | |
2046 ReleaseCapture (); | |
2047 /* Queue a `cancel-mode-internal' misc user event, so mouse | |
2048 selection would be canceled if any */ | |
2049 mswindows_enqueue_misc_user_event (mswindows_find_frame (hwnd), | |
2050 Qcancel_mode_internal, Qnil); | |
2051 break; | |
2052 | |
2053 case WM_NOTIFY: | |
2054 { | |
2055 LPNMHDR nmhdr = (LPNMHDR)lParam; | |
2056 | |
2057 if (nmhdr->code == TTN_NEEDTEXT) | |
2058 { | |
2059 #ifdef HAVE_TOOLBARS | |
2060 LPTOOLTIPTEXT tttext = (LPTOOLTIPTEXT)lParam; | |
2061 Lisp_Object btext; | |
2062 | |
2063 /* find out which toolbar */ | |
2064 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2065 btext = mswindows_get_toolbar_button_text ( frame, | |
2066 nmhdr->idFrom ); | |
2067 | |
2068 tttext->lpszText = NULL; | |
2069 tttext->hinst = NULL; | |
2070 | |
2071 if (!NILP(btext)) | |
2072 { | |
2073 /* I think this is safe since the text will only go away | |
2074 when the toolbar does...*/ | |
2075 TO_EXTERNAL_FORMAT (LISP_STRING, btext, | |
2076 C_STRING_ALLOCA, tttext->lpszText, | |
2077 Qnative); | |
2078 } | |
2079 #endif | |
2080 } | |
2081 /* handle tree view callbacks */ | |
2082 else if (nmhdr->code == TVN_SELCHANGED) | |
2083 { | |
2084 NM_TREEVIEW* ptree = (NM_TREEVIEW*)lParam; | |
2085 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2086 mswindows_handle_gui_wm_command (frame, 0, ptree->itemNew.lParam); | |
2087 } | |
2088 /* handle tab control callbacks */ | |
2089 else if (nmhdr->code == TCN_SELCHANGE) | |
2090 { | |
2091 TC_ITEM item; | |
2092 int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0); | |
2093 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2094 | |
2095 item.mask = TCIF_PARAM; | |
2096 SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx, | |
2097 (LPARAM)&item); | |
2098 | |
2099 mswindows_handle_gui_wm_command (frame, 0, item.lParam); | |
2100 } | |
2101 } | |
2102 break; | |
2103 | |
2104 case WM_PAINT: | |
2105 /* hdc will be NULL unless this is a subwindow - in which case we | |
2106 shouldn't have received a paint message for it here. */ | |
2107 assert (wParam == 0); | |
2108 | |
2109 /* Can't queue a magic event because windows goes modal and sends paint | |
2110 messages directly to the windows procedure when doing solid drags | |
2111 and the message queue doesn't get processed. */ | |
2112 mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd))); | |
2113 break; | |
2114 | |
2115 case WM_SIZE: | |
2116 /* We only care about this message if our size has really changed */ | |
2117 if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED) | |
2118 { | |
2119 RECT rect; | |
2120 int columns, rows; | |
2121 | |
2122 fobj = mswindows_find_frame (hwnd); | |
2123 frame = XFRAME (fobj); | |
2124 msframe = FRAME_MSWINDOWS_DATA (frame); | |
2125 | |
2126 /* We cannot handle frame map and unmap hooks right in | |
2127 this routine, because these may throw. We queue | |
2128 magic events to run these hooks instead - kkm */ | |
2129 | |
2130 if (wParam==SIZE_MINIMIZED) | |
2131 { | |
2132 /* Iconified */ | |
2133 FRAME_VISIBLE_P (frame) = 0; | |
2134 mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME); | |
2135 } | |
2136 else | |
2137 { | |
2138 GetClientRect(hwnd, &rect); | |
2139 FRAME_PIXWIDTH(frame) = rect.right; | |
2140 FRAME_PIXHEIGHT(frame) = rect.bottom; | |
2141 | |
2142 pixel_to_real_char_size (frame, rect.right, rect.bottom, | |
2143 &FRAME_MSWINDOWS_CHARWIDTH (frame), | |
2144 &FRAME_MSWINDOWS_CHARHEIGHT (frame)); | |
2145 | |
2146 pixel_to_char_size (frame, rect.right, rect.bottom, &columns, &rows); | |
2147 change_frame_size (frame, rows, columns, 1); | |
2148 | |
2149 /* If we are inside frame creation, we have to apply geometric | |
2150 properties now. */ | |
2151 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | |
2152 { | |
2153 /* Yes, we have to size again */ | |
2154 mswindows_size_frame_internal ( frame, | |
2155 FRAME_MSWINDOWS_TARGET_RECT | |
2156 (frame)); | |
2157 /* Reset so we do not get here again. The SetWindowPos call in | |
2158 * mswindows_size_frame_internal can cause recursion here. */ | |
2159 if (FRAME_MSWINDOWS_TARGET_RECT (frame)) | |
2160 { | |
2161 xfree (FRAME_MSWINDOWS_TARGET_RECT (frame)); | |
2162 FRAME_MSWINDOWS_TARGET_RECT (frame) = 0; | |
2163 } | |
2164 } | |
2165 else | |
2166 { | |
2167 if (!msframe->sizing && !FRAME_VISIBLE_P (frame)) | |
2168 mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME); | |
2169 FRAME_VISIBLE_P (frame) = 1; | |
2170 | |
2171 if (!msframe->sizing || mswindows_dynamic_frame_resize) | |
2172 redisplay (); | |
2173 } | |
2174 } | |
2175 } | |
2176 break; | |
2177 | |
2178 case WM_DISPLAYCHANGE: | |
2179 { | |
2180 struct device *d; | |
2181 | |
2182 fobj = mswindows_find_frame (hwnd); | |
2183 frame = XFRAME (fobj); | |
2184 d = XDEVICE (FRAME_DEVICE (frame)); | |
2185 | |
2186 DEVICE_MSWINDOWS_HORZRES(d) = LOWORD (lParam); | |
2187 DEVICE_MSWINDOWS_VERTRES(d) = HIWORD (lParam); | |
2188 DEVICE_MSWINDOWS_BITSPIXEL(d) = wParam; | |
2189 break; | |
2190 } | |
2191 | |
2192 /* Misc magic events which only require that the frame be identified */ | |
2193 case WM_SETFOCUS: | |
2194 case WM_KILLFOCUS: | |
2195 mswindows_enqueue_magic_event (hwnd, message); | |
2196 break; | |
2197 | |
2198 case WM_WINDOWPOSCHANGING: | |
2199 { | |
2200 WINDOWPOS *wp = (LPWINDOWPOS) lParam; | |
2201 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) }; | |
2202 GetWindowPlacement(hwnd, &wpl); | |
2203 | |
2204 /* Only interested if size is changing and we're not being iconified */ | |
2205 if (wpl.showCmd != SW_SHOWMINIMIZED | |
2206 && wpl.showCmd != SW_SHOWMAXIMIZED | |
2207 && !(wp->flags & SWP_NOSIZE)) | |
2208 { | |
2209 RECT ncsize = { 0, 0, 0, 0 }; | |
2210 int pixwidth, pixheight; | |
2211 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE), | |
2212 GetMenu(hwnd) != NULL, | |
2213 GetWindowLong (hwnd, GWL_EXSTYLE)); | |
2214 | |
2215 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)), | |
2216 wp->cx - (ncsize.right - ncsize.left), | |
2217 wp->cy - (ncsize.bottom - ncsize.top), | |
2218 &pixwidth, &pixheight); | |
2219 | |
2220 /* Convert client sizes to window sizes */ | |
2221 pixwidth += (ncsize.right - ncsize.left); | |
2222 pixheight += (ncsize.bottom - ncsize.top); | |
2223 | |
2224 if (wpl.showCmd != SW_SHOWMAXIMIZED) | |
2225 { | |
2226 /* Adjust so that the bottom or right doesn't move if it's | |
2227 * the top or left that's being changed */ | |
2228 RECT rect; | |
2229 GetWindowRect (hwnd, &rect); | |
2230 | |
2231 if (rect.left != wp->x) | |
2232 wp->x += wp->cx - pixwidth; | |
2233 if (rect.top != wp->y) | |
2234 wp->y += wp->cy - pixheight; | |
2235 } | |
2236 | |
2237 wp->cx = pixwidth; | |
2238 wp->cy = pixheight; | |
2239 } | |
2240 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts | |
2241 window position if the user tries to track window too small */ | |
2242 } | |
2243 goto defproc; | |
2244 | |
2245 case WM_ENTERSIZEMOVE: | |
2246 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2247 msframe->sizing = 1; | |
2248 return 0; | |
2249 | |
2250 case WM_EXITSIZEMOVE: | |
2251 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2252 msframe->sizing = 0; | |
2253 /* Queue noop event */ | |
2254 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | |
2255 return 0; | |
2256 | |
2257 #ifdef HAVE_SCROLLBARS | |
2258 case WM_VSCROLL: | |
2259 case WM_HSCROLL: | |
2260 { | |
2261 /* Direction of scroll is determined by scrollbar instance. */ | |
2262 int code = (int) LOWORD(wParam); | |
2263 int pos = (short int) HIWORD(wParam); | |
2264 HWND hwndScrollBar = (HWND) lParam; | |
2265 struct gcpro gcpro1, gcpro2; | |
2266 | |
2267 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos); | |
2268 GCPRO2 (emacs_event, fobj); | |
2269 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */ | |
2270 { | |
2271 /* Error during event pumping - cancel scroll */ | |
2272 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0); | |
2273 } | |
2274 UNGCPRO; | |
2275 break; | |
2276 } | |
2277 | |
2278 case WM_MOUSEWHEEL: | |
2279 { | |
2280 int keys = LOWORD (wParam); /* Modifier key flags */ | |
2281 int delta = (short) HIWORD (wParam); /* Wheel rotation amount */ | |
2282 struct gcpro gcpro1, gcpro2; | |
2283 | |
2284 if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta)) | |
2285 { | |
2286 GCPRO2 (emacs_event, fobj); | |
2287 mswindows_pump_outstanding_events (); /* Can GC */ | |
2288 UNGCPRO; | |
2289 } | |
2290 else | |
2291 goto defproc; | |
2292 break; | |
2293 } | |
2294 #endif | |
2295 | |
2296 #ifdef HAVE_MENUBARS | |
2297 case WM_INITMENU: | |
2298 if (UNBOUNDP (mswindows_handle_wm_initmenu ( | |
2299 (HMENU) wParam, | |
2300 XFRAME (mswindows_find_frame (hwnd))))) | |
2301 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | |
2302 break; | |
2303 | |
2304 case WM_INITMENUPOPUP: | |
2305 if (!HIWORD(lParam)) | |
2306 { | |
2307 if (UNBOUNDP (mswindows_handle_wm_initmenupopup ( | |
2308 (HMENU) wParam, | |
2309 XFRAME (mswindows_find_frame (hwnd))))) | |
2310 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | |
2311 } | |
2312 break; | |
2313 | |
2314 #endif /* HAVE_MENUBARS */ | |
2315 | |
2316 case WM_COMMAND: | |
2317 { | |
2318 WORD id = LOWORD (wParam); | |
2319 WORD nid = HIWORD (wParam); | |
2320 HWND cid = (HWND)lParam; | |
2321 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2322 | |
2323 #ifdef HAVE_TOOLBARS | |
2324 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id))) | |
2325 break; | |
2326 #endif | |
2327 /* widgets in a buffer only eval a callback for suitable events.*/ | |
2328 switch (nid) | |
2329 { | |
2330 case BN_CLICKED: | |
2331 case EN_CHANGE: | |
2332 case CBN_EDITCHANGE: | |
2333 case CBN_SELCHANGE: | |
2334 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id))) | |
2335 return 0; | |
2336 } | |
2337 /* menubars always must come last since the hashtables do not | |
2338 always exist*/ | |
2339 #ifdef HAVE_MENUBARS | |
2340 if (!NILP (mswindows_handle_wm_command (frame, id))) | |
2341 break; | |
2342 #endif | |
2343 | |
2344 return DefWindowProc (hwnd, message, wParam, lParam); | |
2345 /* Bite me - a spurious command. This used to not be able to | |
2346 happen but with the introduction of widgets its now | |
2347 possible. */ | |
2348 } | |
2349 break; | |
2350 | |
2351 case WM_CTLCOLORBTN: | |
2352 case WM_CTLCOLORLISTBOX: | |
2353 case WM_CTLCOLOREDIT: | |
2354 case WM_CTLCOLORSTATIC: | |
2355 case WM_CTLCOLORSCROLLBAR: | |
2356 { | |
2357 /* if we get an opportunity to paint a widget then do so if | |
2358 there is an appropriate face */ | |
2359 HWND crtlwnd = (HWND)lParam; | |
2360 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA); | |
2361 if (ii) | |
2362 { | |
2363 Lisp_Object image_instance; | |
2364 VOID_TO_LISP (image_instance, ii); | |
2365 if (IMAGE_INSTANCEP (image_instance) | |
2366 && | |
2367 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)) | |
2368 { | |
2369 /* set colors for the buttons */ | |
2370 HDC hdc = (HDC)wParam; | |
2371 if (last_widget_brushed != ii) | |
2372 { | |
2373 if (widget_brush) | |
2374 DeleteObject (widget_brush); | |
2375 widget_brush = CreateSolidBrush | |
2376 (COLOR_INSTANCE_MSWINDOWS_COLOR | |
2377 (XCOLOR_INSTANCE | |
2378 (FACE_BACKGROUND | |
2379 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2380 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2381 } | |
2382 last_widget_brushed = ii; | |
2383 SetTextColor | |
2384 (hdc, | |
2385 COLOR_INSTANCE_MSWINDOWS_COLOR | |
2386 (XCOLOR_INSTANCE | |
2387 (FACE_FOREGROUND | |
2388 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2389 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2390 SetBkMode (hdc, OPAQUE); | |
2391 SetBkColor | |
2392 (hdc, | |
2393 COLOR_INSTANCE_MSWINDOWS_COLOR | |
2394 (XCOLOR_INSTANCE | |
2395 (FACE_BACKGROUND | |
2396 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2397 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2398 return (LRESULT)widget_brush; | |
2399 } | |
2400 } | |
2401 } | |
2402 goto defproc; | |
2403 | |
2404 #ifdef HAVE_DRAGNDROP | |
2405 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */ | |
2406 { | |
2407 UINT filecount, i, len; | |
2408 POINT point; | |
2409 char* filename; | |
2410 char* fname; | |
2411 | |
2412 Lisp_Object l_dndlist = Qnil, l_item = Qnil; | |
2413 struct gcpro gcpro1, gcpro2, gcpro3; | |
2414 | |
2415 emacs_event = Fmake_event (Qnil, Qnil); | |
2416 event = XEVENT(emacs_event); | |
2417 | |
2418 GCPRO3 (emacs_event, l_dndlist, l_item); | |
2419 | |
2420 if (!DragQueryPoint ((HDROP) wParam, &point)) | |
2421 point.x = point.y = -1; /* outside client area */ | |
2422 | |
2423 event->event_type = misc_user_event; | |
2424 event->channel = mswindows_find_frame(hwnd); | |
2425 event->timestamp = GetMessageTime(); | |
2426 event->event.misc.button = 1; /* #### Should try harder */ | |
2427 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0); | |
2428 event->event.misc.x = point.x; | |
2429 event->event.misc.y = point.y; | |
2430 event->event.misc.function = Qdragdrop_drop_dispatch; | |
2431 | |
2432 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0); | |
2433 for (i=0; i<filecount; i++) | |
2434 { | |
2435 len = DragQueryFile ((HDROP) wParam, i, NULL, 0); | |
2436 /* The URLs that we make here aren't correct according to section | |
2437 * 3.10 of rfc1738 because they're missing the //<host>/ part and | |
2438 * because they may contain reserved characters. But that's OK - | |
2439 * they just need to be good enough to keep dragdrop.el happy. */ | |
2440 fname = (char *)xmalloc (len+1); | |
2441 DragQueryFile ((HANDLE) wParam, i, fname, len+1); | |
2442 | |
2443 /* May be a shell link aka "shortcut" - replace fname if so */ | |
2444 #if !(defined(__CYGWIN32__) || defined(__MINGW32__)) | |
2445 /* cygwin doesn't define this COM stuff */ | |
2446 if (!stricmp (fname + strlen (fname) - 4, ".LNK")) | |
2447 { | |
2448 IShellLink* psl; | |
2449 | |
2450 if (CoCreateInstance (&CLSID_ShellLink, NULL, | |
2451 CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl) == S_OK) | |
2452 { | |
2453 IPersistFile* ppf; | |
2454 | |
2455 if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile, | |
2456 &ppf) == S_OK) | |
2457 { | |
2458 WORD wsz[MAX_PATH]; | |
2459 WIN32_FIND_DATA wfd; | |
2460 LPSTR resolved = (char *) xmalloc (MAX_PATH+1); | |
2461 | |
2462 MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, MAX_PATH); | |
2463 | |
2464 if ((ppf->lpVtbl->Load (ppf, wsz, STGM_READ) == S_OK) && | |
2465 (psl->lpVtbl->GetPath (psl, resolved, MAX_PATH, | |
2466 &wfd, 0)==S_OK)) | |
2467 { | |
2468 xfree (fname); | |
2469 fname = resolved; | |
2470 len = strlen (fname); | |
2471 } | |
2472 | |
2473 ppf->lpVtbl->Release (ppf); | |
2474 } | |
2475 | |
2476 psl->lpVtbl->Release (psl); | |
2477 } | |
2478 } | |
2479 #endif | |
2480 | |
2481 #ifdef __CYGWIN32__ | |
2482 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5); | |
2483 strcpy (filename, "file:"); | |
2484 cygwin32_win32_to_posix_path_list (fname, filename+5); | |
2485 #else | |
2486 filename = (char *)xmalloc (len+6); | |
2487 strcat (strcpy (filename, "file:"), fname); | |
2488 dostounix_filename (filename+5); | |
2489 #endif | |
2490 xfree (fname); | |
2491 l_item = make_string (filename, strlen (filename)); | |
2492 l_dndlist = Fcons (l_item, l_dndlist); | |
2493 xfree (filename); | |
2494 } | |
2495 DragFinish ((HDROP) wParam); | |
2496 | |
2497 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist); | |
2498 mswindows_enqueue_dispatch_event (emacs_event); | |
2499 UNGCPRO; | |
2500 } | |
2501 break; | |
2502 #endif | |
2503 | |
2504 defproc: | |
2505 default: | |
2506 return DefWindowProc (hwnd, message, wParam, lParam); | |
2131 } | 2507 } |
2132 break; | |
2133 | |
2134 /* Misc magic events which only require that the frame be identified */ | |
2135 case WM_SETFOCUS: | |
2136 case WM_KILLFOCUS: | |
2137 mswindows_enqueue_magic_event (hwnd, message); | |
2138 break; | |
2139 | |
2140 case WM_WINDOWPOSCHANGING: | |
2141 { | |
2142 WINDOWPOS *wp = (LPWINDOWPOS) lParam; | |
2143 WINDOWPLACEMENT wpl = { sizeof(WINDOWPLACEMENT) }; | |
2144 GetWindowPlacement(hwnd, &wpl); | |
2145 | |
2146 /* Only interested if size is changing and we're not being iconified */ | |
2147 if (wpl.showCmd != SW_SHOWMINIMIZED | |
2148 && wpl.showCmd != SW_SHOWMAXIMIZED | |
2149 && !(wp->flags & SWP_NOSIZE)) | |
2150 { | |
2151 RECT ncsize = { 0, 0, 0, 0 }; | |
2152 int pixwidth, pixheight; | |
2153 AdjustWindowRectEx (&ncsize, GetWindowLong (hwnd, GWL_STYLE), | |
2154 GetMenu(hwnd) != NULL, | |
2155 GetWindowLong (hwnd, GWL_EXSTYLE)); | |
2156 | |
2157 round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)), | |
2158 wp->cx - (ncsize.right - ncsize.left), | |
2159 wp->cy - (ncsize.bottom - ncsize.top), | |
2160 &pixwidth, &pixheight); | |
2161 | |
2162 /* Convert client sizes to window sizes */ | |
2163 pixwidth += (ncsize.right - ncsize.left); | |
2164 pixheight += (ncsize.bottom - ncsize.top); | |
2165 | |
2166 if (wpl.showCmd != SW_SHOWMAXIMIZED) | |
2167 { | |
2168 /* Adjust so that the bottom or right doesn't move if it's | |
2169 * the top or left that's being changed */ | |
2170 RECT rect; | |
2171 GetWindowRect (hwnd, &rect); | |
2172 | |
2173 if (rect.left != wp->x) | |
2174 wp->x += wp->cx - pixwidth; | |
2175 if (rect.top != wp->y) | |
2176 wp->y += wp->cy - pixheight; | |
2177 } | |
2178 | |
2179 wp->cx = pixwidth; | |
2180 wp->cy = pixheight; | |
2181 } | |
2182 /* DefWindowProc sends useful WM_GETMINMAXINFO message, and adjusts | |
2183 window position if the user tries to track window too small */ | |
2184 } | |
2185 goto defproc; | |
2186 | |
2187 case WM_ENTERSIZEMOVE: | |
2188 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2189 msframe->sizing = 1; | |
2190 return 0; | |
2191 | |
2192 case WM_EXITSIZEMOVE: | |
2193 msframe = FRAME_MSWINDOWS_DATA (XFRAME (mswindows_find_frame (hwnd))); | |
2194 msframe->sizing = 0; | |
2195 /* Queue noop event */ | |
2196 mswindows_enqueue_magic_event (NULL, XM_BUMPQUEUE); | |
2197 return 0; | |
2198 | |
2199 #ifdef HAVE_SCROLLBARS | |
2200 case WM_VSCROLL: | |
2201 case WM_HSCROLL: | |
2202 { | |
2203 /* Direction of scroll is determined by scrollbar instance. */ | |
2204 int code = (int) LOWORD(wParam); | |
2205 int pos = (short int) HIWORD(wParam); | |
2206 HWND hwndScrollBar = (HWND) lParam; | |
2207 struct gcpro gcpro1, gcpro2; | |
2208 | |
2209 mswindows_handle_scrollbar_event (hwndScrollBar, code, pos); | |
2210 GCPRO2 (emacs_event, fobj); | |
2211 if (UNBOUNDP(mswindows_pump_outstanding_events())) /* Can GC */ | |
2212 { | |
2213 /* Error during event pumping - cancel scroll */ | |
2214 SendMessage (hwndScrollBar, WM_CANCELMODE, 0, 0); | |
2215 } | |
2216 UNGCPRO; | |
2217 break; | |
2218 } | |
2219 | |
2220 case WM_MOUSEWHEEL: | |
2221 { | |
2222 int keys = LOWORD (wParam); /* Modifier key flags */ | |
2223 int delta = (short) HIWORD (wParam); /* Wheel rotation amount */ | |
2224 struct gcpro gcpro1, gcpro2; | |
2225 | |
2226 if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta)) | |
2227 { | |
2228 GCPRO2 (emacs_event, fobj); | |
2229 mswindows_pump_outstanding_events (); /* Can GC */ | |
2230 UNGCPRO; | |
2231 } | |
2232 else | |
2233 goto defproc; | |
2234 break; | |
2235 } | |
2236 #endif | |
2237 | |
2238 #ifdef HAVE_MENUBARS | |
2239 case WM_INITMENU: | |
2240 if (UNBOUNDP (mswindows_handle_wm_initmenu ( | |
2241 (HMENU) wParam, | |
2242 XFRAME (mswindows_find_frame (hwnd))))) | |
2243 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | |
2244 break; | |
2245 | |
2246 case WM_INITMENUPOPUP: | |
2247 if (!HIWORD(lParam)) | |
2248 { | |
2249 if (UNBOUNDP (mswindows_handle_wm_initmenupopup ( | |
2250 (HMENU) wParam, | |
2251 XFRAME (mswindows_find_frame (hwnd))))) | |
2252 SendMessage (hwnd, WM_CANCELMODE, 0, 0); | |
2253 } | |
2254 break; | |
2255 | |
2256 #endif /* HAVE_MENUBARS */ | |
2257 | |
2258 case WM_COMMAND: | |
2259 { | |
2260 WORD id = LOWORD (wParam); | |
2261 WORD nid = HIWORD (wParam); | |
2262 HWND cid = (HWND)lParam; | |
2263 frame = XFRAME (mswindows_find_frame (hwnd)); | |
2264 | |
2265 #ifdef HAVE_TOOLBARS | |
2266 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id))) | |
2267 break; | |
2268 #endif | |
2269 /* widgets in a buffer only eval a callback for suitable events.*/ | |
2270 switch (nid) | |
2271 { | |
2272 case BN_CLICKED: | |
2273 case EN_CHANGE: | |
2274 case CBN_EDITCHANGE: | |
2275 case CBN_SELCHANGE: | |
2276 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id))) | |
2277 return 0; | |
2278 } | |
2279 /* menubars always must come last since the hashtables do not | |
2280 always exist*/ | |
2281 #ifdef HAVE_MENUBARS | |
2282 if (!NILP (mswindows_handle_wm_command (frame, id))) | |
2283 break; | |
2284 #endif | |
2285 | |
2286 return DefWindowProc (hwnd, message, wParam, lParam); | |
2287 /* Bite me - a spurious command. This used to not be able to | |
2288 happen but with the introduction of widgets its now | |
2289 possible. */ | |
2290 } | |
2291 break; | |
2292 | |
2293 case WM_CTLCOLORBTN: | |
2294 case WM_CTLCOLORLISTBOX: | |
2295 case WM_CTLCOLOREDIT: | |
2296 case WM_CTLCOLORSTATIC: | |
2297 case WM_CTLCOLORSCROLLBAR: | |
2298 { | |
2299 /* if we get an opportunity to paint a widget then do so if | |
2300 there is an appropriate face */ | |
2301 HWND crtlwnd = (HWND)lParam; | |
2302 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA); | |
2303 if (ii) | |
2304 { | |
2305 Lisp_Object image_instance; | |
2306 VOID_TO_LISP (image_instance, ii); | |
2307 if (IMAGE_INSTANCEP (image_instance) | |
2308 && | |
2309 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)) | |
2310 { | |
2311 /* set colors for the buttons */ | |
2312 HDC hdc = (HDC)wParam; | |
2313 if (last_widget_brushed != ii) | |
2314 { | |
2315 if (widget_brush) | |
2316 DeleteObject (widget_brush); | |
2317 widget_brush = CreateSolidBrush | |
2318 (COLOR_INSTANCE_MSWINDOWS_COLOR | |
2319 (XCOLOR_INSTANCE | |
2320 (FACE_BACKGROUND | |
2321 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2322 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2323 } | |
2324 last_widget_brushed = ii; | |
2325 SetTextColor | |
2326 (hdc, | |
2327 COLOR_INSTANCE_MSWINDOWS_COLOR | |
2328 (XCOLOR_INSTANCE | |
2329 (FACE_FOREGROUND | |
2330 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2331 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2332 SetBkMode (hdc, OPAQUE); | |
2333 SetBkColor | |
2334 (hdc, | |
2335 COLOR_INSTANCE_MSWINDOWS_COLOR | |
2336 (XCOLOR_INSTANCE | |
2337 (FACE_BACKGROUND | |
2338 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance), | |
2339 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance))))); | |
2340 return (LRESULT)widget_brush; | |
2341 } | |
2342 } | |
2343 } | |
2344 goto defproc; | |
2345 | |
2346 #ifdef HAVE_DRAGNDROP | |
2347 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */ | |
2348 { | |
2349 UINT filecount, i, len; | |
2350 POINT point; | |
2351 char* filename; | |
2352 #ifdef __CYGWIN32__ | |
2353 char* fname; | |
2354 #endif | |
2355 Lisp_Object l_dndlist = Qnil, l_item = Qnil; | |
2356 struct gcpro gcpro1, gcpro2, gcpro3; | |
2357 | |
2358 emacs_event = Fmake_event (Qnil, Qnil); | |
2359 event = XEVENT(emacs_event); | |
2360 | |
2361 GCPRO3 (emacs_event, l_dndlist, l_item); | |
2362 | |
2363 if (!DragQueryPoint ((HDROP) wParam, &point)) | |
2364 point.x = point.y = -1; /* outside client area */ | |
2365 | |
2366 event->event_type = misc_user_event; | |
2367 event->channel = mswindows_find_frame(hwnd); | |
2368 event->timestamp = GetMessageTime(); | |
2369 event->event.misc.button = 1; /* #### Should try harder */ | |
2370 event->event.misc.modifiers = mswindows_modifier_state (NULL, 0); | |
2371 event->event.misc.x = point.x; | |
2372 event->event.misc.y = point.y; | |
2373 event->event.misc.function = Qdragdrop_drop_dispatch; | |
2374 | |
2375 filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0); | |
2376 for (i=0; i<filecount; i++) | |
2377 { | |
2378 len = DragQueryFile ((HDROP) wParam, i, NULL, 0); | |
2379 /* The URLs that we make here aren't correct according to section | |
2380 * 3.10 of rfc1738 because they're missing the //<host>/ part and | |
2381 * because they may contain reserved characters. But that's OK. */ | |
2382 #ifdef __CYGWIN32__ | |
2383 fname = (char *)xmalloc (len+1); | |
2384 DragQueryFile ((HANDLE) wParam, i, fname, len+1); | |
2385 filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5); | |
2386 strcpy (filename, "file:"); | |
2387 cygwin32_win32_to_posix_path_list (fname, filename+5); | |
2388 xfree (fname); | |
2389 #else | |
2390 filename = (char *)xmalloc (len+6); | |
2391 strcpy (filename, "file:"); | |
2392 DragQueryFile ((HDROP) wParam, i, filename+5, len+1); | |
2393 dostounix_filename (filename+5); | |
2394 #endif | |
2395 l_item = make_string (filename, strlen (filename)); | |
2396 l_dndlist = Fcons (l_item, l_dndlist); | |
2397 xfree (filename); | |
2398 } | |
2399 DragFinish ((HDROP) wParam); | |
2400 | |
2401 event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist); | |
2402 mswindows_enqueue_dispatch_event (emacs_event); | |
2403 UNGCPRO; | |
2404 } | |
2405 break; | |
2406 #endif | |
2407 | |
2408 defproc: | |
2409 default: | |
2410 return DefWindowProc (hwnd, message, wParam, lParam); | |
2411 } | |
2412 return (0); | 2508 return (0); |
2413 } | 2509 } |
2414 | 2510 |
2415 | 2511 |
2416 /************************************************************************/ | 2512 /************************************************************************/ |
2485 has_AltGr = mswindows_current_layout_has_AltGr (); | 2581 has_AltGr = mswindows_current_layout_has_AltGr (); |
2486 } | 2582 } |
2487 | 2583 |
2488 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) | 2584 if (has_AltGr && (keymap [VK_LCONTROL] & 0x80) && (keymap [VK_RMENU] & 0x80)) |
2489 { | 2585 { |
2490 mods |= (keymap [VK_LMENU] & 0x80) ? MOD_META : 0; | 2586 mods |= (keymap [VK_LMENU] & 0x80) ? XEMACS_MOD_META : 0; |
2491 mods |= (keymap [VK_RCONTROL] & 0x80) ? MOD_CONTROL : 0; | 2587 mods |= (keymap [VK_RCONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0; |
2492 } | 2588 } |
2493 else | 2589 else |
2494 { | 2590 { |
2495 mods |= (keymap [VK_MENU] & 0x80) ? MOD_META : 0; | 2591 mods |= (keymap [VK_MENU] & 0x80) ? XEMACS_MOD_META : 0; |
2496 mods |= (keymap [VK_CONTROL] & 0x80) ? MOD_CONTROL : 0; | 2592 mods |= (keymap [VK_CONTROL] & 0x80) ? XEMACS_MOD_CONTROL : 0; |
2497 } | 2593 } |
2498 | 2594 |
2499 mods |= (keymap [VK_SHIFT] & 0x80) ? MOD_SHIFT : 0; | 2595 mods |= (keymap [VK_SHIFT] & 0x80) ? XEMACS_MOD_SHIFT : 0; |
2500 | 2596 |
2501 return mods; | 2597 return mods; |
2502 } | 2598 } |
2503 | 2599 |
2504 /* | 2600 /* |
2552 case VK_SNAPSHOT: return KEYSYM ("print"); | 2648 case VK_SNAPSHOT: return KEYSYM ("print"); |
2553 case VK_INSERT: return KEYSYM ("kp-insert"); | 2649 case VK_INSERT: return KEYSYM ("kp-insert"); |
2554 case VK_DELETE: return KEYSYM ("kp-delete"); | 2650 case VK_DELETE: return KEYSYM ("kp-delete"); |
2555 case VK_HELP: return KEYSYM ("help"); | 2651 case VK_HELP: return KEYSYM ("help"); |
2556 #if 0 /* FSF Emacs allows these to return configurable syms/mods */ | 2652 #if 0 /* FSF Emacs allows these to return configurable syms/mods */ |
2557 case VK_LWIN return KEYSYM (""); | 2653 case VK_LWIN return KEYSYM (""); |
2558 case VK_RWIN return KEYSYM (""); | 2654 case VK_RWIN return KEYSYM (""); |
2559 #endif | 2655 #endif |
2560 case VK_APPS: return KEYSYM ("menu"); | 2656 case VK_APPS: return KEYSYM ("menu"); |
2561 case VK_NUMPAD0: return KEYSYM ("kp-0"); | 2657 case VK_NUMPAD0: return KEYSYM ("kp-0"); |
2562 case VK_NUMPAD1: return KEYSYM ("kp-1"); | 2658 case VK_NUMPAD1: return KEYSYM ("kp-1"); |
2563 case VK_NUMPAD2: return KEYSYM ("kp-2"); | 2659 case VK_NUMPAD2: return KEYSYM ("kp-2"); |
2715 { | 2811 { |
2716 case XM_BUMPQUEUE: | 2812 case XM_BUMPQUEUE: |
2717 break; | 2813 break; |
2718 | 2814 |
2719 case WM_PAINT: | 2815 case WM_PAINT: |
2720 mswindows_handle_paint (XFRAME (EVENT_CHANNEL (emacs_event))); | 2816 { |
2817 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event)); | |
2818 mswindows_handle_paint (f); | |
2819 (FRAME_MSWINDOWS_DATA (f))->paint_pending = 0; | |
2820 } | |
2721 break; | 2821 break; |
2722 | 2822 |
2723 case WM_SETFOCUS: | 2823 case WM_SETFOCUS: |
2724 case WM_KILLFOCUS: | 2824 case WM_KILLFOCUS: |
2725 { | 2825 { |
2776 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) | 2876 #if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT) |
2777 return (network_connection_p (p) | 2877 return (network_connection_p (p) |
2778 ? get_winsock_stream_waitable (XLSTREAM (instr)) | 2878 ? get_winsock_stream_waitable (XLSTREAM (instr)) |
2779 : get_ntpipe_input_stream_waitable (XLSTREAM (instr))); | 2879 : get_ntpipe_input_stream_waitable (XLSTREAM (instr))); |
2780 #else | 2880 #else |
2781 return get_ntpipe_input_stream_waitable (XLSTREAM (instr)); | 2881 return get_ntpipe_input_stream_waitable (XLSTREAM (instr)); |
2782 #endif | 2882 #endif |
2783 } | 2883 } |
2784 | 2884 |
2785 static void | 2885 static void |
2786 emacs_mswindows_select_process (Lisp_Process *process) | 2886 emacs_mswindows_select_process (Lisp_Process *process) |
2864 while (mswindows_quit_chars_count-- > 0) | 2964 while (mswindows_quit_chars_count-- > 0) |
2865 { | 2965 { |
2866 emacs_event = mswindows_cancel_dispatch_event (&match_against); | 2966 emacs_event = mswindows_cancel_dispatch_event (&match_against); |
2867 assert (!NILP (emacs_event)); | 2967 assert (!NILP (emacs_event)); |
2868 | 2968 |
2869 if (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT) | 2969 if (XEVENT(emacs_event)->event.key.modifiers & XEMACS_MOD_SHIFT) |
2870 critical_p = 1; | 2970 critical_p = 1; |
2871 | 2971 |
2872 Fdeallocate_event(emacs_event); | 2972 Fdeallocate_event(emacs_event); |
2873 } | 2973 } |
2874 | 2974 |
2948 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream)))); | 3048 : HANDLE_TO_USID (get_ntpipe_input_stream_waitable (XLSTREAM (*instream)))); |
2949 } | 3049 } |
2950 | 3050 |
2951 USID | 3051 USID |
2952 emacs_mswindows_delete_stream_pair (Lisp_Object instream, | 3052 emacs_mswindows_delete_stream_pair (Lisp_Object instream, |
2953 Lisp_Object outstream) | 3053 Lisp_Object outstream) |
2954 { | 3054 { |
2955 /* Oh nothing special here for Win32 at all */ | 3055 /* Oh nothing special here for Win32 at all */ |
2956 #if defined (HAVE_UNIX_PROCESSES) | 3056 #if defined (HAVE_UNIX_PROCESSES) |
2957 int in = (NILP(instream) | 3057 int in = (NILP(instream) |
2958 ? -1 | 3058 ? -1 |
3010 mswindows_pending_timers_count = 0; | 3110 mswindows_pending_timers_count = 0; |
3011 | 3111 |
3012 mswindows_event_stream = xnew (struct event_stream); | 3112 mswindows_event_stream = xnew (struct event_stream); |
3013 | 3113 |
3014 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; | 3114 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; |
3115 mswindows_event_stream->force_event_pending = 0; | |
3015 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; | 3116 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; |
3016 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; | 3117 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; |
3017 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; | 3118 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; |
3018 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; | 3119 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; |
3019 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; | 3120 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; |
3050 pdump_wire (&mswindows_s_dispatch_event_queue_tail); | 3151 pdump_wire (&mswindows_s_dispatch_event_queue_tail); |
3051 | 3152 |
3052 mswindows_error_caught_in_modal_loop = Qnil; | 3153 mswindows_error_caught_in_modal_loop = Qnil; |
3053 staticpro (&mswindows_error_caught_in_modal_loop); | 3154 staticpro (&mswindows_error_caught_in_modal_loop); |
3054 | 3155 |
3055 DEFVAR_BOOL ("mswindows-meta-activates-menu", &mswindows_meta_activates_menu /* | 3156 DEFVAR_BOOL ("mswindows-alt-by-itself-activates-menu", |
3056 *Controls whether pressing and releasing the Meta (Alt) key should | 3157 &mswindows_alt_by_itself_activates_menu /* |
3057 activate the menubar. | 3158 *Controls whether pressing and releasing the Alt key activates the menubar. |
3159 This applies only if no intervening key was pressed. See also | |
3160 `menu-accelerator-enabled', which is probably the behavior you actually want. | |
3058 Default is t. | 3161 Default is t. |
3059 */ ); | 3162 */ ); |
3060 | 3163 |
3061 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /* | 3164 DEFVAR_BOOL ("mswindows-dynamic-frame-resize", |
3165 &mswindows_dynamic_frame_resize /* | |
3062 *Controls redrawing frame contents during mouse-drag or keyboard resize | 3166 *Controls redrawing frame contents during mouse-drag or keyboard resize |
3063 operation. When non-nil, the frame is redrawn while being resized. When | 3167 operation. When non-nil, the frame is redrawn while being resized. When |
3064 nil, frame is not redrawn, and exposed areas are filled with default | 3168 nil, frame is not redrawn, and exposed areas are filled with default |
3065 MDI application background color. Note that this option only has effect | 3169 MDI application background color. Note that this option only has effect |
3066 if "Show window contents while dragging" is on in system Display/Plus! | 3170 if "Show window contents while dragging" is on in system Display/Plus! |
3067 settings. | 3171 settings. |
3068 Default is t on fast machines, nil on slow. | 3172 Default is t on fast machines, nil on slow. |
3069 */ ); | 3173 */ ); |
3070 | 3174 |
3071 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */ | 3175 DEFVAR_INT ("mswindows-mouse-button-tolerance", |
3072 DEFVAR_INT ("mswindows-mouse-button-tolerance", &mswindows_mouse_button_tolerance /* | 3176 &mswindows_mouse_button_tolerance /* |
3073 *Analogue of double click interval for faking middle mouse events. | 3177 *Analogue of double click interval for faking middle mouse events. |
3074 The value is the minimum time in milliseconds that must elapse between | 3178 The value is the minimum time in milliseconds that must elapse between |
3075 left/right button down events before they are considered distinct events. | 3179 left/right button down events before they are considered distinct events. |
3076 If both mouse buttons are depressed within this interval, a middle mouse | 3180 If both mouse buttons are depressed within this interval, a middle mouse |
3077 button down event is generated instead. | 3181 button down event is generated instead. |
3078 If negative or zero, currently set system default is used instead. | 3182 If negative or zero, currently set system default is used instead. |
3079 */ ); | 3183 */ ); |
3080 | 3184 |
3081 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */ | |
3082 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /* | 3185 DEFVAR_INT ("mswindows-num-mouse-buttons", &mswindows_num_mouse_buttons /* |
3083 Number of physical mouse buttons. | 3186 Number of physical mouse buttons. |
3084 */ ); | 3187 */ ); |
3085 | 3188 |
3086 DEFVAR_INT ("mswindows-mouse-button-max-skew-x", &mswindows_mouse_button_max_skew_x /* | 3189 DEFVAR_INT ("mswindows-mouse-button-max-skew-x", |
3190 &mswindows_mouse_button_max_skew_x /* | |
3087 *Maximum horizontal distance in pixels between points in which left and | 3191 *Maximum horizontal distance in pixels between points in which left and |
3088 right button clicks occurred for them to be translated into single | 3192 right button clicks occurred for them to be translated into single |
3089 middle button event. Clicks must occur in time not longer than defined | 3193 middle button event. Clicks must occur in time not longer than defined |
3090 by the variable `mswindows-mouse-button-tolerance'. | 3194 by the variable `mswindows-mouse-button-tolerance'. |
3091 If negative or zero, currently set system default is used instead. | 3195 If negative or zero, currently set system default is used instead. |
3092 */ ); | 3196 */ ); |
3093 | 3197 |
3094 DEFVAR_INT ("mswindows-mouse-button-max-skew-y", &mswindows_mouse_button_max_skew_y /* | 3198 DEFVAR_INT ("mswindows-mouse-button-max-skew-y", |
3199 &mswindows_mouse_button_max_skew_y /* | |
3095 *Maximum vertical distance in pixels between points in which left and | 3200 *Maximum vertical distance in pixels between points in which left and |
3096 right button clicks occurred for them to be translated into single | 3201 right button clicks occurred for them to be translated into single |
3097 middle button event. Clicks must occur in time not longer than defined | 3202 middle button event. Clicks must occur in time not longer than defined |
3098 by the variable `mswindows-mouse-button-tolerance'. | 3203 by the variable `mswindows-mouse-button-tolerance'. |
3099 If negative or zero, currently set system default is used instead. | 3204 If negative or zero, currently set system default is used instead. |
3100 */ ); | 3205 */ ); |
3101 | 3206 |
3102 mswindows_mouse_button_max_skew_x = 0; | 3207 mswindows_mouse_button_max_skew_x = 0; |
3103 mswindows_mouse_button_max_skew_y = 0; | 3208 mswindows_mouse_button_max_skew_y = 0; |
3104 mswindows_mouse_button_tolerance = 0; | 3209 mswindows_mouse_button_tolerance = 0; |
3105 mswindows_meta_activates_menu = 1; | 3210 mswindows_alt_by_itself_activates_menu = 1; |
3106 } | 3211 } |
3107 | 3212 |
3108 void | 3213 void |
3109 syms_of_event_mswindows (void) | 3214 syms_of_event_mswindows (void) |
3110 { | 3215 { |