comparison src/event-msw.c @ 223:2c611d1463a6 r20-4b10

Import from CVS: tag r20-4b10
author cvs
date Mon, 13 Aug 2007 10:10:54 +0200
parents 262b8bb4a523
children 12579d965149
comparison
equal deleted inserted replaced
222:aae4c8b01452 223:2c611d1463a6
44 #include "systime.h" 44 #include "systime.h"
45 45
46 #include "event-msw.h" 46 #include "event-msw.h"
47 47
48 static struct event_stream *mswindows_event_stream; 48 static struct event_stream *mswindows_event_stream;
49 static Lisp_Object mswindows_dispatch_event_queue, mswindows_dispatch_event_queue_tail; 49
50 CRITICAL_SECTION mswindows_dispatch_crit; 50 /*
51 * Two separate queues, for efficiency, one (_u_) for user events, and
52 * another (_s_) for non-user ones. We always return events out of the
53 * first one until it is empty and only then proceed with the second
54 * one.
55 */
56 static Lisp_Object mswindows_u_dispatch_event_queue, mswindows_u_dispatch_event_queue_tail;
57 static Lisp_Object mswindows_s_dispatch_event_queue, mswindows_s_dispatch_event_queue_tail;
51 58
52 /* 59 /*
53 * List of mswindows waitable handles. 60 * List of mswindows waitable handles.
54 * Apart from the dispatch queue semaphore, all of these handles may be waited 61 * Apart from the dispatch queue semaphore, all of these handles may be waited
55 * on multiple times in emacs_mswindows_next_event before being processed and so 62 * on multiple times in emacs_mswindows_next_event before being processed and so
58 static HANDLE mswindows_waitable[MAX_WAITABLE]; 65 static HANDLE mswindows_waitable[MAX_WAITABLE];
59 66
60 /* random emacs info associated with each of the wait handles */ 67 /* random emacs info associated with each of the wait handles */
61 static mswindows_waitable_info_type mswindows_waitable_info[MAX_WAITABLE]; 68 static mswindows_waitable_info_type mswindows_waitable_info[MAX_WAITABLE];
62 69
70 /* Count of quit chars currently in the queue */
71 /* Incremented in WM_CHAR handler in msw-proc.c
72 Decremented in mswindows_dequeue_dispatch_event() */
73 int mswindows_quit_chars_count = 0;
74
75 /* These are Lisp integers; see DEFVARS in this file for description. */
76 int mswindows_dynamic_frame_resize;
77 int mswindows_num_mouse_buttons;
78 int mswindows_button2_max_skew_x;
79 int mswindows_button2_max_skew_y;
80 int mswindows_button2_chord_time;
81
63 /* Number of wait handles */ 82 /* Number of wait handles */
64 static mswindows_waitable_count=0; 83 static mswindows_waitable_count=0;
65 84
66 /* 85 static int
67 * Add an emacs event to the dispatch queue and increment the semaphore 86 mswindows_user_event_p (struct Lisp_Event* sevt)
87 {
88 return (sevt->event_type == key_press_event
89 || sevt->event_type == button_press_event
90 || sevt->event_type == button_release_event
91 || sevt->event_type == pointer_motion_event);
92 }
93
94 /*
95 * Add an emacs event to the proper dispatch queue
68 */ 96 */
69 void 97 void
70 mswindows_enqueue_dispatch_event (Lisp_Object event) 98 mswindows_enqueue_dispatch_event (Lisp_Object event)
71 { 99 {
72 enqueue_event (event, &mswindows_dispatch_event_queue, 100 int user_p = mswindows_user_event_p (XEVENT(event));
73 &mswindows_dispatch_event_queue_tail); 101 enqueue_event (event,
74 ReleaseSemaphore(mswindows_waitable[0], 1, NULL); 102 user_p ? &mswindows_u_dispatch_event_queue :
75 } 103 &mswindows_s_dispatch_event_queue,
76 104 user_p ? &mswindows_u_dispatch_event_queue_tail :
77 /* 105 &mswindows_s_dispatch_event_queue_tail);
78 * Remove and return the first emacs event on the dispatch queue. Don't 106
79 * decrement the queue's semaphore because it will be decremented by being 107 /* This one does not go to window procedure, hence does not
80 * waited on. 108 generate XM_BUMPQUEUE magic event! */
109 PostMessage (NULL, XM_BUMPQUEUE, 0, 0);
110 }
111
112 /*
113 * Remove and return the first emacs event on the dispatch queue.
114 * Give a preference to user events over non-user ones.
81 */ 115 */
82 static Lisp_Object 116 static Lisp_Object
83 mswindows_dequeue_dispatch_event (void) 117 mswindows_dequeue_dispatch_event ()
84 { 118 {
85 Lisp_Object event; 119 Lisp_Object event;
86 event = dequeue_event (&mswindows_dispatch_event_queue, 120 struct Lisp_Event* sevt;
87 &mswindows_dispatch_event_queue_tail); 121
122 assert (!NILP(mswindows_u_dispatch_event_queue) ||
123 !NILP(mswindows_s_dispatch_event_queue));
124
125 event = dequeue_event (
126 NILP(mswindows_u_dispatch_event_queue) ?
127 &mswindows_s_dispatch_event_queue :
128 &mswindows_u_dispatch_event_queue,
129 NILP(mswindows_u_dispatch_event_queue) ?
130 &mswindows_s_dispatch_event_queue_tail :
131 &mswindows_u_dispatch_event_queue_tail);
132
133 sevt = XEVENT(event);
134 if (sevt->event_type == key_press_event
135 && (sevt->event.key.modifiers & FAKE_MOD_QUIT))
136 {
137 sevt->event.key.modifiers &= ~FAKE_MOD_QUIT;
138 --mswindows_quit_chars_count;
139 }
140
88 return event; 141 return event;
89 } 142 }
90 143
91 /* 144 /*
92 * Remove and return the first emacs event on the dispatch queue that matches 145 * Remove and return the first emacs event on the dispatch queue that matches
93 * the supplied event and decrement the queue's semaphore. 146 * the supplied event
94 * Only supports timeout events. 147 * Timeout event matches if interval_id equals to that of the given event.
95 */ 148 * Keypress event matches if logical AND between modifiers bitmask of the
149 * event in the queue and that of the given event is non-zero
150 * For all other event types, this function asserts.
151 */
152
96 Lisp_Object 153 Lisp_Object
97 mswindows_cancel_dispatch_event (Lisp_Object match_event) 154 mswindows_cancel_dispatch_event (struct Lisp_Event* match)
98 { 155 {
99 Lisp_Object event; 156 Lisp_Object event;
100 Lisp_Object previous_event=Qnil; 157 Lisp_Object previous_event=Qnil;
101 struct Lisp_Event *match = XEVENT(match_event); 158 int user_p = mswindows_user_event_p (match);
102 159 Lisp_Object* head = user_p ? &mswindows_u_dispatch_event_queue :
103 assert (match->event_type == timeout_event); 160 &mswindows_s_dispatch_event_queue;
104 161 Lisp_Object* tail = user_p ? &mswindows_u_dispatch_event_queue_tail :
105 EVENT_CHAIN_LOOP (event, mswindows_dispatch_event_queue) 162 &mswindows_s_dispatch_event_queue_tail;
106 if (XEVENT_TYPE (event) == match->event_type) 163
107 { 164 assert (match->event_type == timeout_event
108 /* We only handle timeouts */ 165 || match->event_type == key_press_event);
109 if (XEVENT(event)->event.timeout.interval_id == 166
110 match->event.timeout.interval_id) 167 EVENT_CHAIN_LOOP (event, *head)
111 { 168 {
112 if (NILP (previous_event)) 169 int found = 1;
113 dequeue_event (&mswindows_dispatch_event_queue, 170 if (XEVENT_TYPE (event) != match->event_type)
114 &mswindows_dispatch_event_queue_tail); 171 found = 0;
115 else 172 if (found && match->event_type == timeout_event
116 { 173 && (XEVENT(event)->event.timeout.interval_id !=
117 XSET_EVENT_NEXT (previous_event, XEVENT_NEXT (event)); 174 match->event.timeout.interval_id))
118 if (EQ (mswindows_dispatch_event_queue_tail, event)) 175 found = 0;
119 mswindows_dispatch_event_queue_tail = previous_event; 176 if (found && match->event_type == key_press_event
120 } 177 && ((XEVENT(event)->event.key.modifiers &
121 178 match->event.key.modifiers) == 0))
122 /* Decrement the dispatch queue counter */ 179 found = 0;
123 WaitForSingleObject(mswindows_waitable[0], INFINITE); 180
124 return event; 181 if (found)
125 } 182 {
126 } 183 if (NILP (previous_event))
127 else 184 dequeue_event (head, tail);
185 else
186 {
187 XSET_EVENT_NEXT (previous_event, XEVENT_NEXT (event));
188 if (EQ (*tail, event))
189 *tail = previous_event;
190 }
191
192 return event;
193 }
128 previous_event = event; 194 previous_event = event;
129 195 }
130 return Qnil;
131 } 196 }
132 197
133 /* 198 /*
134 * Find a free waitable slot 199 * Find a free waitable slot
135 */ 200 */
154 int waitable; 219 int waitable;
155 220
156 switch (info->type) 221 switch (info->type)
157 { 222 {
158 case mswindows_waitable_type_dispatch: 223 case mswindows_waitable_type_dispatch:
224 assert (0); /* kkm - should not get here */
159 /* Can only have one waitable for the dispatch queue, and it's the first one */ 225 /* Can only have one waitable for the dispatch queue, and it's the first one */
160 assert (mswindows_waitable_count++ == 0); 226 assert (mswindows_waitable_count++ == 0);
161 waitable=0; 227 waitable=0;
162 InitializeCriticalSection(&mswindows_dispatch_crit); 228 // InitializeCriticalSection(&mswindows_dispatch_crit);
163 assert (mswindows_waitable[0] = CreateSemaphore (NULL, 0, 0x7fffffff, NULL)); 229 assert (mswindows_waitable[0] = CreateSemaphore (NULL, 0, 0x7fffffff, NULL));
164 return mswindows_waitable_info+0; 230 return mswindows_waitable_info+0;
165
166 #if 0 /* Windows95 doesn't support WaitableTimers */
167 case mswindows_waitable_type_timeout:
168 {
169 LARGE_INTEGER due;
170 due.QuadPart = 10000 * (LONGLONG) info->data.timeout.milliseconds;
171 waitable = mswindows_find_free_waitable();
172 mswindows_waitable[waitable] = CreateWaitableTimer(NULL, TRUE, NULL);
173 SetWaitableTimer(mswindows_waitable[waitable], &due, 0, NULL, NULL, FALSE);
174 mswindows_waitable_info[waitable].data.timeout.id = waitable;
175 }
176 break;
177 #endif
178 231
179 default: 232 default:
180 assert(0); 233 assert(0);
181 } 234 }
182 mswindows_waitable_info[waitable].type = info->type; 235 mswindows_waitable_info[waitable].type = info->type;
191 { 244 {
192 int waitable; 245 int waitable;
193 246
194 switch (info->type) 247 switch (info->type)
195 { 248 {
196 #if 0
197 case mswindows_waitable_type_timeout:
198 waitable = info->data.timeout.id;
199 CancelWaitableTimeout(mswindows_waitable[waitable]);
200 break;
201 #endif
202 249
203 default: 250 default:
204 assert(0); 251 assert(0);
205 } 252 }
206 253
209 mswindows_waitable_info[waitable].type = mswindows_waitable_type_none; 256 mswindows_waitable_info[waitable].type = mswindows_waitable_type_none;
210 if (waitable == mswindows_waitable_count-1) 257 if (waitable == mswindows_waitable_count-1)
211 --mswindows_waitable_count; 258 --mswindows_waitable_count;
212 } 259 }
213 260
261 /*
262 * Callback procedure for synchronous timer messages
263 */
264 static void CALLBACK
265 mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
266 {
267 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
268 struct Lisp_Event *event = XEVENT (emacs_event);
269
270 KillTimer (NULL, id_timer);
271
272 event->channel = Qnil;
273 event->timestamp = dwtime;
274 event->event_type = timeout_event;
275 event->event.timeout.interval_id = id_timer;
276
277 mswindows_enqueue_dispatch_event (emacs_event);
278 }
279
280 static void
281 mswindows_drain_windows_queue ()
282 {
283 MSG msg;
284 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
285 DispatchMessage (&msg);
286 }
287
288 /*
289 * This drains the event queue and fills up two internal queues until
290 * an event of a type specified by USER_P is retrieved.
291 *
292 * If user_p, then the function drains until the first user event, or
293 * the first non-user event if there no user events. Otherwise, If
294 * not user_p, it does not give preference to user events.
295 *
296 * If badly_p, then the function does not return until an event is
297 * available.
298 *
299 * The code does not rely on MsgWaitForMultipleObjects preference for
300 * messages over waitable handles.
301 *
302 * Used by emacs_mswindows_event_pending_p and emacs_mswindows_next_event
303 */
304 static void
305 mswindows_need_event (int user_p, int badly_p)
306 {
307 int active;
308
309 /* Have to drain Windows message queue first, otherwise, we may miss
310 quit char when called from quit_p */
311 mswindows_drain_windows_queue ();
312
313 while (NILP (mswindows_u_dispatch_event_queue) &&
314 (user_p || NILP (mswindows_s_dispatch_event_queue)))
315 {
316 /* If we already have an event, we've got someting to return - no wait! */
317 if (!NILP (mswindows_u_dispatch_event_queue)
318 || !NILP (mswindows_s_dispatch_event_queue))
319 badly_p = 0;
320
321 /* Now try getting a message */
322 active = MsgWaitForMultipleObjects (mswindows_waitable_count,
323 mswindows_waitable,
324 FALSE, badly_p ? INFINITE : 0,
325 QS_ALLINPUT);
326
327 /* This will assert if handle being waited for becomes abandoned.
328 Not the case currently tho */
329 assert ((!badly_p && active == WAIT_TIMEOUT) ||
330 (active >= WAIT_OBJECT_0 &&
331 active <= WAIT_OBJECT_0 + mswindows_waitable_count));
332
333 if (active == WAIT_TIMEOUT)
334 {
335 /* No luck trying - just return what we've already got */
336 return;
337 }
338 else if (active == WAIT_OBJECT_0 + mswindows_waitable_count)
339 {
340 /* Got your message, thanks */
341 mswindows_drain_windows_queue ();
342 }
343 else
344 {
345 /* XXX FIXME: We should do some kind of round-robin scheme to ensure fairness */
346 int waitable = active - WAIT_OBJECT_0;
347 mswindows_waitable_info_type *info = mswindows_waitable_info + waitable;
348
349 switch (info->type)
350 {
351 /* XXX FIXME: Should enque subprocess event here so that it is not lost */
352 default:
353 assert(0);
354 }
355 }
356 } /* while */
357
358 return;
359 }
360
214 361
215 /************************************************************************/ 362 /************************************************************************/
216 /* methods */ 363 /* methods */
217 /************************************************************************/ 364 /************************************************************************/
218 365
219 static int 366 static int
220 emacs_mswindows_add_timeout (EMACS_TIME thyme) 367 emacs_mswindows_add_timeout (EMACS_TIME thyme)
221 { 368 {
369 int milliseconds;
222 EMACS_TIME current_time; 370 EMACS_TIME current_time;
223 int milliseconds;
224 int id;
225 mswindows_request_type request;
226
227 EMACS_GET_TIME (current_time); 371 EMACS_GET_TIME (current_time);
228 EMACS_SUB_TIME (thyme, thyme, current_time); 372 EMACS_SUB_TIME (thyme, thyme, current_time);
229 milliseconds = EMACS_SECS (thyme) * 1000 + EMACS_USECS (thyme) / 1000; 373 milliseconds = EMACS_SECS (thyme) * 1000 +
374 (EMACS_USECS (thyme) + 500) / 1000;
230 if (milliseconds < 1) 375 if (milliseconds < 1)
231 milliseconds = 1; 376 milliseconds = 1;
232 request.thing1 = (void *) milliseconds; 377 return SetTimer (NULL, 0, milliseconds, mswindows_wm_timer_callback);
233 id = mswindows_make_request(WM_XEMACS_SETTIMER, 0, &request);
234 assert(id); /* XXX */
235 return id;
236 } 378 }
237 379
238 static void 380 static void
239 emacs_mswindows_remove_timeout (int id) 381 emacs_mswindows_remove_timeout (int id)
240 { 382 {
241 mswindows_request_type request = { (void *) id }; 383 struct Lisp_Event match_against;
242 mswindows_make_request(WM_XEMACS_KILLTIMER, 0, &request); 384 Lisp_Object emacs_event;
385
386 KillTimer (NULL, id);
387
388 /* If there is a dispatch event generated by this
389 timeout in the queue, we have to remove it too. */
390 match_against.event_type = timeout_event;
391 match_against.event.timeout.interval_id = id;
392 emacs_event = mswindows_cancel_dispatch_event (&match_against);
393 if (!NILP (emacs_event))
394 Fdeallocate_event(emacs_event);
243 } 395 }
244 396
245 /* If `user_p' is false, then return whether there are any win32, timeout, 397 /* If `user_p' is false, then return whether there are any win32, timeout,
246 * or subprocess events pending (that is, whether 398 * or subprocess events pending (that is, whether
247 * emacs_mswindows_next_event() would return immediately without blocking). 399 * emacs_mswindows_next_event() would return immediately without blocking).
252 * emacs_mswindows_next_event() would not block. 404 * emacs_mswindows_next_event() would not block.
253 */ 405 */
254 static int 406 static int
255 emacs_mswindows_event_pending_p (int user_p) 407 emacs_mswindows_event_pending_p (int user_p)
256 { 408 {
257 if (user_p) 409 mswindows_need_event (user_p, 0);
258 { 410
259 /* Iterate over the dispatch queue looking for user-events */ 411 return (!NILP (mswindows_u_dispatch_event_queue)
260 int found = 0; 412 || (!user_p && !NILP (mswindows_s_dispatch_event_queue)));
261 Lisp_Object event;
262
263 EnterCriticalSection (&mswindows_dispatch_crit);
264 EVENT_CHAIN_LOOP (event, mswindows_dispatch_event_queue)
265 if (command_event_p (event))
266 found = 1;
267 LeaveCriticalSection (&mswindows_dispatch_crit);
268 return found;
269 }
270 else
271 {
272 /* Check for any kind of input, including the dispatch queue */
273 #if 0
274 /* Want do do the following, but it's not clear whether this would
275 * cause the waitables to become unsignalled */
276 return (WaitForMultipleObjects (mswindows_waitable_count,
277 mswindows_waitable, FALSE, 0)
278 != WAIT_TIMEOUT);
279 #else
280 return !NILP (mswindows_dispatch_event_queue);
281 #endif
282 }
283 }
284
285 static struct console *
286 find_console_from_fd (int fd)
287 {
288 return 0;
289 } 413 }
290 414
291 /* 415 /*
292 * Return the next event 416 * Return the next event
293 * We return windows events off the dispatch event queue in preference to other events
294 */ 417 */
295 static void 418 static void
296 emacs_mswindows_next_event (struct Lisp_Event *emacs_event) 419 emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
297 { 420 {
298 DWORD active; 421 Lisp_Object event, event2;
299 active = WaitForMultipleObjects (mswindows_waitable_count, mswindows_waitable, 422
300 FALSE, INFINITE); 423 /* Give strong preference to user events */
301 assert(active >= WAIT_OBJECT_0 && active <= WAIT_OBJECT_0 + mswindows_waitable_count - 1); 424 mswindows_need_event (1, 1);
302 425
303 /* Windows events on the dispatch event queue */ 426 /* XXX Copied from event-Xt.c */
304 if (active == WAIT_OBJECT_0) 427 event = mswindows_dequeue_dispatch_event (!NILP(mswindows_u_dispatch_event_queue));
305 { 428 XSETEVENT (event2, emacs_event);
306 /* XXX Copied from event-Xt.c */ 429 Fcopy_event (event, event2);
307 Lisp_Object event, event2; 430 Fdeallocate_event (event);
308
309 EnterCriticalSection (&mswindows_dispatch_crit);
310 XSETEVENT (event2, emacs_event);
311 event = mswindows_dequeue_dispatch_event ();
312 Fcopy_event (event, event2);
313 Fdeallocate_event (event);
314 LeaveCriticalSection (&mswindows_dispatch_crit);
315 }
316 else
317 {
318 /* XXX FIXME: We should do some kind of round-robin scheme to ensure fairness */
319 int waitable = active - WAIT_OBJECT_0;
320 mswindows_waitable_info_type *info = mswindows_waitable_info + waitable;
321
322 switch (info->type)
323 {
324 case mswindows_waitable_type_timeout:
325 emacs_event->channel = Qnil;
326 emacs_event->event_type = timeout_event;
327 emacs_event->event.timeout.interval_id = info->data.timeout.id;
328 mswindows_remove_waitable(info);
329 break;
330
331 default:
332 assert(0);
333 }
334 }
335 } 431 }
336 432
337 /* 433 /*
338 * Handle a magic event off the dispatch queue. 434 * Handle a magic event off the dispatch queue.
339 * XXX split into seperate functions for clarity.
340 */ 435 */
341 static void 436 static void
342 emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event) 437 emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
343 { 438 {
344 RECT *rect = &EVENT_MSWINDOWS_MAGIC_DATA(emacs_event);
345 struct frame *f = XFRAME (EVENT_CHANNEL (emacs_event));
346 Lisp_Object frame = Qnil;
347 XSETFRAME (frame, f);
348 #if 0 439 #if 0
349 stderr_out("magic %x, (%d,%d), (%d,%d)\n", 440 stderr_out("magic %x, (%d,%d), (%d,%d)\n",
350 EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event), 441 EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event),
351 rect->left, rect->top, rect->right, rect->bottom); 442 rect->left, rect->top, rect->right, rect->bottom);
352 #endif 443 #endif
353 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)) 444 switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event))
354 { 445 {
355 case WM_SETFOCUS: 446 case WM_SETFOCUS:
356 case WM_KILLFOCUS: 447 case WM_KILLFOCUS:
357 { 448 {
449 Lisp_Object frame = EVENT_CHANNEL (emacs_event);
450 struct frame *f = XFRAME (frame);
358 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS); 451 int in_p = (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event) == WM_SETFOCUS);
359 Lisp_Object conser; 452 Lisp_Object conser;
453
360 /* struct gcpro gcpro1; */ 454 /* struct gcpro gcpro1; */
361 455
362 /* Clear sticky modifiers here (if we had any) */ 456 /* Clear sticky modifiers here (if we had any) */
363 457
364 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil)); 458 conser = Fcons (frame, Fcons (FRAME_DEVICE (f), in_p ? Qt : Qnil));
366 emacs_handle_focus_change_preliminary (conser); 460 emacs_handle_focus_change_preliminary (conser);
367 /* Under X the stuff up to here is done in the X event handler. 461 /* Under X the stuff up to here is done in the X event handler.
368 I Don't know why */ 462 I Don't know why */
369 emacs_handle_focus_change_final (conser); 463 emacs_handle_focus_change_final (conser);
370 /* UNGCPRO; */ 464 /* UNGCPRO; */
465
371 } 466 }
372 break; 467 break;
373 468
374 /* XXX What about Enter & Leave */ 469 case XM_BUMPQUEUE:
470 /* This is a nice event, when we're in need to queue *something* */
471 break;
472
473 case XM_MAPFRAME:
474 case XM_UNMAPFRAME:
475 {
476 Lisp_Object frame = EVENT_CHANNEL (emacs_event);
477 va_run_hook_with_args (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event)
478 == XM_MAPFRAME ?
479 Qmap_frame_hook : Qunmap_frame_hook,
480 1, frame);
481 }
482 break;
483
484 /* XXX What about Enter & Leave */
375 #if 0 485 #if 0
376 va_run_hook_with_args (in_p ? Qmouse_enter_frame_hook : 486 va_run_hook_with_args (in_p ? Qmouse_enter_frame_hook :
377 Qmouse_leave_frame_hook, 1, frame); 487 Qmouse_leave_frame_hook, 1, frame);
378 break;
379 #endif 488 #endif
380
381 case WM_SIZE:
382 if ((rect->left & rect->top & rect->right & rect->bottom) == -1)
383 {
384 /* Iconified */
385 FRAME_VISIBLE_P (f) = 0;
386 va_run_hook_with_args (Qunmap_frame_hook, 1, frame);
387 Fframe_iconified_p (frame);
388 }
389 else
390 {
391 /* If we're uniconified, our size may or may not have changed */
392 int columns, rows;
393 int was_visible = FRAME_VISIBLE_P (f);
394
395 FRAME_VISIBLE_P (f) = 1;
396 FRAME_PIXWIDTH(f) = rect->right;
397 FRAME_PIXHEIGHT(f) = rect->bottom;
398
399 pixel_to_char_size (f, rect->right, rect->bottom, &columns, &rows);
400 change_frame_size (f, rows, columns, 0);
401 /* MARK_FRAME_WINDOWS_STRUCTURE_CHANGED (f); /* XXX Too extreme? */
402
403 if (!was_visible)
404 va_run_hook_with_args (Qmap_frame_hook, 1, frame);
405
406 }
407 break;
408
409 case WM_PAINT:
410 mswindows_redraw_exposed_area(f, rect->left, rect->top,
411 rect->right, rect->bottom);
412 break;
413
414 case WM_CLOSE:
415 enqueue_misc_user_event (frame, Qeval, list3 (Qdelete_frame, frame, Qt));
416 break;
417 489
418 default: 490 default:
419 assert(0); 491 assert(0);
420 } 492 }
421 } 493 }
441 } 513 }
442 514
443 static void 515 static void
444 emacs_mswindows_quit_p (void) 516 emacs_mswindows_quit_p (void)
445 { 517 {
518 mswindows_need_event (1, 0);
519
520 if (mswindows_quit_chars_count > 0)
521 {
522 /* Yes there's a hidden one... Throw it away */
523 struct Lisp_Event match_against;
524 Lisp_Object emacs_event;
525
526 match_against.event_type = key_press_event;
527 match_against.event.key.modifiers = FAKE_MOD_QUIT;
528
529 emacs_event = mswindows_cancel_dispatch_event (&match_against);
530 assert (!NILP (emacs_event));
531
532 Vquit_flag = (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT
533 ? Qcritical : Qt);
534
535 Fdeallocate_event(emacs_event);
536 --mswindows_quit_chars_count;
537 }
446 } 538 }
447 539
448 /* This is called from GC when a process object is about to be freed. 540 /* This is called from GC when a process object is about to be freed.
449 If we've still got pointers to it in this file, we're gonna lose hard. 541 If we've still got pointers to it in this file, we're gonna lose hard.
450 */ 542 */
472 /************************************************************************/ 564 /************************************************************************/
473 565
474 void 566 void
475 vars_of_event_mswindows (void) 567 vars_of_event_mswindows (void)
476 { 568 {
477 mswindows_dispatch_event_queue = Qnil; 569 mswindows_u_dispatch_event_queue = Qnil;
478 staticpro (&mswindows_dispatch_event_queue); 570 staticpro (&mswindows_u_dispatch_event_queue);
479 mswindows_dispatch_event_queue_tail = Qnil; 571 mswindows_u_dispatch_event_queue_tail = Qnil;
572
573 mswindows_s_dispatch_event_queue = Qnil;
574 staticpro (&mswindows_s_dispatch_event_queue);
575 mswindows_s_dispatch_event_queue_tail = Qnil;
480 576
481 mswindows_event_stream = xnew (struct event_stream); 577 mswindows_event_stream = xnew (struct event_stream);
482 578
483 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; 579 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p;
484 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; 580 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event;
485 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event; 581 mswindows_event_stream->handle_magic_event_cb = emacs_mswindows_handle_magic_event;
486 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout; 582 mswindows_event_stream->add_timeout_cb = emacs_mswindows_add_timeout;
487 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout; 583 mswindows_event_stream->remove_timeout_cb = emacs_mswindows_remove_timeout;
488 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console; 584 mswindows_event_stream->select_console_cb = emacs_mswindows_select_console;
489 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console; 585 mswindows_event_stream->unselect_console_cb = emacs_mswindows_unselect_console;
490 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process; 586 mswindows_event_stream->select_process_cb = emacs_mswindows_select_process;
491 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process; 587 mswindows_event_stream->unselect_process_cb = emacs_mswindows_unselect_process;
492 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p; 588 mswindows_event_stream->quit_p_cb = emacs_mswindows_quit_p;
589
590 DEFVAR_BOOL ("w32-dynamic-frame-resize", &mswindows_dynamic_frame_resize /*
591 *Controls redrawing frame contents during mouse-drag or keyboard resize
592 operation. When non-nil, the frame is redrawn while being resized. When
593 nil, frame is not redrawn, and exposed areas are filled with default
594 MDI application background color. Note that this option only has effect
595 if "Show window contents while dragging" is on in system Display/Plus!
596 settings.
597 Default is t on fast machines, nil on slow.
598 */ );
599
600 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */
601 DEFVAR_INT ("w32-mouse-button-tolerance", &mswindows_button2_chord_time /*
602 *Analogue of double click interval for faking middle mouse events.
603 The value is the minimum time in milliseconds that must elapse between
604 left/right button down events before they are considered distinct events.
605 If both mouse buttons are depressed within this interval, a middle mouse
606 button down event is generated instead.
607 If negative or zero, currently set system default is used instead.
608 */ );
609
610 /* The description copied verbatim from nt-emacs. (C) Geoff Voelker */
611 DEFVAR_INT ("w32-num-mouse-buttons", &mswindows_num_mouse_buttons /*
612 Number of physical mouse buttons.
613 */ );
614
615 DEFVAR_INT ("w32-mouse-button-max-skew-x", &mswindows_button2_max_skew_x /*
616 *Maximum horizontal distance in pixels between points in which left and
617 right button clicks occured for them to be translated into single
618 middle button event. Clicks must occur in time not longer than defined
619 by the variable w32-mouse-button-tolerance.
620 If negative or zero, currently set system default is used instead.
621 */ );
622
623 DEFVAR_INT ("w32-mouse-button-max-skew-y", &mswindows_button2_max_skew_y /*
624 *Maximum vertical distance in pixels between points in which left and
625 right button clicks occured for them to be translated into single
626 middle button event. Clicks must occur in time not longer than defined
627 by the variable w32-mouse-button-tolerance.
628 If negative or zero, currently set system default is used instead.
629 */ );
630
631 mswindows_button2_max_skew_x = 0;
632 mswindows_button2_max_skew_y = 0;
633 mswindows_button2_chord_time = 0;
493 } 634 }
494 635
495 void 636 void
496 syms_of_event_mswindows (void) 637 syms_of_event_mswindows (void)
497 { 638 {
499 640
500 void 641 void
501 init_event_mswindows_late (void) 642 init_event_mswindows_late (void)
502 { 643 {
503 event_stream = mswindows_event_stream; 644 event_stream = mswindows_event_stream;
504 } 645
646 mswindows_dynamic_frame_resize = !GetSystemMetrics (SM_SLOWMACHINE);
647 mswindows_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
648 }