comparison src/event-msw.c @ 384:bbff43aa5eb7 r21-2-7

Import from CVS: tag r21-2-7
author cvs
date Mon, 13 Aug 2007 11:08:24 +0200
parents 064ab7fed2e0
children aabb7f5b1c81
comparison
equal deleted inserted replaced
383:6a50c6a581a5 384:bbff43aa5eb7
26 /* Authorship: 26 /* Authorship:
27 27
28 Ultimately based on FSF. 28 Ultimately based on FSF.
29 Rewritten by Ben Wing. 29 Rewritten by Ben Wing.
30 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0. 30 Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
31 Subprocess and modal loop support by Kirill M. Katsnelson.
31 */ 32 */
32 33
33 #include <config.h> 34 #include <config.h>
34 #include "lisp.h" 35 #include "lisp.h"
35 36
48 #endif 49 #endif
49 50
50 #include "device.h" 51 #include "device.h"
51 #include "events.h" 52 #include "events.h"
52 #include "frame.h" 53 #include "frame.h"
54 #include "buffer.h"
55 #include "faces.h"
53 #include "lstream.h" 56 #include "lstream.h"
54 #include "process.h" 57 #include "process.h"
55 #include "redisplay.h" 58 #include "redisplay.h"
56 #include "sysproc.h" 59 #include "sysproc.h"
57 #include "syswait.h" 60 #include "syswait.h"
58 #include "systime.h" 61 #include "systime.h"
59 #include "sysdep.h" 62 #include "sysdep.h"
63 #include "objects-msw.h"
60 64
61 #include "events-mod.h" 65 #include "events-mod.h"
62 #ifdef HAVE_MSG_SELECT 66 #ifdef HAVE_MSG_SELECT
63 #include "sysfile.h" 67 #include "sysfile.h"
64 #elif defined(__CYGWIN32__) 68 #elif defined(__CYGWIN32__)
82 86
83 extern Lisp_Object 87 extern Lisp_Object
84 mswindows_get_toolbar_button_text (struct frame* f, int command_id); 88 mswindows_get_toolbar_button_text (struct frame* f, int command_id);
85 extern Lisp_Object 89 extern Lisp_Object
86 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id); 90 mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
91 extern Lisp_Object
92 mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id);
87 93
88 static Lisp_Object mswindows_find_frame (HWND hwnd); 94 static Lisp_Object mswindows_find_frame (HWND hwnd);
89 static Lisp_Object mswindows_find_console (HWND hwnd); 95 static Lisp_Object mswindows_find_console (HWND hwnd);
90 static Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods); 96 static Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods);
91 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr); 97 static int mswindows_modifier_state (BYTE* keymap, int has_AltGr);
116 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1) 122 #define MAX_WAITABLE (MAXIMUM_WAIT_OBJECTS - 1)
117 123
118 /* List of mswindows waitable handles. */ 124 /* List of mswindows waitable handles. */
119 static HANDLE mswindows_waitable_handles[MAX_WAITABLE]; 125 static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
120 126
127 #ifndef HAVE_MSG_SELECT
121 /* Number of wait handles */ 128 /* Number of wait handles */
122 static int mswindows_waitable_count=0; 129 static int mswindows_waitable_count=0;
130 #endif /* HAVE_MSG_SELECT */
131 /* Brush for painting widgets */
132 static HBRUSH widget_brush = 0;
133 static LONG last_widget_brushed = 0;
123 134
124 /* Count of quit chars currently in the queue */ 135 /* Count of quit chars currently in the queue */
125 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc() 136 /* Incremented in WM_[SYS]KEYDOWN handler in the mswindows_wnd_proc()
126 Decremented in mswindows_dequeue_dispatch_event() */ 137 Decremented in mswindows_dequeue_dispatch_event() */
127 int mswindows_quit_chars_count = 0; 138 int mswindows_quit_chars_count = 0;
468 }; 479 };
469 480
470 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove, 481 DEFINE_LSTREAM_IMPLEMENTATION ("ntpipe-output", lstream_ntpipe_shove,
471 sizeof (struct ntpipe_shove_stream)); 482 sizeof (struct ntpipe_shove_stream));
472 483
484 #ifndef HAVE_MSG_SELECT
473 static DWORD WINAPI 485 static DWORD WINAPI
474 shove_thread (LPVOID vparam) 486 shove_thread (LPVOID vparam)
475 { 487 {
476 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam; 488 struct ntpipe_shove_stream *s = (struct ntpipe_shove_stream*) vparam;
477 489
539 get_ntpipe_output_stream_param (Lstream *stream) 551 get_ntpipe_output_stream_param (Lstream *stream)
540 { 552 {
541 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); 553 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
542 return s->user_data; 554 return s->user_data;
543 } 555 }
556 #endif
544 557
545 static int 558 static int
546 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size) 559 ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
547 { 560 {
548 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream); 561 struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
937 if (message==WM_LBUTTONDOWN || message==WM_MBUTTONDOWN || 950 if (message==WM_LBUTTONDOWN || message==WM_MBUTTONDOWN ||
938 message==WM_RBUTTONDOWN) 951 message==WM_RBUTTONDOWN)
939 { 952 {
940 event->event_type = button_press_event; 953 event->event_type = button_press_event;
941 SetCapture (hwnd); 954 SetCapture (hwnd);
955 /* we need this to make sure the main window regains the focus
956 from control subwindows */
957 if (GetFocus() != hwnd)
958 {
959 SetFocus (hwnd);
960 mswindows_enqueue_magic_event (hwnd, WM_SETFOCUS);
961 }
942 } 962 }
943 else 963 else
944 { 964 {
945 event->event_type = button_release_event; 965 event->event_type = button_release_event;
946 ReleaseCapture (); 966 ReleaseCapture ();
995 return event; 1015 return event;
996 } 1016 }
997 1017
998 /* 1018 /*
999 * Remove and return the first emacs event on the dispatch queue that matches 1019 * Remove and return the first emacs event on the dispatch queue that matches
1000 * the supplied event 1020 * the supplied event.
1001 * Timeout event matches if interval_id equals to that of the given event. 1021 * Timeout event matches if interval_id is equal to that of the given event.
1002 * Keypress event matches if logical AND between modifiers bitmask of the 1022 * Keypress event matches if logical AND between modifiers bitmask of the
1003 * event in the queue and that of the given event is non-zero 1023 * event in the queue and that of the given event is non-zero.
1004 * For all other event types, this function asserts. 1024 * For all other event types, this function aborts.
1005 */ 1025 */
1006 1026
1007 Lisp_Object 1027 Lisp_Object
1008 mswindows_cancel_dispatch_event (struct Lisp_Event* match) 1028 mswindows_cancel_dispatch_event (struct Lisp_Event *match)
1009 { 1029 {
1010 Lisp_Object event; 1030 Lisp_Object event;
1011 Lisp_Object previous_event=Qnil; 1031 Lisp_Object previous_event = Qnil;
1012 int user_p = mswindows_user_event_p (match); 1032 int user_p = mswindows_user_event_p (match);
1013 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue : 1033 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue :
1014 &mswindows_s_dispatch_event_queue; 1034 &mswindows_s_dispatch_event_queue;
1015 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail : 1035 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail :
1016 &mswindows_s_dispatch_event_queue_tail; 1036 &mswindows_s_dispatch_event_queue_tail;
1018 assert (match->event_type == timeout_event 1038 assert (match->event_type == timeout_event
1019 || match->event_type == key_press_event); 1039 || match->event_type == key_press_event);
1020 1040
1021 EVENT_CHAIN_LOOP (event, *head) 1041 EVENT_CHAIN_LOOP (event, *head)
1022 { 1042 {
1023 int found = 1; 1043 struct Lisp_Event *e = XEVENT (event);
1024 if (XEVENT_TYPE (event) != match->event_type) 1044 if ((e->event_type == match->event_type) &&
1025 found = 0; 1045 ((e->event_type == timeout_event) ?
1026 if (found && match->event_type == timeout_event 1046 (e->event.timeout.interval_id == match->event.timeout.interval_id) :
1027 && (XEVENT(event)->event.timeout.interval_id != 1047 /* Must be key_press_event */
1028 match->event.timeout.interval_id)) 1048 ((e->event.key.modifiers & match->event.key.modifiers) != 0)))
1029 found = 0;
1030 if (found && match->event_type == key_press_event
1031 && ((XEVENT(event)->event.key.modifiers &
1032 match->event.key.modifiers) == 0))
1033 found = 0;
1034
1035 if (found)
1036 { 1049 {
1037 if (NILP (previous_event)) 1050 if (NILP (previous_event))
1038 dequeue_event (head, tail); 1051 dequeue_event (head, tail);
1039 else 1052 else
1040 { 1053 {
1048 previous_event = event; 1061 previous_event = event;
1049 } 1062 }
1050 return Qnil; 1063 return Qnil;
1051 } 1064 }
1052 1065
1066 #ifndef HAVE_MSG_SELECT
1053 /************************************************************************/ 1067 /************************************************************************/
1054 /* Waitable handles manipulation */ 1068 /* Waitable handles manipulation */
1055 /************************************************************************/ 1069 /************************************************************************/
1056 static int 1070 static int
1057 find_waitable_handle (HANDLE h) 1071 find_waitable_handle (HANDLE h)
1083 return; 1097 return;
1084 1098
1085 mswindows_waitable_handles [ix] = 1099 mswindows_waitable_handles [ix] =
1086 mswindows_waitable_handles [--mswindows_waitable_count]; 1100 mswindows_waitable_handles [--mswindows_waitable_count];
1087 } 1101 }
1102 #endif /* HAVE_MSG_SELECT */
1088 1103
1089 1104
1090 /************************************************************************/ 1105 /************************************************************************/
1091 /* Event pump */ 1106 /* Event pump */
1092 /************************************************************************/ 1107 /************************************************************************/
1212 mswindows_drain_windows_queue () 1227 mswindows_drain_windows_queue ()
1213 { 1228 {
1214 MSG msg; 1229 MSG msg;
1215 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) 1230 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
1216 { 1231 {
1232 /* we have to translate messages that are not sent to the main
1233 window. this is so that key presses work ok in things like
1234 edit fields. however, we *musn't* translate message for the
1235 main window as this is handled in the wnd proc. */
1236 if ( GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD )
1237 {
1238 TranslateMessage (&msg);
1239 }
1217 DispatchMessage (&msg); 1240 DispatchMessage (&msg);
1218 mswindows_unmodalize_signal_maybe (); 1241 mswindows_unmodalize_signal_maybe ();
1219 } 1242 }
1220 } 1243 }
1221 1244
1646 mswindows_enqueue_keypress_event (hwnd, keysym, mods); 1669 mswindows_enqueue_keypress_event (hwnd, keysym, mods);
1647 else 1670 else
1648 { 1671 {
1649 int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); 1672 int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd)));
1650 BYTE keymap_orig[256]; 1673 BYTE keymap_orig[256];
1651 MSG msg = { hwnd, message, wParam, lParam, GetMessageTime(), (GetMessagePos()) }; 1674 POINT pnt = { LOWORD (GetMessagePos()), HIWORD (GetMessagePos()) };
1675 MSG msg = { hwnd, message, wParam, lParam, GetMessageTime(), pnt };
1652 1676
1653 /* GetKeyboardState() does not work as documented on Win95. We have 1677 /* GetKeyboardState() does not work as documented on Win95. We have
1654 * to loosely track Left and Right modifiers on behalf of the OS, 1678 * to loosely track Left and Right modifiers on behalf of the OS,
1655 * without screwing up Windows NT which tracks them properly. */ 1679 * without screwing up Windows NT which tracks them properly. */
1656 if (wParam == VK_CONTROL) 1680 if (wParam == VK_CONTROL)
1916 1940
1917 if (!NILP(btext)) 1941 if (!NILP(btext))
1918 { 1942 {
1919 /* I think this is safe since the text will only go away 1943 /* I think this is safe since the text will only go away
1920 when the toolbar does...*/ 1944 when the toolbar does...*/
1921 tttext->lpszText=XSTRING_DATA (btext); 1945 GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS,
1946 tttext->lpszText);
1922 } 1947 }
1923 #if 0 1948 #if 0
1924 tttext->uFlags |= TTF_DI_SETITEM; 1949 tttext->uFlags |= TTF_DI_SETITEM;
1925 #endif 1950 #endif
1926 } 1951 }
2113 #endif /* HAVE_MENUBARS */ 2138 #endif /* HAVE_MENUBARS */
2114 2139
2115 case WM_COMMAND: 2140 case WM_COMMAND:
2116 { 2141 {
2117 WORD id = LOWORD (wParam); 2142 WORD id = LOWORD (wParam);
2143 WORD nid = HIWORD (wParam);
2118 HWND cid = (HWND)lParam; 2144 HWND cid = (HWND)lParam;
2119 frame = XFRAME (mswindows_find_frame (hwnd)); 2145 frame = XFRAME (mswindows_find_frame (hwnd));
2120 2146
2121 #ifdef HAVE_TOOLBARS 2147 #ifdef HAVE_TOOLBARS
2122 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id))) 2148 if (!NILP (mswindows_handle_toolbar_wm_command (frame, cid, id)))
2123 break; 2149 break;
2124 #endif 2150 #endif
2125 2151 /* widgets in a buffer only eval a callback for suitable events.*/
2152 switch (nid)
2153 {
2154 case BN_CLICKED:
2155 case EN_CHANGE:
2156 case CBN_EDITCHANGE:
2157 case CBN_SELCHANGE:
2158 if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
2159 return 0;
2160 default: /* do nothing */
2161 }
2162 /* menubars always must come last since the hashtables do not
2163 always exist*/
2126 #ifdef HAVE_MENUBARS 2164 #ifdef HAVE_MENUBARS
2127 if (!NILP (mswindows_handle_wm_command (frame, id))) 2165 if (!NILP (mswindows_handle_wm_command (frame, id)))
2128 break; 2166 break;
2129 #endif 2167 #endif
2130 2168
2131 /* Bite me - a spurious command. This cannot happen. */ 2169 return DefWindowProc (hwnd, message, wParam, lParam);
2132 error ("XEMACS BUG: Cannot decode command message"); 2170 /* Bite me - a spurious command. This used to not be able to
2171 happen but with the introduction of widgets its now
2172 possible. */
2133 } 2173 }
2134 break; 2174 break;
2175
2176 case WM_CTLCOLORBTN:
2177 case WM_CTLCOLORLISTBOX:
2178 case WM_CTLCOLOREDIT:
2179 case WM_CTLCOLORSTATIC:
2180 case WM_CTLCOLORSCROLLBAR:
2181 {
2182 /* if we get an opportunity to paint a widget then do so if
2183 there is an appropriate face */
2184 HWND crtlwnd = (HWND)lParam;
2185 LONG ii = GetWindowLong (crtlwnd, GWL_USERDATA);
2186 if (ii)
2187 {
2188 Lisp_Object image_instance;
2189 VOID_TO_LISP (image_instance, ii);
2190 if (IMAGE_INSTANCEP (image_instance)
2191 &&
2192 IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)
2193 &&
2194 !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance)))
2195 {
2196 /* set colors for the buttons */
2197 HDC hdc = (HDC)wParam;
2198 if (last_widget_brushed != ii)
2199 {
2200 if (widget_brush)
2201 DeleteObject (widget_brush);
2202 widget_brush = CreateSolidBrush
2203 (COLOR_INSTANCE_MSWINDOWS_COLOR
2204 (XCOLOR_INSTANCE
2205 (FACE_BACKGROUND
2206 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2207 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2208 }
2209 last_widget_brushed = ii;
2210 SetTextColor
2211 (hdc,
2212 COLOR_INSTANCE_MSWINDOWS_COLOR
2213 (XCOLOR_INSTANCE
2214 (FACE_FOREGROUND
2215 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2216 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2217 SetBkMode (hdc, OPAQUE);
2218 SetBkColor
2219 (hdc,
2220 COLOR_INSTANCE_MSWINDOWS_COLOR
2221 (XCOLOR_INSTANCE
2222 (FACE_BACKGROUND
2223 (XIMAGE_INSTANCE_WIDGET_FACE (image_instance),
2224 XIMAGE_INSTANCE_SUBWINDOW_FRAME (image_instance)))));
2225 return (LRESULT)widget_brush;
2226 }
2227 }
2228 }
2229 goto defproc;
2135 2230
2136 #ifdef HAVE_DRAGNDROP 2231 #ifdef HAVE_DRAGNDROP
2137 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */ 2232 case WM_DROPFILES: /* implementation ripped-off from event-Xt.c */
2138 { 2233 {
2139 UINT filecount, i, len; 2234 UINT filecount, i, len;
2516 default: 2611 default:
2517 assert(0); 2612 assert(0);
2518 } 2613 }
2519 } 2614 }
2520 2615
2616 #ifndef HAVE_MSG_SELECT
2521 static HANDLE 2617 static HANDLE
2522 get_process_input_waitable (struct Lisp_Process *process) 2618 get_process_input_waitable (struct Lisp_Process *process)
2523 { 2619 {
2524 Lisp_Object instr, outstr, p; 2620 Lisp_Object instr, outstr, p;
2525 XSETPROCESS (p, process); 2621 XSETPROCESS (p, process);
2565 /* Process handle is removed in the event loop as soon 2661 /* Process handle is removed in the event loop as soon
2566 as it is signaled, so don't bother here about it */ 2662 as it is signaled, so don't bother here about it */
2567 HANDLE hev = get_process_input_waitable (process); 2663 HANDLE hev = get_process_input_waitable (process);
2568 remove_waitable_handle (hev); 2664 remove_waitable_handle (hev);
2569 } 2665 }
2666 #endif /* HAVE_MSG_SELECT */
2570 2667
2571 static void 2668 static void
2572 emacs_mswindows_select_console (struct console *con) 2669 emacs_mswindows_select_console (struct console *con)
2573 { 2670 {
2574 } 2671 }
2579 } 2676 }
2580 2677
2581 static void 2678 static void
2582 emacs_mswindows_quit_p (void) 2679 emacs_mswindows_quit_p (void)
2583 { 2680 {
2681 MSG msg;
2682
2584 /* Quit cannot happen in modal loop: all program 2683 /* Quit cannot happen in modal loop: all program
2585 input is dedicated to Windows. */ 2684 input is dedicated to Windows. */
2586 if (mswindows_in_modal_loop) 2685 if (mswindows_in_modal_loop)
2587 return; 2686 return;
2588 2687
2589 /* Drain windows queue. This sets up number of quit 2688 /* Drain windows queue. This sets up number of quit characters in the queue
2590 characters in in the queue */ 2689 * (and also processes wm focus change, move, resize, etc messages).
2591 mswindows_drain_windows_queue (); 2690 * We don't want to process WM_PAINT messages because this function can be
2691 * called from almost anywhere and the windows' states may be changing. */
2692 while (PeekMessage (&msg, NULL, 0, WM_PAINT-1, PM_REMOVE) ||
2693 PeekMessage (&msg, NULL, WM_PAINT+1, WM_USER-1, PM_REMOVE))
2694 DispatchMessage (&msg);
2592 2695
2593 if (mswindows_quit_chars_count > 0) 2696 if (mswindows_quit_chars_count > 0)
2594 { 2697 {
2595 /* Yes there's a hidden one... Throw it away */ 2698 /* Yes there's a hidden one... Throw it away */
2596 struct Lisp_Event match_against; 2699 struct Lisp_Event match_against;