Mercurial > hg > xemacs-beta
diff src/events.h @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/events.h Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,546 @@ +/* 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 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 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). + + 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 scrollbar misc-user events, channel + will be a window. + -- for menubar 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 most 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. + 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 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. + */ + + +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); +}; + + +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, object; +}; + +struct eval_data +{ + Lisp_Object function; + Lisp_Object object; +}; + +struct magic_eval_data +{ + void (*internal_function) (Lisp_Object); + 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 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 uses this too */ + 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 GC_EVENTP(x) GC_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 (! EVENTP (x) \ + || ! 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 (! 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 XEmacs 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)) + +Lisp_Object allocate_command_builder (Lisp_Object console); + +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); +void enqueue_magic_eval_event (void (*fun) (Lisp_Object), Lisp_Object object); +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 is 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); + +int event_stream_event_pending_p (int user); +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 *c); +void event_stream_unselect_console (struct console *c); +void event_stream_select_process (struct Lisp_Process *proc); +void event_stream_unselect_process (struct Lisp_Process *proc); +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); + +/* from signal.c */ +int event_stream_add_async_timeout (EMACS_TIME thyme); +void event_stream_remove_async_timeout (int id); + +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); + +#ifdef HAVE_UNIXOID_EVENT_LOOP +/* 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 *c, int fd); +#endif /* HAVE_UNIXOID_EVENT_LOOP */ + +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 console is tty, even if HAVE_X_WINDOWS is defined */ +/* #define DEBUG_TTY_EVENT_STREAM */ + +#endif /* emacs */ + +#endif /* _XEMACS_EVENTS_H_ */