Mercurial > hg > xemacs-beta
diff src/events.h @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 3a7e78e1142d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/events.h Mon Aug 13 11:28:15 2007 +0200 @@ -0,0 +1,663 @@ +/* Definitions for the new event model; + created 16-jul-91 by Jamie Zawinski + Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1995, 1996 Ben Wing. + +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, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, 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 XEmacs requires. + + If XEmacs is compiled with support for X11 and the X Toolkit, then this + event_stream structure will contain functions that can cope with input + on XEmacs windows on multiple displays, as well as input from dumb tty + frames. + + If it is desired to have XEmacs 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 simple. + To implement this for multiple window systems is trickier and may + not be possible in all situations, but it's been done for X and TTY. + + Note that these callbacks are *NOT* console methods; that's because + the routines are not specific to a particular console type but must + be able to simultaneously cope with all allowable console types. + + The slots of the event_stream structure: + + next_event_cb A function which fills in an XEmacs_event structure + 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 XEmacs calls this with an event structure which + contains window-system dependent information that + XEmacs 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_console_cb These callbacks tell the underlying implementation + unselect_console_cb to add or remove a console from the list of consoles + which are polled for user-input. + + select_device_cb These callbacks are used by Unixoid event loops + unselect_device_cb (those that use select() and file descriptors and + have a separate input fd per device). + + create_stream_pair_cb These callbacks are called by process code to + delete_stream_pair_cb create and delete a pair of input and output lstreams + which are used for subprocess I/O. + + 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). + + XEmacs 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 should be measured as milliseconds since XEmacs + started. Currently many or most events have a 0 as their + timestamp value, and for other timestamps, they are raw server + timestamps. (The X protocol doesn't provide any easy way of + translating between server time and real process time; yuck.) + + Every event type has the following structures: + + channel Where this event occurred on. This will be + a frame, device, console, or nil, depending on the + event type. It is important that an object of + a more specific type than is actually generated + is not substituted -- e.g. there should not be + a frame inserted when a key-press event occurs, + because events on dead channels are automatically + ignored. + + Specifically: + + -- for button and mouse-motion events, channel + will be a frame. (The translation to a window + occurs later.) + -- for keyboard events, channel will be a console. + Note that fake keyboard events (generated + by `character-to-event' or something that + calls this, such as macros) need to have + the selected console stored into them when + the event is created. This is so that the + correct console-local variables (e.g. the + command builder) will get affected. + -- for timer, process, magic-eval, and eval events, + channel will be nil. + -- for misc-user events, channel will be a frame. + -- for magic events, channel will be a frame + (usually) or a device. + + timestamp When this event occurred -- if not known, this + is made up. + + In addition, the following structures are specific to particular event + types: + + key_press_event + 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 many keys, Shift is not a bit; that is implicit + in the keyboard layout. + + button_press_event + button_release_event + 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 + 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 + process the XEmacs "process" object in question + + timeout_event + interval_id The ID returned when the associated call to + add_timeout_cb() was made + ------ the rest of the fields are filled in by XEmacs ----- + id_number The XEmacs timeout ID for this timeout (more + than one timeout event can have the same value + here, since XEmacs 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 + function An elisp function to call with this event object. + internal_function An unexported function to call with this event + object. This allows eval events to call internal + functions. For a normal eval event, this field + will always be 0. + object Anything. + This kind of event is used internally; sometimes the + window system interface would like to inform XEmacs 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 + function An elisp function to call with this event object. + internal_function Ignored. + object Anything. + 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). + This is similar to an eval_event, except that it is + generated by user actions: selections in the + menubar, scrollbar actions, or drag and drop 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. + The button, modifiers, x, and y parts are only used + by the XEmacs Drag'n'Drop system. Don't depend on their + values for other types of misc_user_events. + + magic_event + No user-serviceable parts within. This is for things + like KeymapNotify and ExposeRegion events and so on + that XEmacs 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. + + magic_eval_event + This is like an eval event but its contents are + not Lisp-accessible. This allows for "internal + eval events" that call non-Lisp-accessible functions. + Externally, a magic_eval_event just appears as + a magic_event; the Lisp programmer need not know + anything more. + +*/ + +/* + Stream pairs description + ------------------------ + + Since there are many possible processes/event loop combinations, the event code + is responsible for creating an appropriate lstream type. The process + implementation does not care about that implementation. + + The Create stream pair function is passed two void* values, which identify + process-dependent 'handles'. The process implementation uses these handles + to communicate with child processes. The function must be prepared to receive + handle types of any process implementation. Since there only one process + implementation exists in a particular XEmacs configuration, preprocessing + is a mean of compiling in the support for the code which deals with particular + handle types. + + For example, a unixoid type loop, which relies on file descriptors, may be + asked to create a pair of streams by a unix-style process implementation. + In this case, the handles passed are unix file descriptors, and the code + may deal with these directly. Although, the same code may be used on Win32 + system with X-Windows. In this case, Win32 process implementation passes + handles of type HANDLE, and the create_stream_pair function must call + appropriate function to get file descriptors given HANDLEs, so that these + descriptors may be passed to XtAddInput. + + The handle given may have special denying value, in which case the + corresponding lstream should not be created. + + The return value of the function is a unique stream identifier. It is used + by processes implementation, in its platform-independent part. There is + the get_process_from_usid function, which returns process object given its + USID. The event stream is responsible for converting its internal handle + type into USID. + + Example is the TTY event stream. When a file descriptor signals input, the + event loop must determine process to which the input is destined. Thus, + the implementation uses process input stream file descriptor as USID, by + simply casting the fd value to USID type. + + There are two special USID values. One, USID_ERROR, indicates that the stream + pair cannot be created. The second, USID_DONTHASH, indicates that streams are + created, but the event stream does not wish to be able to find the process + by its USID. Specifically, if an event stream implementation never calls + get_process_from_usid, this value should always be returned, to prevent + accumulating useless information on USID to process relationship. +*/ + +/* typedef unsigned int USID; in lisp.h */ +#define USID_ERROR ((USID)-1) +#define USID_DONTHASH ((USID)0) + + +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_console_cb) (struct console *); + void (*unselect_console_cb) (struct console *); + void (*select_process_cb) (struct Lisp_Process *); + void (*unselect_process_cb) (struct Lisp_Process *); + void (*quit_p_cb) (void); + USID (*create_stream_pair_cb) (void* /* inhandle*/, void* /*outhandle*/ , + Lisp_Object* /* instream */, + Lisp_Object* /* outstream */, + int /* flags */); + USID (*delete_stream_pair_cb) (Lisp_Object /* instream */, + Lisp_Object /* outstream */); +}; + +/* Flags for create_stream_pair_cb() FLAGS parameter */ +#define STREAM_PTY_FLUSHING 0x0001 +#define STREAM_NETWORK_CONNECTION 0x0002 + +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, + magic_eval_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; + Lisp_Object object; +}; + +struct eval_data +{ + Lisp_Object function; + Lisp_Object object; +}; + +struct misc_user_data +{ + Lisp_Object function; + Lisp_Object object; + int button; + unsigned char modifiers; + int x, y; +}; + +struct magic_eval_data +{ + void (*internal_function) (Lisp_Object); + Lisp_Object object; +}; + +#if defined (HAVE_X_WINDOWS) && defined(emacs) +# include <X11/Xlib.h> +#endif + +union magic_data +{ +#ifdef HAVE_TTY + char underlying_tty_event; +#endif +#ifdef HAVE_X_WINDOWS + XEvent underlying_x_event; +#endif +#ifdef HAVE_MS_WINDOWS + int underlying_mswindows_event; +#endif +}; + +struct Lisp_Timeout +{ + struct lcrecord_header header; + int id; /* Id we use to identify the timeout over its lifetime */ + int interval_id; /* Id for this particular interval; this may + be different each time the timeout is + signalled.*/ + Lisp_Object function, object; /* Function and object associated + with timeout. */ + EMACS_TIME next_signal_time; /* Absolute time when the timeout + is next going to be signalled. */ + unsigned int resignal_msecs; /* How far after the next timeout + should the one after that + occur? */ +}; + +DECLARE_LRECORD (timeout, struct Lisp_Timeout); +#define XTIMEOUT(x) XRECORD (x, timeout, struct Lisp_Timeout) +#define XSETTIMEOUT(x, p) XSETRECORD (x, p, timeout) +#define TIMEOUTP(x) RECORDP (x, timeout) +#define CHECK_TIMEOUT(x) CHECK_RECORD (x, timeout) +#define CONCHECK_TIMEOUT(x) CONCHECK_RECORD (x, timeout) + +struct Lisp_Event +{ + /* header->next (aka XEVENT_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. + - Likewise for events chained in the command builder. + - Otherwise it's Qnil. + */ + struct lrecord_header lheader; + Lisp_Object next; + emacs_event_type event_type; + Lisp_Object channel; + 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 no longer uses this */ + struct misc_user_data misc; /* because it needs position information */ + union magic_data magic; + struct magic_eval_data magic_eval; + } 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) CHECK_RECORD (x, event) +#define CONCHECK_EVENT(x) CONCHECK_RECORD (x, event) + +DECLARE_LRECORD (command_builder, struct command_builder); + +#define EVENT_CHANNEL(a) ((a)->channel) +#define EVENT_TYPE(a) ((a)->event_type) +#define XEVENT_TYPE(a) (XEVENT (a)->event_type) +#define EVENT_NEXT(a) ((a)->next) +#define XEVENT_NEXT(e) (XEVENT (e)->next) +#define XSET_EVENT_NEXT(e, n) do { (XEVENT (e)->next = (n)); } while (0) + +#define EVENT_CHAIN_LOOP(event, chain) \ + for (event = chain; !NILP (event); event = XEVENT_NEXT (event)) + +#define EVENT_LIVE_P(a) (EVENT_TYPE (a) != dead_event) + +#define CHECK_LIVE_EVENT(x) do { \ + CHECK_EVENT (x); \ + if (! EVENT_LIVE_P (XEVENT (x))) \ + dead_wrong_type_argument (Qevent_live_p, (x)); \ +} while (0) +#define CONCHECK_LIVE_EVENT(x) do { \ + CONCHECK_EVENT (x); \ + if (! EVENT_LIVE_P (XEVENT (x))) \ + x = wrong_type_argument (Qevent_live_p, (x)); \ +} while (0) + + +EXFUN (Fcharacter_to_event, 4); +EXFUN (Fdeallocate_event, 1); +EXFUN (Fevent_glyph_extent, 1); +EXFUN (Fevent_modeline_position, 1); +EXFUN (Fevent_over_modeline_p, 1); +EXFUN (Fevent_over_toolbar_p, 1); +EXFUN (Fevent_over_vertical_divider_p, 1); +EXFUN (Fevent_point, 1); +EXFUN (Fevent_window, 1); +EXFUN (Fmake_event, 2); + +extern Lisp_Object QKbackspace, QKdelete, QKescape, QKlinefeed, QKreturn; +extern Lisp_Object QKspace, QKtab, Qmouse_event_p, Vcharacter_set_property; +extern Lisp_Object Qcancel_mode_internal; + +/* 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)) + +/* from events.c */ +void format_event_object (char *buf, struct Lisp_Event *e, int brief); +void character_to_event (Emchar c, struct Lisp_Event *event, + struct console *con, + int use_console_meta_flag, + int do_backspace_mapping); +void zero_event (struct Lisp_Event *e); +void deallocate_event_chain (Lisp_Object event); +Lisp_Object event_chain_tail (Lisp_Object event); +void enqueue_event (Lisp_Object event, Lisp_Object *head, Lisp_Object *tail); +Lisp_Object dequeue_event (Lisp_Object *head, Lisp_Object *tail); +void enqueue_event_chain (Lisp_Object event_chain, Lisp_Object *head, + Lisp_Object *tail); +int event_chain_count (Lisp_Object event_chain); +void nth_of_key_sequence_as_event (Lisp_Object seq, int n, Lisp_Object event); +Lisp_Object key_sequence_to_event_chain (Lisp_Object seq); +Lisp_Object event_chain_find_previous (Lisp_Object event_chain, + Lisp_Object event); +Lisp_Object event_chain_nth (Lisp_Object event_chain, int n); +Lisp_Object copy_event_chain (Lisp_Object event_chain); +/* True if this is a non-internal event + (keyboard press, menu, scrollbar, mouse button) */ +int command_event_p (Lisp_Object event); +struct console *event_console_or_selected (Lisp_Object event); + +/* from event-stream.c */ +Lisp_Object allocate_command_builder (Lisp_Object console); +void enqueue_magic_eval_event (void (*fun) (Lisp_Object), Lisp_Object object); +void event_stream_next_event (struct Lisp_Event *event); +void event_stream_handle_magic_event (struct Lisp_Event *event); +void event_stream_select_console (struct console *con); +void event_stream_unselect_console (struct console *con); +void event_stream_select_process (struct Lisp_Process *proc); +void event_stream_unselect_process (struct Lisp_Process *proc); +USID event_stream_create_stream_pair (void* inhandle, void* outhandle, + Lisp_Object* instream, Lisp_Object* outstream, int flags); +USID event_stream_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream); +void event_stream_quit_p (void); + +struct low_level_timeout +{ + int id; + EMACS_TIME time; + struct low_level_timeout *next; +}; + +int add_low_level_timeout (struct low_level_timeout **timeout_list, + EMACS_TIME thyme); +void remove_low_level_timeout (struct low_level_timeout **timeout_list, + int id); +int get_low_level_timeout_interval (struct low_level_timeout * + timeout_list, EMACS_TIME *interval); +int pop_low_level_timeout (struct low_level_timeout **timeout_list, + EMACS_TIME *time_out); +int event_stream_generate_wakeup (unsigned int milliseconds, + unsigned int vanilliseconds, + Lisp_Object function, + Lisp_Object object, + int async_p); +void event_stream_disable_wakeup (int id, int async_p); +void event_stream_deal_with_async_timeout (int interval_id); + +int event_stream_add_async_timeout (EMACS_TIME thyme); +void event_stream_remove_async_timeout (int id); + +/* from event-stream.c -- focus sanity */ +extern int focus_follows_mouse; +void investigate_frame_change (void); + +void emacs_handle_focus_change_preliminary (Lisp_Object frame_inp_and_dev); +void emacs_handle_focus_change_final (Lisp_Object frame_inp_and_dev); + +Lisp_Object extract_this_command_keys_nth_mouse_event (int n); +Lisp_Object extract_vector_nth_mouse_event (Lisp_Object vector, int n); + +void single_console_state (void); +void any_console_state (void); +int in_single_console_state (void); + +extern int emacs_is_blocking; + +extern volatile int sigint_happened; + +#ifdef HAVE_UNIXOID_EVENT_LOOP +/* from event-unixoid.c */ + +/* Ceci n'est pas un pipe. */ +extern int signal_event_pipe[]; + +void signal_fake_event (void); +void drain_signal_event_pipe (void); + +extern int fake_event_occurred; + +int event_stream_unixoid_select_console (struct console *con); +int event_stream_unixoid_unselect_console (struct console *con); +int event_stream_unixoid_select_process (struct Lisp_Process *proc); +int event_stream_unixoid_unselect_process (struct Lisp_Process *proc); +int read_event_from_tty_or_stream_desc (struct Lisp_Event *event, + struct console *con, int fd); +USID event_stream_unixoid_create_stream_pair (void* inhandle, void* outhandle, + Lisp_Object* instream, + Lisp_Object* outstream, + int flags); +USID event_stream_unixoid_delete_stream_pair (Lisp_Object instream, + Lisp_Object outstream); + +/* Beware: this evil macro evaluates its arg many times */ +#define FD_TO_USID(fd) ((fd)==0 ? (USID)999999 : ((fd)<0 ? USID_DONTHASH : (USID)(fd))) + +#endif /* HAVE_UNIXOID_EVENT_LOOP */ + +/* Define this if you want the tty event stream to be used when the + first console is tty, even if HAVE_X_WINDOWS is defined */ +/* #define DEBUG_TTY_EVENT_STREAM */ + +#endif /* emacs */ + +#endif /* _XEMACS_EVENTS_H_ */