comparison src/event-gtk.c @ 1268:fffe735e63ee

[xemacs-hg @ 2003-02-07 11:50:50 by ben] fixes for menu crashes + better preemption behavior This contains two related changes: (1) Fix problems with reentrant calling of lwlib and associated crashes when selecting menu items. (2) Improve redisplay handling of preemption. Turn on lazy lock and hold down page-down or page-up and you'll see what I mean. They are related because they both touch on the code that retrieves events and handles the internal queues. console-msw.h, event-msw.c, event-stream.c, events.h, menubar-msw.c, menubar-x.c, menubar.h: mswindows_protect_modal_loop() has been generalized to event_stream_protect_modal_loop(), and moved to event-stream.c. mswindows_in_modal_loop ->in_modal_loop likewise. Changes in event-msw.c and menubar-msw.c for the new names and calling format (use structures instead of static variables in menubar-msw.c). Delete former in_menu_callback and use in_modal_loop in its place. Remove emacs_mswindows_quit_check_disallowed_p(), superseded by in_modal_loop. Use event_stream_protect_modal_loop() in pre_activate_callback() so that we get no lwlib reentrancy. Rearrange some of the code in event-msw.c to be grouped better. Make mswindows_drain_windows_queue() respect in_modal_loop and do nothing if so. cmdloop.c, event-stream.c: Don't conditionalize on LWLIB_MENUBARS_LUCID when giving error when in_modal_loop, and give better error. event-Xt.c, event-gtk.c: If in_modal_loop, only retrieve process and timeout events. Don't retrieve any X events because processing them can lead to reentrancy in lwlib -> death. event-stream.c: Remove unused parameter to check_event_stream_ok() and change all callers. lisp.h, event-stream.c: Rearrange some functions for increased clarity -- in particular, group all the input-pending/QUIT-related stuff together, and put right next to next-event stuff, to which it's related. Add the concept of "HOW_MANY" -- when asking whether user input is pending, you can ask if at least HOW_MANY events are pending, not just if any are. Add parameter to detect_input_pending() for this. Change recursive_sit_for from a Lisp_Object (which could only be Qt or Qnil) to an int, like it should be. event-Xt.c, event-gtk.c, event-xlike-inc.c: New file. Abstract out similar code in event_{Xt/gtk}_pending_p() and write only once, using include-file tricks. Rewrite this function to implement HOW_MANY and only process events when not in_modal_loop. event-msw.c: Implement HOW_MANY and only process events when not in_modal_loop. event-tty.c: Implement HOW_MANY. redisplay.c: Add var `max-preempts' to control maximum number of preempts. (#### perhaps not useful) Rewrite preemption check so that, rather than preempting when any user events are available, only preempt when a certain number (currently 4) of them are backed up. This effectively allows redisplay to proceed to completion in the presence of a fast auto-repeat (usually the auto-repeating is generated dynamically as necessary), and you get much better display behavior with lazy-lock active. event-unixoid.c: Comment changes. event-stream.c: Rewrite discard-input much more simply and safely using the drain-queue functions. I think the old version might loop forever if called when in_modal_loop. SEMI-UNRELATED CHANGES: ----------------------- event-stream.c: Turn QUIT-checking back on when running the pre-idle hook so it can be quit out of. indent.c: Document exact functioning of `vertical-motion' better, and its differences from GNU Emacs.
author ben
date Fri, 07 Feb 2003 11:50:54 +0000
parents e22b0213b713
children f3437b56874d
comparison
equal deleted inserted replaced
1267:c57f32e44416 1268:fffe735e63ee
1 /* The event_stream interface for X11 with gtk, and/or tty frames. 1 /* The event_stream interface for X11 with gtk, and/or tty frames.
2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc. 2 Copyright (C) 1991-5, 1997 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1996, 2001, 2002 Ben Wing. 4 Copyright (C) 1996, 2001, 2002, 2003 Ben Wing.
5 Copyright (C) 2000 William Perry. 5 Copyright (C) 2000 William Perry.
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
91 #define IS_MODIFIER_KEY(keysym) \ 91 #define IS_MODIFIER_KEY(keysym) \
92 ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R)) \ 92 ((((keysym) >= GDK_Shift_L) && ((keysym) <= GDK_Hyper_R)) \
93 || ((keysym) == GDK_Mode_switch) \ 93 || ((keysym) == GDK_Mode_switch) \
94 || ((keysym) == GDK_Num_Lock)) 94 || ((keysym) == GDK_Num_Lock))
95 95
96 #define THIS_IS_GTK
97 #include "event-xlike-inc.c"
96 98
97 99
98 /************************************************************************/ 100 /************************************************************************/
99 /* magic-event handling */ 101 /* magic-event handling */
100 /************************************************************************/ 102 /************************************************************************/
1554 */ 1556 */
1555 if (GDK_DISPLAY ()) 1557 if (GDK_DISPLAY ())
1556 while (gdk_events_pending ()) 1558 while (gdk_events_pending ())
1557 gtk_main_iteration (); 1559 gtk_main_iteration ();
1558 1560
1561 #ifdef HAVE_TTY
1559 drain_tty_devices (); 1562 drain_tty_devices ();
1560 }
1561
1562 static int
1563 emacs_gtk_event_pending_p (int user_p)
1564 {
1565 Lisp_Object event;
1566 int tick_count_val;
1567
1568 /* If `user_p' is false, then this function returns whether there are any
1569 X, timeout, or fd events pending (that is, whether emacs_gtk_next_event()
1570 would return immediately without blocking).
1571
1572 if `user_p' is true, then this function returns whether there are any
1573 *user generated* events available (that is, whether there are keyboard
1574 or mouse-click events ready to be read). This also implies that
1575 emacs_Xt_next_event() would not block.
1576
1577 In a non-SIGIO world, this also checks whether the user has typed ^G,
1578 since this is a convenient place to do so. We don't need to do this
1579 in a SIGIO world, since input causes an interrupt.
1580 */
1581
1582 /* This function used to simply check whether there were any X
1583 events (or if user_p was 1, it iterated over all the pending
1584 X events using XCheckIfEvent(), looking for keystrokes and
1585 button events). That worked in the old cheesoid event loop,
1586 which didn't go through XtAppDispatchEvent(), but it doesn't
1587 work any more -- X events may not result in anything. For
1588 example, a button press in a blank part of the menubar appears
1589 as an X event but will not result in any Emacs events (a
1590 button press that activates the menubar results in an Emacs
1591 event through the stop_next_event mechanism).
1592
1593 The only accurate way of determining whether these X events
1594 translate into Emacs events is to go ahead and dispatch them
1595 until there's something on the dispatch queue. */
1596
1597 /* See if there are any user events already on the queue. */
1598 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
1599 if (!user_p || command_event_p (event))
1600 return 1;
1601
1602 /* See if there's any TTY input available.
1603 */
1604 if (poll_fds_for_input (tty_only_mask))
1605 return 1;
1606
1607 if (!user_p)
1608 {
1609 /* If not user_p and there are any timer or file-desc events
1610 pending, we know there will be an event so we're through. */
1611 /* XtInputMask pending_value; */
1612
1613 /* Note that formerly we just checked the value of XtAppPending()
1614 to determine if there was file-desc input. This doesn't
1615 work any more with the signal_event_pipe; XtAppPending()
1616 will says "yes" in this case but there isn't really any
1617 input. Another way of fixing this problem is for the
1618 signal_event_pipe to generate actual input in the form
1619 of an identity eval event or something. (#### maybe this
1620 actually happens?) */
1621
1622 if (poll_fds_for_input (process_only_mask))
1623 return 1;
1624
1625 /* #### Is there any way to do this in Gtk? I don't think there
1626 is a 'peek' for events */
1627 #if 0
1628 pending_value = XtAppPending (Xt_app_con);
1629
1630 if (pending_value & XtIMTimer)
1631 return 1;
1632 #endif 1563 #endif
1633 }
1634
1635 /* XtAppPending() can be super-slow, esp. over a network connection.
1636 Quantify results have indicated that in some cases the
1637 call to detect_input_pending() completely dominates the
1638 running time of redisplay(). Fortunately, in a SIGIO world
1639 we can more quickly determine whether there are any X events:
1640 if an event has happened since the last time we checked, then
1641 a SIGIO will have happened. On a machine with broken SIGIO,
1642 we'll still be in an OK state -- the sigio_happened flag
1643 will get set at least once a second, so we'll be no more than
1644 one second behind reality. (In general it's OK if we
1645 erroneously report no input pending when input is actually
1646 pending() -- preemption is just a bit less efficient, that's
1647 all. It's bad bad bad if you err the other way -- you've
1648 promised that `next-event' won't block but it actually will,
1649 and some action might get delayed until the next time you
1650 hit a key.)
1651 */
1652
1653 /* quit_check_signal_tick_count is volatile so try to avoid race conditions
1654 by using a temporary variable */
1655 tick_count_val = quit_check_signal_tick_count;
1656 if (last_quit_check_signal_tick_count != tick_count_val)
1657 {
1658 last_quit_check_signal_tick_count = tick_count_val;
1659
1660 /* We need to drain the entire queue now -- if we only
1661 drain part of it, we may later on end up with events
1662 actually pending but detect_input_pending() returning
1663 false because there wasn't another SIGIO. */
1664
1665 emacs_gtk_drain_queue ();
1666
1667 EVENT_CHAIN_LOOP (event, dispatch_event_queue)
1668 if (!user_p || command_event_p (event))
1669 return 1;
1670 }
1671
1672 return 0;
1673 } 1564 }
1674 1565
1675 static void 1566 static void
1676 emacs_gtk_force_event_pending (struct frame* f) 1567 emacs_gtk_force_event_pending (struct frame* f)
1677 { 1568 {