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