diff options
| author | Richard M. Stallman | 1993-08-01 18:48:20 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1993-08-01 18:48:20 +0000 |
| commit | 559f9d04059f2a4f45f12be775a144b29fbd34a1 (patch) | |
| tree | 1d64e9766e70434a0e2386284817ce7be0392434 | |
| parent | 7f3e80e3b4ee05605a38e95e292796a1fea5a0cb (diff) | |
| download | emacs-559f9d04059f2a4f45f12be775a144b29fbd34a1.tar.gz emacs-559f9d04059f2a4f45f12be775a144b29fbd34a1.zip | |
(last_mouse_button): Renamed from button_up_button.
(last_mouse_x, last_mouse_y): Likewise.
(button_down_time): Replaces button_up_time.
(make_lispy_event): Set button_down_time.
Detect and report double-down and double-drag events.
(apply_modifiers_uncached): Put `double' or `triple' first.
(read_key_sequence): Convert unbound double-drag/down to drag/down.
| -rw-r--r-- | src/keyboard.c | 184 |
1 files changed, 99 insertions, 85 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index 5714ec6ac13..9614a967b89 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -2180,10 +2180,10 @@ static Lisp_Object button_down_location; | |||
| 2180 | /* Information about the most recent up-going button event: Which | 2180 | /* Information about the most recent up-going button event: Which |
| 2181 | button, what location, and what time. */ | 2181 | button, what location, and what time. */ |
| 2182 | 2182 | ||
| 2183 | static int button_up_button; | 2183 | static int last_mouse_button; |
| 2184 | static int button_up_x; | 2184 | static int last_mouse_x; |
| 2185 | static int button_up_y; | 2185 | static int last_mouse_y; |
| 2186 | static unsigned long button_up_time; | 2186 | static unsigned long button_down_time; |
| 2187 | 2187 | ||
| 2188 | /* The maximum time between clicks to make a double-click, | 2188 | /* The maximum time between clicks to make a double-click, |
| 2189 | or Qnil to disable double-click detection, | 2189 | or Qnil to disable double-click detection, |
| @@ -2227,14 +2227,14 @@ make_lispy_event (event) | |||
| 2227 | c |= (event->modifiers | 2227 | c |= (event->modifiers |
| 2228 | & (meta_modifier | alt_modifier | 2228 | & (meta_modifier | alt_modifier |
| 2229 | | hyper_modifier | super_modifier)); | 2229 | | hyper_modifier | super_modifier)); |
| 2230 | button_up_time = 0; | 2230 | button_down_time = 0; |
| 2231 | return c; | 2231 | return c; |
| 2232 | } | 2232 | } |
| 2233 | 2233 | ||
| 2234 | /* A function key. The symbol may need to have modifier prefixes | 2234 | /* A function key. The symbol may need to have modifier prefixes |
| 2235 | tacked onto it. */ | 2235 | tacked onto it. */ |
| 2236 | case non_ascii_keystroke: | 2236 | case non_ascii_keystroke: |
| 2237 | button_up_time = 0; | 2237 | button_down_time = 0; |
| 2238 | return modify_event_symbol (XFASTINT (event->code), event->modifiers, | 2238 | return modify_event_symbol (XFASTINT (event->code), event->modifiers, |
| 2239 | Qfunction_key, | 2239 | Qfunction_key, |
| 2240 | lispy_function_keys, &func_key_syms, | 2240 | lispy_function_keys, &func_key_syms, |
| @@ -2248,6 +2248,7 @@ make_lispy_event (event) | |||
| 2248 | case scroll_bar_click: | 2248 | case scroll_bar_click: |
| 2249 | { | 2249 | { |
| 2250 | int button = XFASTINT (event->code); | 2250 | int button = XFASTINT (event->code); |
| 2251 | int is_double; | ||
| 2251 | Lisp_Object position; | 2252 | Lisp_Object position; |
| 2252 | Lisp_Object *start_pos_ptr; | 2253 | Lisp_Object *start_pos_ptr; |
| 2253 | Lisp_Object start_pos; | 2254 | Lisp_Object start_pos; |
| @@ -2339,10 +2340,34 @@ make_lispy_event (event) | |||
| 2339 | start_pos = *start_pos_ptr; | 2340 | start_pos = *start_pos_ptr; |
| 2340 | *start_pos_ptr = Qnil; | 2341 | *start_pos_ptr = Qnil; |
| 2341 | 2342 | ||
| 2343 | is_double = (button == last_mouse_button | ||
| 2344 | && XINT (event->x) == last_mouse_x | ||
| 2345 | && XINT (event->y) == last_mouse_y | ||
| 2346 | && button_down_time != 0 | ||
| 2347 | && (EQ (Vdouble_click_time, Qt) | ||
| 2348 | || (INTEGERP (Vdouble_click_time) | ||
| 2349 | && ((int)(event->timestamp - button_down_time) | ||
| 2350 | < XINT (Vdouble_click_time))))); | ||
| 2351 | last_mouse_button = button; | ||
| 2352 | last_mouse_x = XINT (event->x); | ||
| 2353 | last_mouse_y = XINT (event->y); | ||
| 2354 | |||
| 2342 | /* If this is a button press, squirrel away the location, so | 2355 | /* If this is a button press, squirrel away the location, so |
| 2343 | we can decide later whether it was a click or a drag. */ | 2356 | we can decide later whether it was a click or a drag. */ |
| 2344 | if (event->modifiers & down_modifier) | 2357 | if (event->modifiers & down_modifier) |
| 2345 | *start_pos_ptr = Fcopy_alist (position); | 2358 | { |
| 2359 | if (is_double) | ||
| 2360 | { | ||
| 2361 | double_click_count++; | ||
| 2362 | event->modifiers |= ((double_click_count > 2) | ||
| 2363 | ? triple_modifier | ||
| 2364 | : double_modifier); | ||
| 2365 | } | ||
| 2366 | else | ||
| 2367 | double_click_count = 1; | ||
| 2368 | button_down_time = event->timestamp; | ||
| 2369 | *start_pos_ptr = Fcopy_alist (position); | ||
| 2370 | } | ||
| 2346 | 2371 | ||
| 2347 | /* Now we're releasing a button - check the co-ordinates to | 2372 | /* Now we're releasing a button - check the co-ordinates to |
| 2348 | see if this was a click or a drag. */ | 2373 | see if this was a click or a drag. */ |
| @@ -2372,33 +2397,16 @@ make_lispy_event (event) | |||
| 2372 | if (EQ (event->x, XCONS (down)->car) | 2397 | if (EQ (event->x, XCONS (down)->car) |
| 2373 | && EQ (event->y, XCONS (down)->cdr)) | 2398 | && EQ (event->y, XCONS (down)->cdr)) |
| 2374 | { | 2399 | { |
| 2375 | if (button == button_up_button | 2400 | if (is_double && double_click_count > 1) |
| 2376 | && XINT (event->x) == button_up_x | 2401 | event->modifiers |= ((double_click_count > 2) |
| 2377 | && XINT (event->y) == button_up_y | 2402 | ? triple_modifier |
| 2378 | && button_up_time != 0 | 2403 | : double_modifier); |
| 2379 | && (EQ (Vdouble_click_time, Qt) | ||
| 2380 | || (INTEGERP (Vdouble_click_time) | ||
| 2381 | && ((int)(event->timestamp - button_up_time) | ||
| 2382 | < XINT (Vdouble_click_time))))) | ||
| 2383 | { | ||
| 2384 | double_click_count++; | ||
| 2385 | event->modifiers |= ((double_click_count > 2) | ||
| 2386 | ? triple_modifier | ||
| 2387 | : double_modifier); | ||
| 2388 | } | ||
| 2389 | else | 2404 | else |
| 2390 | { | 2405 | event->modifiers |= click_modifier; |
| 2391 | double_click_count = 1; | ||
| 2392 | event->modifiers |= click_modifier; | ||
| 2393 | } | ||
| 2394 | button_up_button = button; | ||
| 2395 | button_up_x = XINT (event->x); | ||
| 2396 | button_up_y = XINT (event->y); | ||
| 2397 | button_up_time = event->timestamp; | ||
| 2398 | } | 2406 | } |
| 2399 | else | 2407 | else |
| 2400 | { | 2408 | { |
| 2401 | button_up_time = 0; | 2409 | button_down_time = 0; |
| 2402 | event->modifiers |= drag_modifier; | 2410 | event->modifiers |= drag_modifier; |
| 2403 | } | 2411 | } |
| 2404 | } | 2412 | } |
| @@ -2658,10 +2666,10 @@ apply_modifiers_uncached (modifiers, base, base_len) | |||
| 2658 | if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } | 2666 | if (modifiers & meta_modifier) { *p++ = 'M'; *p++ = '-'; } |
| 2659 | if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } | 2667 | if (modifiers & shift_modifier) { *p++ = 'S'; *p++ = '-'; } |
| 2660 | if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; } | 2668 | if (modifiers & super_modifier) { *p++ = 's'; *p++ = '-'; } |
| 2661 | if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } | ||
| 2662 | if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } | ||
| 2663 | if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; } | 2669 | if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; } |
| 2664 | if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; } | 2670 | if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; } |
| 2671 | if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } | ||
| 2672 | if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } | ||
| 2665 | /* The click modifier is denoted by the absence of other modifiers. */ | 2673 | /* The click modifier is denoted by the absence of other modifiers. */ |
| 2666 | 2674 | ||
| 2667 | *p = '\0'; | 2675 | *p = '\0'; |
| @@ -4064,65 +4072,71 @@ read_key_sequence (keybuf, bufsize, prompt) | |||
| 4064 | Lisp_Object breakdown = parse_modifiers (head); | 4072 | Lisp_Object breakdown = parse_modifiers (head); |
| 4065 | int modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car); | 4073 | int modifiers = XINT (XCONS (XCONS (breakdown)->cdr)->car); |
| 4066 | 4074 | ||
| 4067 | /* We drop unbound `down-' events altogether. */ | 4075 | /* Attempt to reduce an unbound mouse event to a simpler |
| 4068 | if (modifiers & down_modifier) | 4076 | event that is bound: |
| 4077 | Drags reduce to clicks. | ||
| 4078 | Double-clicks reduce to clicks. | ||
| 4079 | Triple-clicks reduce to double-clicks, then to clicks. | ||
| 4080 | Down-clicks are eliminated. | ||
| 4081 | Double-downs reduce to downs, then are eliminated. | ||
| 4082 | Triple-downs reduce to double-downs, then to downs, | ||
| 4083 | then are eliminated. */ | ||
| 4084 | if (modifiers & (down_modifier | drag_modifier | ||
| 4085 | | double_modifier | triple_modifier)) | ||
| 4069 | { | 4086 | { |
| 4070 | /* Dispose of this event by simply jumping back to | 4087 | while (modifiers & (down_modifier | drag_modifier |
| 4071 | replay_key, to get another event. | 4088 | | double_modifier | triple_modifier)) |
| 4072 | |||
| 4073 | Note that if this event came from mock input, | ||
| 4074 | then just jumping back to replay_key will just | ||
| 4075 | hand it to us again. So we have to wipe out any | ||
| 4076 | mock input. | ||
| 4077 | |||
| 4078 | We could delete keybuf[t] and shift everything | ||
| 4079 | after that to the left by one spot, but we'd also | ||
| 4080 | have to fix up any variable that points into | ||
| 4081 | keybuf, and shifting isn't really necessary | ||
| 4082 | anyway. | ||
| 4083 | |||
| 4084 | Adding prefixes for non-textual mouse clicks | ||
| 4085 | creates two characters of mock input, and both | ||
| 4086 | must be thrown away. If we're only looking at | ||
| 4087 | the prefix now, we can just jump back to | ||
| 4088 | replay_key. On the other hand, if we've already | ||
| 4089 | processed the prefix, and now the actual click | ||
| 4090 | itself is giving us trouble, then we've lost the | ||
| 4091 | state of the keymaps we want to backtrack to, and | ||
| 4092 | we need to replay the whole sequence to rebuild | ||
| 4093 | it. | ||
| 4094 | |||
| 4095 | Beyond that, only function key expansion could | ||
| 4096 | create more than two keys, but that should never | ||
| 4097 | generate mouse events, so it's okay to zero | ||
| 4098 | mock_input in that case too. | ||
| 4099 | |||
| 4100 | Isn't this just the most wonderful code ever? */ | ||
| 4101 | if (t == last_real_key_start) | ||
| 4102 | { | ||
| 4103 | mock_input = 0; | ||
| 4104 | goto replay_key; | ||
| 4105 | } | ||
| 4106 | else | ||
| 4107 | { | ||
| 4108 | mock_input = last_real_key_start; | ||
| 4109 | goto replay_sequence; | ||
| 4110 | } | ||
| 4111 | } | ||
| 4112 | |||
| 4113 | /* We turn unbound `drag-' events into `click-' | ||
| 4114 | events, if the click would be bound. */ | ||
| 4115 | else if (modifiers & (drag_modifier | double_modifier | ||
| 4116 | | triple_modifier)) | ||
| 4117 | { | ||
| 4118 | while (modifiers & (drag_modifier | double_modifier | ||
| 4119 | | triple_modifier)) | ||
| 4120 | { | 4089 | { |
| 4121 | Lisp_Object new_head, new_click; | 4090 | Lisp_Object new_head, new_click; |
| 4122 | if (modifiers & triple_modifier) | 4091 | if (modifiers & triple_modifier) |
| 4123 | modifiers ^= (double_modifier | triple_modifier); | 4092 | modifiers ^= (double_modifier | triple_modifier); |
| 4124 | else | 4093 | else if (modifiers & (drag_modifier | double_modifier)) |
| 4125 | modifiers &= ~(drag_modifier | double_modifier); | 4094 | modifiers &= ~(drag_modifier | double_modifier); |
| 4095 | else | ||
| 4096 | { | ||
| 4097 | /* Dispose of this `down' event by simply jumping | ||
| 4098 | back to replay_key, to get another event. | ||
| 4099 | |||
| 4100 | Note that if this event came from mock input, | ||
| 4101 | then just jumping back to replay_key will just | ||
| 4102 | hand it to us again. So we have to wipe out any | ||
| 4103 | mock input. | ||
| 4104 | |||
| 4105 | We could delete keybuf[t] and shift everything | ||
| 4106 | after that to the left by one spot, but we'd also | ||
| 4107 | have to fix up any variable that points into | ||
| 4108 | keybuf, and shifting isn't really necessary | ||
| 4109 | anyway. | ||
| 4110 | |||
| 4111 | Adding prefixes for non-textual mouse clicks | ||
| 4112 | creates two characters of mock input, and both | ||
| 4113 | must be thrown away. If we're only looking at | ||
| 4114 | the prefix now, we can just jump back to | ||
| 4115 | replay_key. On the other hand, if we've already | ||
| 4116 | processed the prefix, and now the actual click | ||
| 4117 | itself is giving us trouble, then we've lost the | ||
| 4118 | state of the keymaps we want to backtrack to, and | ||
| 4119 | we need to replay the whole sequence to rebuild | ||
| 4120 | it. | ||
| 4121 | |||
| 4122 | Beyond that, only function key expansion could | ||
| 4123 | create more than two keys, but that should never | ||
| 4124 | generate mouse events, so it's okay to zero | ||
| 4125 | mock_input in that case too. | ||
| 4126 | |||
| 4127 | Isn't this just the most wonderful code ever? */ | ||
| 4128 | if (t == last_real_key_start) | ||
| 4129 | { | ||
| 4130 | mock_input = 0; | ||
| 4131 | goto replay_key; | ||
| 4132 | } | ||
| 4133 | else | ||
| 4134 | { | ||
| 4135 | mock_input = last_real_key_start; | ||
| 4136 | goto replay_sequence; | ||
| 4137 | } | ||
| 4138 | } | ||
| 4139 | |||
| 4126 | new_head = | 4140 | new_head = |
| 4127 | apply_modifiers (modifiers, XCONS (breakdown)->car); | 4141 | apply_modifiers (modifiers, XCONS (breakdown)->car); |
| 4128 | new_click = | 4142 | new_click = |