Mercurial > emacs
changeset 1310:8db103d11270
* keyboard.c (echo_char, read_char): Apply EVENT_HEAD without first
testing for EVENT_HAS_PARAMETERS; EVENT_HEAD works properly on
all sorts of events now.
(read_key_sequence): Use the new accessors to decide in which window
an event occurred.
* keyboard.c (Qevent_unmodified): Replaced by...
(Qevent_symbol_elements): New property.
(syms_of_keyboard): initialize and staticpro the latter, not the
former.
* keyboard.c (readable_events): This doesn't need to scan and
discard mouse release events anymore; it just uses
EVENT_QUEUES_EMPTY.
(kbd_buffer_get_event): No need to skip past mouse release events.
* keyboard.c (button_down_location): New variable, which
stores the location at which each button was pressed, so we
can build a complete drag event when the button is released.
(make_lispy_event): When a button is pressed, record its
location in button_down_location, and turn it into a `down'
event. When a button is released, compare its release
location with its press location, and decide whether to call
it a `click' or `drag' event.
Change mouse movement events to be arranged like click events.
(format_modifiers): Note that the click modifier has no
written representation.
(modifier_names, modifer_symbols): New variables, used to
create the Qevent_symbol_elements property.
(modify_event_symbol): Change the format of the modified
symbol cache; there are too many modifier bits now to use a
vector indexed by a modifier mask. Use an assoc-list instead.
Document the format of the cache.
Put the Qevent_symbol_elements property on each new symbol,
instead of a Qevent_unmodified property.
(symbols_of_keyboard): Put Qevent_symbol_elements properties on
the symbols specified in head_table, not Qevent_unmodifed properties.
Initialize and staticpro modifier_symbols, and staticpro the
window elements of button_down_location.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Fri, 02 Oct 1992 23:55:39 +0000 |
parents | aa286e6e7bec |
children | 339a82d29dfa |
files | src/keyboard.c |
diffstat | 1 files changed, 210 insertions(+), 142 deletions(-) [+] |
line wrap: on
line diff
--- a/src/keyboard.c Fri Oct 02 23:52:26 1992 +0000 +++ b/src/keyboard.c Fri Oct 02 23:55:39 1992 +0000 @@ -293,7 +293,7 @@ /* Properties of event headers. */ Lisp_Object Qevent_kind; -Lisp_Object Qevent_unmodified; +Lisp_Object Qevent_symbol_elements; /* Symbols to use for non-text mouse positions. */ Lisp_Object Qmode_line; @@ -392,8 +392,7 @@ *ptr++ = ' '; /* If someone has passed us a composite event, use its head symbol. */ - if (EVENT_HAS_PARAMETERS (c)) - c = EVENT_HEAD (c); + c = EVENT_HEAD (c); if (XTYPE (c) == Lisp_Int) { @@ -1283,8 +1282,7 @@ Lisp_Object dribblee = c; /* If it's a structured event, take the event header. */ - if (EVENT_HAS_PARAMETERS (dribblee)) - dribblee = EVENT_HEAD (dribblee); + dribblee = EVENT_HEAD (dribblee); if (XTYPE (c) == Lisp_Symbol) { @@ -1385,30 +1383,7 @@ static int readable_events () { - struct input_event *ep; - - if (EVENT_QUEUES_EMPTY) - return 0; - - if (do_mouse_tracking) - return 1; - - /* Mouse tracking is disabled, so we need to actually scan the - input queue to see if any events are currently readable. */ - for (ep = kbd_fetch_ptr; ep != kbd_store_ptr; ep++) - { - if (ep == kbd_buffer + KBD_BUFFER_SIZE) - ep = kbd_buffer; - - /* Skip button-up events. */ - if ((ep->kind == mouse_click || ep->kind == scrollbar_click) - && (ep->modifiers & up_modifier)) - continue; - - return 1; - } - - return 0; + return ! EVENT_QUEUES_EMPTY; } @@ -1537,28 +1512,6 @@ /* Wait until there is input available. */ for (;;) { - - /* Process or toss any events that we don't want to return as - input. The fact that we remove undesirable events here - allows us to use EVENT_QUEUES_EMPTY in the rest of this loop. */ - if (! do_mouse_tracking) - while (kbd_fetch_ptr != kbd_store_ptr) - { - if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) - kbd_fetch_ptr = kbd_buffer; - - if (kbd_fetch_ptr->kind == mouse_click - || kbd_fetch_ptr->kind == scrollbar_click) - { - if ((kbd_fetch_ptr->modifiers & up_modifier) == 0) - break; - } - else - break; - - kbd_fetch_ptr++; - } - if (!EVENT_QUEUES_EMPTY) break; @@ -1720,9 +1673,23 @@ "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5" }; +/* make_lispy_event stores the down-going location of the currently + depressed buttons in button_down_locations. */ +struct mouse_position { + Lisp_Object window; + Lisp_Object buffer_pos; + Lisp_Object x, y; + Lisp_Object timestamp; +}; +static struct mouse_position button_down_location[NUM_MOUSE_BUTTONS]; + /* Given a struct input_event, build the lisp event which represents it. If EVENT is 0, build a mouse movement event from the mouse - movement buffer, which should have a movement event in it. */ + movement buffer, which should have a movement event in it. + + Note that events must be passed to this function in the order they + are received; this function stores the location of button presses + in order to build drag events when the button is released. */ static Lisp_Object make_lispy_event (event) @@ -1734,7 +1701,6 @@ switch (event->kind) #endif { - /* A simple keystroke. */ case ascii_keystroke: return event->code; @@ -1750,16 +1716,22 @@ / sizeof (lispy_function_keys[0]))); break; - /* A mouse click - build a list of the relevant information. */ + /* A mouse click. Figure out where it is, decide whether it's + a press, click or drag, and build the appropriate structure. */ case mouse_click: { int part; - Lisp_Object window = - window_from_coordinates (event->frame, - XINT (event->x), XINT (event->y), - &part); + Lisp_Object window; Lisp_Object posn; - + struct mouse_position *loc; + + if (event->code < 0 || event->code >= NUM_MOUSE_BUTTONS) + abort (); + + /* Where did this mouse click occur? */ + window = window_from_coordinates (event->frame, + XINT (event->x), XINT (event->y), + &part); if (XTYPE (window) != Lisp_Window) posn = Qnil; else @@ -1768,7 +1740,6 @@ - XINT (XWINDOW (window)->left))); XSETINT (event->y, (XINT (event->y) - XINT (XWINDOW (window)->top))); - if (part == 1) posn = Qmode_line; else if (part == 2) @@ -1780,18 +1751,67 @@ XINT (event->y))); } - return Fcons (modify_event_symbol (XFASTINT (event->code) - 1, - event->modifiers, - Qmouse_click, - lispy_mouse_names, &mouse_syms, - (sizeof (lispy_mouse_names) - / sizeof (lispy_mouse_names[0]))), - Fcons (window, - Fcons (posn, - Fcons (Fcons (event->x, event->y), - Fcons (make_number - (event->timestamp), - Qnil))))); + /* If this is a button press, squirrel away the location, so we + can decide later whether it was a click or a drag. */ + loc = button_down_location + event->code; + if (event->modifiers & down_modifier) + { + loc->window = window; + loc->buffer_pos = posn; + loc->x = event->x; + loc->y = event->y; + loc->timestamp = event->timestamp; + } + + /* Now we're releasing a button - check the co-ordinates to + see if this was a click or a drag. */ + else if (event->modifiers & up_modifier) + { + event->modifiers &= ~up_modifier; + event->modifiers |= ((event->x == loc->x && event->y == loc->y) + ? click_modifier + : drag_modifier); + } + else + /* Every mouse event should either have the down_modifier or + the up_modifier set. */ + abort (); + + + /* Build the event. */ + { + Lisp_Object head, start, end; + + /* Build the components of the event. */ + head = modify_event_symbol (XFASTINT (event->code) - 1, + event->modifiers, + Qmouse_click, + lispy_mouse_names, &mouse_syms, + (sizeof (lispy_mouse_names) + / sizeof (lispy_mouse_names[0]))); + end = Fcons (window, + Fcons (posn, + Fcons (Fcons (event->x, event->y), + Fcons (make_number (event->timestamp), + Qnil)))); + if (event->modifiers & drag_modifier) + start = Fcons (loc->window, + Fcons (loc->buffer_pos, + Fcons (Fcons (loc->x, loc->y), + Fcons (make_number (loc->timestamp), + Qnil)))); + + /* Assemble the pieces. */ + if (event->modifiers & drag_modifier) + return Fcons (head, + Fcons (start, + Fcons (end, + Qnil))); + else + return Fcons (head, + Fcons (end, + Qnil)); + } } /* A scrollbar click. Build a list containing the relevant @@ -1854,10 +1874,12 @@ XSETINT (x, ix); XSETINT (y, iy); return Fcons (Qmouse_movement, - Fcons (window, - Fcons (posn, - Fcons (Fcons (x, y), - Fcons (make_number (time), Qnil))))); + Fcons (Fcons (window, + Fcons (posn, + Fcons (Fcons (x, y), + Fcons (make_number (time), + Qnil)))), + Qnil)); } @@ -1872,8 +1894,8 @@ { char *p = buf; - /* Events with the `up' modifier should always be turned into - click or drag events. */ + /* Only the event queue may use the `up' modifier; it should always + be turned into a click or drag event before presented to lisp code. */ if (modifiers & up_modifier) abort (); @@ -1885,6 +1907,7 @@ if (modifiers & super_modifier) { strcpy (p, "super-"); p += 6; } if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } + /* The click modifier is denoted by the absence of other modifiers. */ *p = '\0'; return p - buf; @@ -1894,7 +1917,7 @@ /* Given a symbol whose name begins with modifiers ("C-", "M-", etc), return a symbol with the modifiers placed in the canonical order. Canonical order is alphabetical, except for down and drag, which - always come last. + always come last. The 'click' modifier is never written out. Fdefine_key calls this to make sure that (for example) C-M-foo and M-C-foo end up being equivalent in the keymap. */ @@ -2029,7 +2052,19 @@ whose prefixes should be applied to the symbol name. SYMBOL_KIND is the value to be placed in the event_kind property of - the returned symbol. */ + the returned symbol. + + The symbols we create are supposed to have an + `event-symbol-elements' propery, which lists the modifiers present + in the symbol's name. */ + +static char *modifier_names[] = +{ + "up", "alt", "ctrl", "hyper", "meta", "shift", "super", "down", "drag", + "click" +}; + +static Lisp_Object modifier_symbols; static Lisp_Object modify_event_symbol (symbol_num, modifiers, symbol_kind, name_table, @@ -2041,76 +2076,89 @@ Lisp_Object *symbol_table; int table_size; { - Lisp_Object *slot, *unmodified_slot; + Lisp_Object *slot; + Lisp_Object unmodified; + Lisp_Object temp; /* Is this a request for a valid symbol? */ - if (symbol_num < 0 || symbol_num >= table_size - || modifiers >= NUM_MODIFIER_COMBOS) + if (symbol_num < 0 || symbol_num >= table_size) abort (); - /* If *symbol_table is not a vector of the appropriate size, - set it to one. */ + /* If *symbol_table doesn't seem to be initialized property, fix that. + + *symbol_table should be a lisp vector TABLE_SIZE elements long, + where the Nth element is an alist for modified versions of + name_table[N]; the alist maps modifier masks onto the modified + symbols. The click modifier is always omitted from the mask; it + is indicated implicitly on a mouse event by the absence of the + down_ and drag_ modifiers. */ if (XTYPE (*symbol_table) != Lisp_Vector || XVECTOR (*symbol_table)->size != table_size) - *symbol_table = Fmake_vector (make_number (table_size), Qnil); - - unmodified_slot = slot = & XVECTOR (*symbol_table)->contents[symbol_num]; - - /* If there are modifier keys, there had better be a vector in - this symbol's position of the symbol_table. */ - if (modifiers != 0) { - Lisp_Object slot_contents = *slot; - - /* If there isn't the right sort of vector there, put one in. */ - if (XTYPE (slot_contents) != Lisp_Vector - || XVECTOR (slot_contents)->size != NUM_MODIFIER_COMBOS) - { - *slot = Fmake_vector (make_number (NUM_MODIFIER_COMBOS), Qnil); - - /* Make sure that the vector has an entry for the unmodified - symbol, so we can put it on the event_unmodified property. */ - if (! NILP (slot_contents)) - XVECTOR (*slot)->contents[0] = slot_contents; - else - XVECTOR (*slot)->contents[0] = intern (name_table [symbol_num]); - } + XFASTINT (temp) = table_size; + *symbol_table = Fmake_vector (temp, Qnil); } - /* If this entry has been filled in with a modified symbol vector, - point to the appropriate slot within that. */ - if (XTYPE (*slot) == Lisp_Vector) - { - unmodified_slot = & XVECTOR (*slot)->contents[0]; - slot = & XVECTOR (*slot)->contents[modifiers]; - } - - /* Make sure we have an unmodified version of the symbol in its - proper place? */ - if (NILP (*unmodified_slot)) - { - *unmodified_slot = intern (name_table [symbol_num]); - Fput (*unmodified_slot, Qevent_kind, symbol_kind); - Fput (*unmodified_slot, Qevent_unmodified, *unmodified_slot); - } - - /* Have we already created a symbol for this combination of modifiers? */ + slot = & XVECTOR (*symbol_table)->contents[symbol_num]; + + /* Have we already modified this symbol? */ + XFASTINT (temp) = modifiers & ~(click_modifier); + temp = Fassq (temp, *slot); + if (CONSP (temp)) + return (XCONS (temp)->cdr); + + /* We don't have an entry for the symbol; we have to build it. */ + + /* Make sure there's an assoc for the unmodified symbol. + Any non-empty alist should contain an entry for the unmodified symbol. */ + XFASTINT (temp) = 0; + if (NILP (*slot)) { - /* No, let's create one. */ - char *modified_name - = (char *) alloca (sizeof ("C-M-S-U-") - + strlen (name_table [symbol_num])); - - strcpy (modified_name + format_modifiers (modifiers, modified_name), - name_table [symbol_num]); - - *slot = intern (modified_name); - Fput (*slot, Qevent_kind, symbol_kind); - Fput (*slot, Qevent_unmodified, *unmodified_slot); + unmodified = intern (name_table [symbol_num]); + *slot = Fcons (Fcons (temp, unmodified), Qnil); + Fput (unmodified, Qevent_kind, symbol_kind); + Fput (unmodified, Qevent_symbol_elements, Fcons (unmodified, Qnil)); + } + else + { + temp = Fassq (temp, *slot); + if (NILP (temp)) + abort (); + unmodified = XCONS (temp)->cdr; } - - return *slot; + + /* Create a modified version of the symbol, and add it to the alist. */ + { + Lisp_Object modified; + char *modified_name + = (char *) alloca (sizeof ("A-C-H-M-S-super-U-down-drag") + + strlen (name_table [symbol_num])); + + strcpy (modified_name + format_modifiers (modifiers, modified_name), + name_table [symbol_num]); + + modified = intern (modified_name); + XFASTINT (temp) = modifiers & ~click_modifier; + *slot = Fcons (Fcons (temp, modified), *slot); + Fput (modified, Qevent_kind, symbol_kind); + + { + Lisp_Object modifier_list; + int i; + + modifier_list = Qnil; + for (i = 0; (1<<i) <= modifiers; i++) + if (modifiers & (1<<i)) + modifier_list = Fcons (XVECTOR (modifier_symbols)->contents[i], + modifier_list); + + Fput (modified, Qevent_symbol_elements, + Fcons (unmodified, modifier_list)); + } + + return modified; + } } DEFUN ("mouse-click-p", Fmouse_click_p, Smouse_click_p, 1, 1, 0, @@ -2546,6 +2594,9 @@ case letter and there are bindings for the corresponding lower-case letter, return the bindings for the lower-case letter. + If KEY has no bindings in any of the CURRENT maps, NEXT is left + unmodified. + NEXT may == CURRENT. */ static int @@ -2786,7 +2837,7 @@ } else if (EVENT_HAS_PARAMETERS (key)) { - Lisp_Object window = EVENT_WINDOW (key); + Lisp_Object window = POSN_WINDOW (EVENT_START (key)); if (NILP (window)) abort (); @@ -3568,8 +3619,8 @@ Qevent_kind = intern ("event-type"); staticpro (&Qevent_kind); - Qevent_unmodified = intern ("event-unmodified"); - staticpro (&Qevent_unmodified); + Qevent_symbol_elements = intern ("event-symbol-elements"); + staticpro (&Qevent_symbol_elements); { struct event_head *p; @@ -3581,10 +3632,27 @@ *p->var = intern (p->name); staticpro (p->var); Fput (*p->var, Qevent_kind, *p->kind); - Fput (*p->var, Qevent_unmodified, *p->var); + Fput (*p->var, Qevent_symbol_elements, Fcons (*p->var, Qnil)); } } + { + int i; + + for (i = 0; i < NUM_MOUSE_BUTTONS; i++) + staticpro (&button_down_location[i].window); + } + + { + int i; + int len = sizeof (modifier_names) / sizeof (modifier_names[0]); + + modifier_symbols = Fmake_vector (make_number (len), Qnil); + for (i = 0; i < len; i++) + XVECTOR (modifier_symbols)->contents[i] = intern (modifier_names[i]); + staticpro (&modifier_symbols); + } + recent_keys = Fmake_vector (make_number (NUM_RECENT_KEYS), Qnil); staticpro (&recent_keys);