aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Blandy1993-06-22 02:06:54 +0000
committerJim Blandy1993-06-22 02:06:54 +0000
commitfbcd35bd72c1778817294cc160a84353fd864a9e (patch)
tree09c94a6596f26a5ee13e5dac4b87b6ed402661cc
parent69b95560cde2119f7f3c3d5bd241bc7355bcf27d (diff)
downloademacs-fbcd35bd72c1778817294cc160a84353fd864a9e.tar.gz
emacs-fbcd35bd72c1778817294cc160a84353fd864a9e.zip
* keyboard.c (make_lispy_event): Added detection of double-click
and triple-click events. (parse_modifiers_uncached, apply_modifiers_uncached): Same. (read_key_sequence): Coerce double-clicks to clicks, and triple-clicks to double-clicks or clicks, by analogy with drag events. (double_click_time): Added variable. * termhooks.h: Added multi-click event modifier bits.
-rw-r--r--src/keyboard.c159
-rw-r--r--src/termhooks.h11
2 files changed, 132 insertions, 38 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 49d27b0dcdc..6a18aed16f9 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2143,6 +2143,22 @@ Lisp_Object *scroll_bar_parts[] = {
2143 2143
2144static Lisp_Object button_down_location; 2144static Lisp_Object button_down_location;
2145 2145
2146/* Information about the most recent up-going button event: Which
2147 button, what location, and what time. */
2148
2149static int button_up_button;
2150static int button_up_x;
2151static int button_up_y;
2152static unsigned long button_up_time;
2153
2154/* The minimum time between clicks to make a double-click. */
2155
2156int double_click_time;
2157
2158/* The number of clicks in this multiple-click. */
2159
2160int double_click_count;
2161
2146/* Given a struct input_event, build the lisp event which represents 2162/* Given a struct input_event, build the lisp event which represents
2147 it. If EVENT is 0, build a mouse movement event from the mouse 2163 it. If EVENT is 0, build a mouse movement event from the mouse
2148 movement buffer, which should have a movement event in it. 2164 movement buffer, which should have a movement event in it.
@@ -2176,12 +2192,14 @@ make_lispy_event (event)
2176 c |= (event->modifiers 2192 c |= (event->modifiers
2177 & (meta_modifier | alt_modifier 2193 & (meta_modifier | alt_modifier
2178 | hyper_modifier | super_modifier)); 2194 | hyper_modifier | super_modifier));
2195 button_up_time = 0;
2179 return c; 2196 return c;
2180 } 2197 }
2181 2198
2182 /* A function key. The symbol may need to have modifier prefixes 2199 /* A function key. The symbol may need to have modifier prefixes
2183 tacked onto it. */ 2200 tacked onto it. */
2184 case non_ascii_keystroke: 2201 case non_ascii_keystroke:
2202 button_up_time = 0;
2185 return modify_event_symbol (XFASTINT (event->code), event->modifiers, 2203 return modify_event_symbol (XFASTINT (event->code), event->modifiers,
2186 Qfunction_key, 2204 Qfunction_key,
2187 lispy_function_keys, &func_key_syms, 2205 lispy_function_keys, &func_key_syms,
@@ -2316,10 +2334,36 @@ make_lispy_event (event)
2316 pair. */ 2334 pair. */
2317 Lisp_Object down = Fnth (make_number (2), start_pos); 2335 Lisp_Object down = Fnth (make_number (2), start_pos);
2318 2336
2319 event->modifiers |= ((EQ (event->x, XCONS (down)->car) 2337 if (EQ (event->x, XCONS (down)->car)
2320 && EQ (event->y, XCONS (down)->cdr)) 2338 && EQ (event->y, XCONS (down)->cdr))
2321 ? click_modifier 2339 {
2322 : drag_modifier); 2340 if (button == button_up_button
2341 && XINT (event->x) == button_up_x
2342 && XINT (event->y) == button_up_y
2343 && button_up_time != 0
2344 && ((int)(event->timestamp - button_up_time)
2345 < double_click_time))
2346 {
2347 double_click_count++;
2348 event->modifiers |= ((double_click_count > 2)
2349 ? triple_modifier
2350 : double_modifier);
2351 }
2352 else
2353 {
2354 double_click_count = 1;
2355 event->modifiers |= click_modifier;
2356 }
2357 button_up_button = button;
2358 button_up_x = XINT (event->x);
2359 button_up_y = XINT (event->y);
2360 button_up_time = event->timestamp;
2361 }
2362 else
2363 {
2364 button_up_time = 0;
2365 event->modifiers |= drag_modifier;
2366 }
2323 } 2367 }
2324 } 2368 }
2325 else 2369 else
@@ -2342,6 +2386,11 @@ make_lispy_event (event)
2342 Fcons (start_pos, 2386 Fcons (start_pos,
2343 Fcons (position, 2387 Fcons (position,
2344 Qnil))); 2388 Qnil)));
2389 else if (event->modifiers & (double_modifier | triple_modifier))
2390 return Fcons (head,
2391 Fcons (position,
2392 Fcons (make_number (double_click_count),
2393 Qnil)));
2345 else 2394 else
2346 return Fcons (head, 2395 return Fcons (head,
2347 Fcons (position, 2396 Fcons (position,
@@ -2498,6 +2547,24 @@ parse_modifiers_uncached (symbol, modifier_end)
2498 modifiers |= down_modifier; 2547 modifiers |= down_modifier;
2499 i += 5; 2548 i += 5;
2500 } 2549 }
2550 else if (i + 7 <= name->size
2551 && ! strncmp (name->data + i, "double-", 7))
2552 {
2553 modifiers |= double_modifier;
2554 i += 7;
2555 }
2556 else
2557 goto no_more_modifiers;
2558 break;
2559
2560 case 't':
2561 if (i + 7 > name->size)
2562 goto no_more_modifiers;
2563 if (! strncmp (name->data + i, "triple-", 7))
2564 {
2565 modifiers |= triple_modifier;
2566 i += 7;
2567 }
2501 else 2568 else
2502 goto no_more_modifiers; 2569 goto no_more_modifiers;
2503 break; 2570 break;
@@ -2510,7 +2577,8 @@ parse_modifiers_uncached (symbol, modifier_end)
2510 no_more_modifiers: 2577 no_more_modifiers:
2511 2578
2512 /* Should we include the `click' modifier? */ 2579 /* Should we include the `click' modifier? */
2513 if (! (modifiers & (down_modifier | drag_modifier)) 2580 if (! (modifiers & (down_modifier | drag_modifier
2581 | double_modifier | triple_modifier))
2514 && i + 7 == name->size 2582 && i + 7 == name->size
2515 && strncmp (name->data + i, "mouse-", 6) == 0 2583 && strncmp (name->data + i, "mouse-", 6) == 0
2516 && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9')) 2584 && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9'))
@@ -2536,7 +2604,7 @@ apply_modifiers_uncached (modifiers, base, base_len)
2536 to use Fintern, which expects a genuine Lisp_String, and keeps a 2604 to use Fintern, which expects a genuine Lisp_String, and keeps a
2537 reference to it. */ 2605 reference to it. */
2538 char *new_mods = 2606 char *new_mods =
2539 (char *) alloca (sizeof ("A-C-H-M-S-s-down-drag-")); 2607 (char *) alloca (sizeof ("A-C-H-M-S-s-down-drag-double-triple-"));
2540 int mod_len; 2608 int mod_len;
2541 2609
2542 { 2610 {
@@ -2555,6 +2623,8 @@ apply_modifiers_uncached (modifiers, base, base_len)
2555 if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; } 2623 if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; }
2556 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } 2624 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; }
2557 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } 2625 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; }
2626 if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; }
2627 if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; }
2558 /* The click modifier is denoted by the absence of other modifiers. */ 2628 /* The click modifier is denoted by the absence of other modifiers. */
2559 2629
2560 *p = '\0'; 2630 *p = '\0';
@@ -2575,7 +2645,7 @@ apply_modifiers_uncached (modifiers, base, base_len)
2575 2645
2576static char *modifier_names[] = 2646static char *modifier_names[] =
2577{ 2647{
2578 "up", "down", "drag", "click", 0, 0, 0, 0, 2648 "up", "down", "drag", "click", "double", "triple", 0, 0,
2579 0, 0, 0, 0, 0, 0, 0, 0, 2649 0, 0, 0, 0, 0, 0, 0, 0,
2580 0, 0, "alt", "super", "hyper", "shift", "control", "meta" 2650 0, 0, "alt", "super", "hyper", "shift", "control", "meta"
2581}; 2651};
@@ -3525,8 +3595,10 @@ follow_key (key, nmaps, current, defs, next)
3525 function key's sequence. If so, we try to read the whole function 3595 function key's sequence. If so, we try to read the whole function
3526 key, and substitute its symbolic name into the key sequence. 3596 key, and substitute its symbolic name into the key sequence.
3527 3597
3528 We ignore unbound `down-' mouse clicks. We turn unbound `drag-' 3598 We ignore unbound `down-' mouse clicks. We turn unbound `drag-' and
3529 events into similar click events, if that would make them bound. 3599 `double-' events into similar click events, if that would make them
3600 bound. We try to turn `triple-' events first into `double-' events,
3601 then into clicks.
3530 3602
3531 If we get a mouse click in a mode line, vertical divider, or other 3603 If we get a mouse click in a mode line, vertical divider, or other
3532 non-text area, we treat the click as if it were prefixed by the 3604 non-text area, we treat the click as if it were prefixed by the
@@ -3947,29 +4019,41 @@ read_key_sequence (keybuf, bufsize, prompt)
3947 4019
3948 /* We turn unbound `drag-' events into `click-' 4020 /* We turn unbound `drag-' events into `click-'
3949 events, if the click would be bound. */ 4021 events, if the click would be bound. */
3950 else if (modifiers & drag_modifier) 4022 else if (modifiers & (drag_modifier | double_modifier
4023 | triple_modifier))
3951 { 4024 {
3952 Lisp_Object new_head = 4025 while (modifiers & (drag_modifier | double_modifier
3953 apply_modifiers (modifiers & ~drag_modifier, 4026 | triple_modifier))
3954 XCONS (breakdown)->car); 4027 {
3955 Lisp_Object new_click = 4028 Lisp_Object new_head, new_click;
3956 Fcons (new_head, Fcons (EVENT_START (key), Qnil)); 4029 if (modifiers & triple_modifier)
3957 4030 modifiers ^= (double_modifier | triple_modifier);
3958 /* Look for a binding for this new key. follow_key 4031 else
3959 promises that it didn't munge submaps the 4032 modifiers &= ~(drag_modifier | double_modifier);
3960 last time we called it, since key was unbound. */ 4033 new_head =
3961 first_binding = 4034 apply_modifiers (modifiers, XCONS (breakdown)->car);
3962 (follow_key (new_click, 4035 new_click =
3963 nmaps - local_first_binding, 4036 Fcons (new_head, Fcons (EVENT_START (key), Qnil));
3964 submaps + local_first_binding, 4037
3965 defs + local_first_binding, 4038 /* Look for a binding for this new key. follow_key
3966 submaps + local_first_binding) 4039 promises that it didn't munge submaps the
3967 + local_first_binding); 4040 last time we called it, since key was unbound. */
3968 4041 first_binding =
3969 /* If that click is bound, go for it. */ 4042 (follow_key (new_click,
3970 if (first_binding < nmaps) 4043 nmaps - local_first_binding,
3971 key = new_click; 4044 submaps + local_first_binding,
3972 /* Otherwise, we'll leave key set to the drag event. */ 4045 defs + local_first_binding,
4046 submaps + local_first_binding)
4047 + local_first_binding);
4048
4049 /* If that click is bound, go for it. */
4050 if (first_binding < nmaps)
4051 {
4052 key = new_click;
4053 break;
4054 }
4055 /* Otherwise, we'll leave key set to the drag event. */
4056 }
3973 } 4057 }
3974 } 4058 }
3975 } 4059 }
@@ -4093,10 +4177,10 @@ of the selected window as normal.\n\
4093\n\ 4177\n\
4094`read-key-sequence' drops unbound button-down events, since you normally\n\ 4178`read-key-sequence' drops unbound button-down events, since you normally\n\
4095only care about the click or drag events which follow them. If a drag\n\ 4179only care about the click or drag events which follow them. If a drag\n\
4096event is unbound, but the corresponding click event would be bound,\n\ 4180or multi-click event is unbound, but the corresponding click event would\n\
4097`read-key-sequence' turns the drag event into a click event at the\n\ 4181be bound, `read-key-sequence' turns the event into a click event at the\n\
4098drag's starting position. This means that you don't have to distinguish\n\ 4182drag's starting position. This means that you don't have to distinguish\n\
4099between click and drag events unless you want to.\n\ 4183between click and drag, double, or triple events unless you want to.\n\
4100\n\ 4184\n\
4101`read-key-sequence' prefixes mouse events on mode lines, the vertical\n\ 4185`read-key-sequence' prefixes mouse events on mode lines, the vertical\n\
4102lines separating windows, and scroll bars with imaginary keys\n\ 4186lines separating windows, and scroll bars with imaginary keys\n\
@@ -4979,6 +5063,13 @@ Polling is needed only when using X windows and SIGIO does not work.\n\
4979Polling is automatically disabled in all other cases."); 5063Polling is automatically disabled in all other cases.");
4980 polling_period = 2; 5064 polling_period = 2;
4981 5065
5066 DEFVAR_INT ("double-click-time", &double_click_time,
5067 "*Maximum time between mouse clicks to make a double-click.\n\
5068Measured in milliseconds. Zero means disable double-click recognition;\n\
5069a large number means double-clicks have no time limit and are detected\n\
5070by position only.");
5071 double_click_time = 500;
5072
4982 DEFVAR_INT ("num-input-keys", &num_input_keys, 5073 DEFVAR_INT ("num-input-keys", &num_input_keys,
4983 "*Number of complete keys read from the keyboard so far."); 5074 "*Number of complete keys read from the keyboard so far.");
4984 num_input_keys = 0; 5075 num_input_keys = 0;
diff --git a/src/termhooks.h b/src/termhooks.h
index a410038f5f6..53d48f254e6 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -286,10 +286,11 @@ struct input_event {
286 is a mouse click lacking the click and drag modifiers. 286 is a mouse click lacking the click and drag modifiers.
287 287
288 The window-system independent code turns all up_modifier events 288 The window-system independent code turns all up_modifier events
289 bits into either drag_modifier or click_modifier events. The 289 bits into drag_modifier, click_modifier, double_modifier, or
290 click_modifier has no written representation in the names of the 290 triple_modifier events. The click_modifier has no written
291 symbols used as event heads, but it does appear in the 291 representation in the names of the symbols used as event heads,
292 Qevent_symbol_components property of the event heads. */ 292 but it does appear in the Qevent_symbol_components property of the
293 event heads. */
293enum { 294enum {
294 up_modifier = 1, /* Only used on mouse buttons - always 295 up_modifier = 1, /* Only used on mouse buttons - always
295 turned into a click or a drag modifier 296 turned into a click or a drag modifier
@@ -299,6 +300,8 @@ enum {
299 queue; it's only used internally by 300 queue; it's only used internally by
300 the window-system-independent code. */ 301 the window-system-independent code. */
301 click_modifier= 8, /* See drag_modifier. */ 302 click_modifier= 8, /* See drag_modifier. */
303 double_modifier= 16, /* See drag_modifier. */
304 triple_modifier= 32, /* See drag_modifier. */
302 305
303 /* The next four modifier bits are used also in keyboard events at 306 /* The next four modifier bits are used also in keyboard events at
304 the Lisp level. 307 the Lisp level.