comparison src/event-msw.c @ 227:0e522484dd2a r20-5b12

Import from CVS: tag r20-5b12
author cvs
date Mon, 13 Aug 2007 10:12:37 +0200
parents 12579d965149
children 557eaa0339bf
comparison
equal deleted inserted replaced
226:eea38c7ad7b4 227:0e522484dd2a
33 #include <config.h> 33 #include <config.h>
34 #include "lisp.h" 34 #include "lisp.h"
35 35
36 #include "device.h" 36 #include "device.h"
37 #include "console-msw.h" 37 #include "console-msw.h"
38 #include "emacsfns.h"
38 #include "events.h" 39 #include "events.h"
39 #include "frame.h" 40 #include "frame.h"
40 #include "process.h" 41 #include "process.h"
41 42 #include "redisplay.h"
42 #include "sysproc.h" 43 #include "sysproc.h"
43 #include "syswait.h" 44 #include "syswait.h"
44 #include "systime.h" 45 #include "systime.h"
45 46
46 #include "event-msw.h" 47 #include "event-msw.h"
79 int mswindows_button2_max_skew_y; 80 int mswindows_button2_max_skew_y;
80 int mswindows_button2_chord_time; 81 int mswindows_button2_chord_time;
81 82
82 /* Number of wait handles */ 83 /* Number of wait handles */
83 static mswindows_waitable_count=0; 84 static mswindows_waitable_count=0;
85
86 /* This is the event signaled by the event pump.
87 See mswindows_pump_outstanding_events for comments */
88 static Lisp_Object mswindows_error_caught_by_event_pump;
89 static int mswindows_in_event_pump;
90
91 /* Count of wound timers */
92 static int mswindows_pending_timers_count;
84 93
85 static int 94 static int
86 mswindows_user_event_p (struct Lisp_Event* sevt) 95 mswindows_user_event_p (struct Lisp_Event* sevt)
87 { 96 {
88 return (sevt->event_type == key_press_event 97 return (sevt->event_type == key_press_event
193 previous_event = event; 202 previous_event = event;
194 } 203 }
195 } 204 }
196 205
197 /* 206 /*
207 * This is an unsafe part of event pump, guarded by
208 * condition_case. See mswindows_pump_outstanding_events
209 */
210 static Lisp_Object
211 mswindows_unsafe_pump_events (Lisp_Object u_n_u_s_e_d)
212 {
213 /* This function can call lisp */
214 Lisp_Object event = Fmake_event (Qnil, Qnil);
215 struct gcpro gcpro1;
216 int do_redisplay = 0;
217 GCPRO1 (event);
218
219 while (detect_input_pending ())
220 {
221 Fnext_event (event, Qnil);
222 Fdispatch_event (event);
223 do_redisplay = 1;
224 }
225
226 if (do_redisplay)
227 redisplay ();
228
229 Fdeallocate_event (event);
230 UNGCPRO;
231
232 /* Qt becomes return value of mswindows_pump_outstanding_events
233 once we get here */
234 return Qt;
235 }
236
237 /* See mswindows_pump_outstanding_events */
238 static Lisp_Object
239 mswindows_event_pump_error_handler (Lisp_Object cons_sig_data,
240 Lisp_Object u_n_u_s_e_d)
241 {
242 mswindows_error_caught_by_event_pump = cons_sig_data;
243 return Qnil;
244 }
245
246 /*
247 * This function pumps emacs events, while available, by using
248 * next_message/dispatch_message loop. Errors are trapped around
249 * the loop so the function always returns.
250 *
251 * Windows message queue is not looked into during the call,
252 * neither are waitable handles checked. The function pumps
253 * thus only dispatch events already queued, as well as those
254 * resulted in dispatching thereof. This is done by setting
255 * module local variable mswidows_in_event_pump to nonzero.
256 *
257 * Return value is Qt if no errors was trapped, or Qnil if
258 * there was an error.
259 *
260 * In case of error, a cons representing the error, in the
261 * form (SIGNAL . DATA), is stored in the module local variable
262 * mswindows_error_caught_by_event_pump. This error is signaled
263 * again when DispatchMessage returns. Thus, Windows internal
264 * modal loops are protected against throws, which are proven
265 * to corrupt internal Windows structures.
266 *
267 * In case of success, mswindows_error_caught_by_event_pump is
268 * assigned Qnil.
269 *
270 * If the value of mswindows_error_caught_by_event_pump is not
271 * nil already upon entry, the function just returns non-nil.
272 * This situation means that a new event has been queued while
273 * cancleng mode. The event will be dequeued on the next regular
274 * call of next-event; the pump is off since error is caught.
275 * The caller must *unconditionally* cancel modal loop if the
276 * value returned by this function is nil. Otherwise, everything
277 * will become frozen until the modal loop exits under normal
278 * condition (scrollbar drag is released, menu closed etc.)
279 */
280 Lisp_Object
281 mswindows_pump_outstanding_events (void)
282 {
283 /* This function can call lisp */
284
285 Lisp_Object result = Qt;
286
287 if (NILP(mswindows_error_caught_by_event_pump))
288 {
289
290 mswindows_in_event_pump = 1;
291
292 result = condition_case_1 (Qt,
293 mswindows_unsafe_pump_events, Qnil,
294 mswindows_event_pump_error_handler, Qnil);
295
296 mswindows_in_event_pump = 0;
297 }
298 return result;
299 }
300
301 /*
198 * Find a free waitable slot 302 * Find a free waitable slot
199 */ 303 */
200 static int 304 static int
201 mswindows_find_free_waitable(void) 305 mswindows_find_free_waitable(void)
202 { 306 {
265 { 369 {
266 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil); 370 Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
267 struct Lisp_Event *event = XEVENT (emacs_event); 371 struct Lisp_Event *event = XEVENT (emacs_event);
268 372
269 KillTimer (NULL, id_timer); 373 KillTimer (NULL, id_timer);
374 --mswindows_pending_timers_count;
270 375
271 event->channel = Qnil; 376 event->channel = Qnil;
272 event->timestamp = dwtime; 377 event->timestamp = dwtime;
273 event->event_type = timeout_event; 378 event->event_type = timeout_event;
274 event->event.timeout.interval_id = id_timer; 379 event->event.timeout.interval_id = id_timer;
279 static void 384 static void
280 mswindows_drain_windows_queue () 385 mswindows_drain_windows_queue ()
281 { 386 {
282 MSG msg; 387 MSG msg;
283 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) 388 while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
284 DispatchMessage (&msg); 389 {
390 DispatchMessage (&msg);
391 if (!NILP (mswindows_error_caught_by_event_pump))
392 {
393 /* Got an error while messages were pumped while
394 in window procedure - have to resignal */
395 Lisp_Object sym = XCAR (mswindows_error_caught_by_event_pump);
396 Lisp_Object data = XCDR (mswindows_error_caught_by_event_pump);
397 mswindows_error_caught_by_event_pump = Qnil;
398 Fsignal (sym, data);
399 }
400 }
401 }
402
403 /*
404 * This is a special flavour of the mswindows_need_event function,
405 * used while in event pump. Actually, there is only kind of events
406 * allowed while in event pump: a timer. An attempt to fetch any
407 * other event leads to a dealock, as there's no source of user input
408 * ('cause event pump mirrors windows modal loop, which is a sole
409 * owner of thread message queue).
410 *
411 * To detect this, we use a counter of active timers, and allow
412 * fetching WM_TIMER messages. Instead of trying to fetch a WM_TIMER
413 * which will never come when there are no pending timers, which leads
414 * to deadlock, we simply signal an error.
415 *
416 * The implementation does not honor user_p by design.
417 */
418 static void
419 mswindows_need_event_in_event_pump (int user_p, int badly_p)
420 {
421 MSG msg;
422
423 /* Check if already have one */
424 if (!NILP (mswindows_u_dispatch_event_queue)
425 || !NILP (mswindows_s_dispatch_event_queue))
426 return;
427
428 /* No event is ok */
429 if (!badly_p)
430 return;
431
432 /* We do not check the _u_ queue, because timers go to _s_ */
433 while (NILP (mswindows_s_dispatch_event_queue))
434 {
435 /* We'll deadlock if go waiting */
436 if (mswindows_pending_timers_count == 0)
437 error ("Deadlock due to an attempt to call next-event in a wrong context");
438
439 /* Fetch and dispatch any pending timers */
440 GetMessage (&msg, NULL, WM_TIMER, WM_TIMER);
441 DispatchMessage (&msg);
442 }
285 } 443 }
286 444
287 /* 445 /*
288 * This drains the event queue and fills up two internal queues until 446 * This drains the event queue and fills up two internal queues until
289 * an event of a type specified by USER_P is retrieved. 447 * an event of a type specified by USER_P is retrieved.
302 */ 460 */
303 static void 461 static void
304 mswindows_need_event (int user_p, int badly_p) 462 mswindows_need_event (int user_p, int badly_p)
305 { 463 {
306 int active; 464 int active;
465
466 if (mswindows_in_event_pump)
467 {
468 mswindows_need_event_in_event_pump (user_p, badly_p);
469 return;
470 }
307 471
308 /* Have to drain Windows message queue first, otherwise, we may miss 472 /* Have to drain Windows message queue first, otherwise, we may miss
309 quit char when called from quit_p */ 473 quit char when called from quit_p */
310 mswindows_drain_windows_queue (); 474 mswindows_drain_windows_queue ();
311 475
371 EMACS_SUB_TIME (thyme, thyme, current_time); 535 EMACS_SUB_TIME (thyme, thyme, current_time);
372 milliseconds = EMACS_SECS (thyme) * 1000 + 536 milliseconds = EMACS_SECS (thyme) * 1000 +
373 (EMACS_USECS (thyme) + 500) / 1000; 537 (EMACS_USECS (thyme) + 500) / 1000;
374 if (milliseconds < 1) 538 if (milliseconds < 1)
375 milliseconds = 1; 539 milliseconds = 1;
540 ++mswindows_pending_timers_count;
376 return SetTimer (NULL, 0, milliseconds, mswindows_wm_timer_callback); 541 return SetTimer (NULL, 0, milliseconds, mswindows_wm_timer_callback);
377 } 542 }
378 543
379 static void 544 static void
380 emacs_mswindows_remove_timeout (int id) 545 emacs_mswindows_remove_timeout (int id)
381 { 546 {
382 struct Lisp_Event match_against; 547 struct Lisp_Event match_against;
383 Lisp_Object emacs_event; 548 Lisp_Object emacs_event;
384 549
385 KillTimer (NULL, id); 550 KillTimer (NULL, id);
551 --mswindows_pending_timers_count;
386 552
387 /* If there is a dispatch event generated by this 553 /* If there is a dispatch event generated by this
388 timeout in the queue, we have to remove it too. */ 554 timeout in the queue, we have to remove it too. */
389 match_against.event_type = timeout_event; 555 match_against.event_type = timeout_event;
390 match_against.event.timeout.interval_id = id; 556 match_against.event.timeout.interval_id = id;
570 mswindows_u_dispatch_event_queue_tail = Qnil; 736 mswindows_u_dispatch_event_queue_tail = Qnil;
571 737
572 mswindows_s_dispatch_event_queue = Qnil; 738 mswindows_s_dispatch_event_queue = Qnil;
573 staticpro (&mswindows_s_dispatch_event_queue); 739 staticpro (&mswindows_s_dispatch_event_queue);
574 mswindows_s_dispatch_event_queue_tail = Qnil; 740 mswindows_s_dispatch_event_queue_tail = Qnil;
741
742 mswindows_error_caught_by_event_pump = Qnil;
743 staticpro (&mswindows_error_caught_by_event_pump);
744 mswindows_in_event_pump = 0;
745 mswindows_pending_timers_count = 0;
575 746
576 mswindows_event_stream = xnew (struct event_stream); 747 mswindows_event_stream = xnew (struct event_stream);
577 748
578 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p; 749 mswindows_event_stream->event_pending_p = emacs_mswindows_event_pending_p;
579 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event; 750 mswindows_event_stream->next_event_cb = emacs_mswindows_next_event;