Mercurial > emacs
comparison src/keyboard.c @ 4397:d6d07b43f6d5
(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.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sun, 01 Aug 1993 18:48:20 +0000 |
parents | 9c6571823ab8 |
children | 02b7d9476fae |
comparison
equal
deleted
inserted
replaced
4396:0ab53cbfac0e | 4397:d6d07b43f6d5 |
---|---|
2178 static Lisp_Object button_down_location; | 2178 static Lisp_Object button_down_location; |
2179 | 2179 |
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, |
2190 or Qt for no time limit. */ | 2190 or Qt for no time limit. */ |
2191 Lisp_Object Vdouble_click_time; | 2191 Lisp_Object Vdouble_click_time; |
2225 just above, and the shift key was taken care of by the X code, | 2225 just above, and the shift key was taken care of by the X code, |
2226 and applied to control characters by make_ctrl_char. */ | 2226 and applied to control characters by make_ctrl_char. */ |
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, |
2241 (sizeof (lispy_function_keys) | 2241 (sizeof (lispy_function_keys) |
2242 / sizeof (lispy_function_keys[0]))); | 2242 / sizeof (lispy_function_keys[0]))); |
2246 a press, click or drag, and build the appropriate structure. */ | 2246 a press, click or drag, and build the appropriate structure. */ |
2247 case mouse_click: | 2247 case mouse_click: |
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; |
2254 | 2255 |
2255 if (button < 0 || button >= NUM_MOUSE_BUTTONS) | 2256 if (button < 0 || button >= NUM_MOUSE_BUTTONS) |
2337 start_pos_ptr = &XVECTOR (button_down_location)->contents[button]; | 2338 start_pos_ptr = &XVECTOR (button_down_location)->contents[button]; |
2338 | 2339 |
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. */ |
2349 else if (event->modifiers & up_modifier) | 2374 else if (event->modifiers & up_modifier) |
2350 { | 2375 { |
2370 Lisp_Object down = Fnth (make_number (2), start_pos); | 2395 Lisp_Object down = Fnth (make_number (2), start_pos); |
2371 | 2396 |
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 } |
2405 } | 2413 } |
2406 else | 2414 else |
2656 if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } | 2664 if (modifiers & ctrl_modifier) { *p++ = 'C'; *p++ = '-'; } |
2657 if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } | 2665 if (modifiers & hyper_modifier) { *p++ = 'H'; *p++ = '-'; } |
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++ = '-'; } |
2669 if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; } | |
2670 if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; } | |
2661 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } | 2671 if (modifiers & down_modifier) { strcpy (p, "down-"); p += 5; } |
2662 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } | 2672 if (modifiers & drag_modifier) { strcpy (p, "drag-"); p += 5; } |
2663 if (modifiers & double_modifier) { strcpy (p, "double-"); p += 7; } | |
2664 if (modifiers & triple_modifier) { strcpy (p, "triple-"); p += 7; } | |
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'; |
2668 | 2676 |
2669 mod_len = p - new_mods; | 2677 mod_len = p - new_mods; |
4062 if (XTYPE (head) == Lisp_Symbol) | 4070 if (XTYPE (head) == Lisp_Symbol) |
4063 { | 4071 { |
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); |
4093 else if (modifiers & (drag_modifier | double_modifier)) | |
4094 modifiers &= ~(drag_modifier | double_modifier); | |
4124 else | 4095 else |
4125 modifiers &= ~(drag_modifier | double_modifier); | 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 = |
4129 Fcons (new_head, Fcons (EVENT_START (key), Qnil)); | 4143 Fcons (new_head, Fcons (EVENT_START (key), Qnil)); |
4130 | 4144 |