This is events.h in view mode; [Download] [Up]
/* Definitions for the new event model; created 16-jul-91 by Jamie Zawinski Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. This file is part of XEmacs. XEmacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. XEmacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with XEmacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Synched up with: Not in FSF. */ #ifndef _XEMACS_EVENTS_H_ #define _XEMACS_EVENTS_H_ #include "systime.h" /* There is one object, called an event_stream. This object contains callback functions for doing the window-system dependent operations that emacs requires. If emacs is compiled with support for X11 and the X Toolkit, then this event_stream structure will contain functions that can cope with input on emacs windows on multiple displays, as well as input from dumb tty frames. If it is desired to have emacs able to open frames on the displays of multiple heterogeneous machines, X11 and SunView, or X11 and NeXT, for example, then it will be necessary to construct an event_stream structure that can cope with the given types. Currently, the only implemented event_streams are for dumb-ttys, and for X11 plus dumb-ttys. To implement this for one window system is relatively clean and simple. To implement this for multiple window systems is hard and hairy, so we are punting for now. The slots of the event_stream structure: next_event_cb A function which fills in an emacs_event struture with the next event available. If there is no event available, then this should block. IMPORTANT: timer events and especially process events *must not* be returned if there are events of other types available; otherwise you can end up with an infinite loop in Fdiscard_input(). event_pending_cb A function which says whether there are events to be read. If called with an argument of 0, then this should say whether calling the next_event_cb will block. If called with an argument of 1, then this should say whether there are user-generated events pending (that is, keypresses or mouse-clicks). This is used for redisplay optimization, among other things. On dumb ttys, these two results are the same, but under a window system, they are not. If this function is not sure whether there are events to be read, it *must* return 0. Otherwise various undesirable effects will occur, such as redisplay not occurring until the next event occurs. handle_magic_event_cb Emacs calls this with an event structure which contains window-system dependent information that emacs doesn't need to know about, but which must happen in order. If the next_event_cb never returns an event of type "magic", this will never be used. add_timeout_cb Called with an EMACS_TIME, the absolute time at which a wakeup event should be generated; and a void *, which is an arbitrary value that will be returned in the timeout event. The timeouts generated by this function should be one-shots: they fire once and then disappear. This callback should return an int id-number which uniquely identifies this wakeup. If an implementation doesn't have microseconds or millisecond granularity, it should round up to the closest value it can deal with. remove_timeout_cb Called with an int, the id number of a wakeup to discard. This id number must have been returned by the add_timeout_cb. If the given wakeup has already expired, this should do nothing. select_process_cb These callbacks tell the underlying implementation to unselect_process_cb add or remove a file descriptor from the list of fds which are polled for inferior-process input. When input becomes available on the given process connection, an event of type "process" should be generated. select_device_cb These callbacks tell the underlying implementation unselect_device_cb to add or remove a device from the list of devices which are polled for user-input. quitp_cb A handler function called from the `QUIT' macro which should check whether the quit character has been typed. On systems with SIGIO, this will not be called unless the `sigio_happened' flag is true (it is set from the SIGIO handler). Emacs has its own event structures, which are distinct from the event structures used by X or any other window system. It is the job of the event_stream layer to translate to this format. NOTE: All timestamps are measured as milliseconds since Emacs started. key_press_event event_channel A token representing which keyboard generated it. For this kind of event, this is a frame object. timestamp When it happened key What keysym this is; an integer or a symbol. If this is an integer, it will be in the printing ASCII range: >32 and <127. modifiers Bucky-bits on that key: control, meta, etc. For most keys, Shift is not a bit; that is implicit in the keyboard layout. button_press_event button_release_event event_channel A token representing which mouse generated it. For this kind of event, this is a frame object. timestamp When it happened button What button went down or up. modifiers Bucky-bits on that button: shift, control, meta, etc. x, y Where it was at the button-state-change (in pixels). pointer_motion_event event_channel A token representing which mouse generated it. For this kind of event, this is a frame object. timestamp When it happened x, y Where it was after it moved (in pixels). modifiers Bucky-bits down when the motion was detected. (Possibly not all window systems will provide this?) process_event timestamp When it happened process the emacs "process" object in question timeout_event timestamp Now (really, when the timeout was signalled) interval_id The ID returned when the associated call to add_timeout_cb() was made ------ the rest of the fields are filled in by Emacs ----- id_number The Emacs timeout ID for this timeout (more than one timeout event can have the same value here, since Emacs timeouts, as opposed to add_timeout_cb() timeouts, can resignal themselves) function An elisp function to call when this timeout is processed. object The object passed to that function. eval_event timestamp When it happened function An elisp function to call with this event object. object Anything. This kind of event is used internally; sometimes the window system interface would like to inform emacs of some user action (such as focusing on another frame) but needs that to happen synchronously with the other user input, like keypresses. This is useful when events are reported through callbacks rather than in the standard event stream. misc_user_event timestamp When it happened function An elisp function to call with this event object. object Anything. This is similar to an eval_event, except that it is generated by user actions: selections in the menubar or scrollbar actions. It is a "command" event, like key and mouse presses (and unlike mouse motion, process output, and enter and leave window hooks). In many ways, eval_events are not the same as keypresses or misc_user_events. magic_event No user-serviceable parts within. This is for things like KeymapNotify and ExposeRegion events and so on that emacs itself doesn't care about, but which it must do something with for proper interaction with the window system. Magic_events are handled somewhat asynchronously, just like subprocess filters. However, occasionally a magic_event needs to be handled synchronously; in that case, the asynchronous handling of the magic_event will push an eval_event back onto the queue, which will be handled synchronously later. This is one of the reasons why eval_events exist; I'm not entirely happy with this aspect of this event model. */ struct Lisp_Event; struct Lisp_Process; struct event_stream { int (*event_pending_p) (int); void (*next_event_cb) (struct Lisp_Event *); void (*handle_magic_event_cb) (struct Lisp_Event *); int (*add_timeout_cb) (EMACS_TIME); void (*remove_timeout_cb) (int); void (*select_device_cb) (struct device *); void (*unselect_device_cb) (struct device *); void (*select_process_cb) (struct Lisp_Process *); void (*unselect_process_cb) (struct Lisp_Process *); void (*quit_p_cb) (void); }; extern struct event_stream *event_stream; typedef enum emacs_event_type { empty_event, key_press_event, button_press_event, button_release_event, pointer_motion_event, process_event, timeout_event, magic_event, eval_event, misc_user_event, dead_event } emacs_event_type; #define first_event_type empty_event #define last_event_type dead_event struct key_data { Lisp_Object keysym; unsigned char modifiers; }; struct button_data { int button; unsigned char modifiers; int x, y; }; struct motion_data { int x, y; unsigned char modifiers; }; struct process_data { Lisp_Object process; }; struct timeout_data { int interval_id; int id_number; Lisp_Object function, object; }; struct eval_data { Lisp_Object function; Lisp_Object object; }; #if defined (HAVE_X_WINDOWS) && defined(emacs) # include <X11/Xlib.h> #endif #if defined (HAVE_NEXTSTEP) && defined(emacs) # import <appkit/appkit.h> #endif union magic_data { char underlying_tty_event; #ifdef HAVE_X_WINDOWS XEvent underlying_x_event; #endif #ifdef HAVE_NEXTSTEP NXEvent underlying_ns_event; #endif }; struct Lisp_Event { /* header->next (aka event_next ()) is used as follows: - For dead events, this is the next dead one. - For events on the command_event_queue, the next one on the queue. - Otherwise it's 0. */ struct lrecord_header lheader; struct Lisp_Event *next; emacs_event_type event_type; Lisp_Object channel; Lisp_Object device; unsigned int timestamp; union { struct key_data key; struct button_data button; struct motion_data motion; struct process_data process; struct timeout_data timeout; struct eval_data eval; /* misc_user_event uses this too */ union magic_data magic; } event; }; DECLARE_LRECORD (event, struct Lisp_Event); #define XEVENT(x) XRECORD (x, event, struct Lisp_Event) #define XSETEVENT(x, p) XSETRECORD (x, p, event) #define EVENTP(x) RECORDP (x, event) #define CHECK_EVENT(x, i) CHECK_RECORD (x, event) #define EVENT_DEVICE(a) ((a)->device) #define EVENT_TYPE(a) ((a)->event_type) #define event_next(a) ((a)->next) #define set_event_next(a, n) do { ((a)->next = (n)); } while (0) #define EVENT_LIVE_P(a) (EVENT_TYPE (a) != dead_event) #define CHECK_LIVE_EVENT(x, i) \ do { CHECK_EVENT (x, i); \ if (! EVENTP (x) \ || ! EVENT_LIVE_P (XEVENT (x))) \ x = wrong_type_argument (Qevent_live_p, (x)); } while (0) extern Lisp_Object Qevent_live_p; /* The modifiers emacs knows about; these appear in key and button events. */ #define MOD_CONTROL (1<<0) #define MOD_META (1<<1) #define MOD_SUPER (1<<2) #define MOD_HYPER (1<<3) #define MOD_ALT (1<<4) #define MOD_SHIFT (1<<5) /* not used for dual-case characters */ /* Note: under X Windows, MOD_ALT is generated by the Alt key if there are both Alt and Meta keys. If there are no Meta keys, then Alt generates MOD_META instead. */ #ifdef emacs /* Maybe this should be trickier */ #define KEYSYM(x) (intern (x)) extern void format_event_object (char *buf, struct Lisp_Event *e, int brief); extern void character_to_event (Emchar c, struct Lisp_Event *event, struct device *d); /* True is this is a non-internal event (keyboard press, menu, scrollbar, mouse button) */ extern int command_event_p (struct Lisp_Event *event); extern int event_stream_event_pending_p (int user); extern void event_stream_next_event (struct Lisp_Event *event); extern void event_stream_handle_magic_event (struct Lisp_Event *event); extern void event_stream_select_device (struct device *d); extern void event_stream_unselect_device (struct device *d); extern void event_stream_select_process (struct Lisp_Process *proc); extern void event_stream_unselect_process (struct Lisp_Process *proc); extern void event_stream_quit_p (void); struct low_level_timeout { int id; EMACS_TIME time; struct low_level_timeout *next; }; extern int add_low_level_timeout (struct low_level_timeout **timeout_list, EMACS_TIME time); extern void remove_low_level_timeout (struct low_level_timeout **timeout_list, int id); extern int get_low_level_timeout_interval (struct low_level_timeout * timeout_list, EMACS_TIME *interval); extern int pop_low_level_timeout (struct low_level_timeout **timeout_list, EMACS_TIME *time_out); extern int event_stream_generate_wakeup (unsigned int milliseconds, unsigned int vanilliseconds, Lisp_Object function, Lisp_Object object, int async_p); extern void event_stream_deal_with_async_timeout (int interval_id); /* from signal.c */ extern int event_stream_add_async_timeout (EMACS_TIME time); extern void event_stream_remove_async_timeout (int id); /* Ceci n'est pas un pipe. */ extern int signal_event_pipe[]; extern void signal_fake_event (void); extern void drain_signal_event_pipe (void); extern int emacs_is_blocking; extern Lisp_Object Vcontrolling_terminal; extern volatile int sigint_happened; /* Define this if you want the tty event stream to be used when the first device is tty, even if HAVE_X_WINDOWS is defined */ /* #define DEBUG_TTY_EVENT_STREAM */ #endif /* emacs */ #endif /* _XEMACS_EVENTS_H_ */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.