comparison src/keyboard.c @ 1711:4cd44b41f1e3

* keyboard.c: Protect all references to kbd_buffer_frames with #ifdef MULTI_FRAME. * frame.h (struct frame): New fields `can_have_scrollbars' and `has_vertical_scrollbars'. (FRAME_CAN_HAVE_SCROLLBARS, FRAME_HAS_VERTICAL_SCROLLBARS): New accessors, for both the MULTI_FRAME and non-MULTI_FRAME. (VERTICAL_SCROLLBAR_WIDTH, WINDOW_VERTICAL_SCROLLBAR, WINDOW_VERTICAL_SCROLLBAR_COLUMN, WINDOW_VERTICAL_SCROLLBAR_HEIGHT): New macros. * window.h (struct window): New field `vertical_scrollbar'. * xterm.h (struct x_display): vertical_scrollbars, judge_timestamp, vertical_scrollbar_extra: New fields. (struct scrollbar): New struct. (VERTICAL_SCROLLBAR_PIXEL_WIDTH, VERTICAL_SCROLLBAR_PIXEL_HEIGHT, VERTICAL_SCROLLBAR_LEFT_BORDER, VERTICAL_SCROLLBAR_RIGHT_BORDER, VERTICAL_SCROLLBAR_TOP_BORDER, VERTICAL_SCROLLBAR_BOTTOM_BORDER, CHAR_TO_PIXEL_WIDTH, CHAR_TO_PIXEL_HEIGHT, PIXEL_TO_CHAR_WIDTH, PIXEL_TO_CHAR_HEIGHT): New accessors and macros. * frame.c (make_frame): Initialize the `can_have_scrollbars' and `has_vertical_scrollbars' fields of the frame. * term.c (term_init): Note that TERMCAP terminals don't support scrollbars. (mouse_position_hook): Document new args. (set_vertical_scrollbar_hook, condemn_scrollbars_hook, redeem_scrollbar_hook, judge_scrollbars_hook): New hooks. * termhooks.h: Declare and document them. (enum scrollbar_part): New type. (struct input_event): Describe the new form of the scrollbar_click event type. Change `part' from a Lisp_Object to an enum scrollbar_part. Add a new field `scrollbar'. * keyboard.c (kbd_buffer_get_event): Pass appropriate new parameters to *mouse_position_hook, and make_lispy_movement. * xfns.c (x_set_vertical_scrollbar): New function. (x_figure_window_size): Use new macros to calculate frame size. (Fx_create_frame): Note that X Windows frames do support scroll bars. Default to "yes". * xterm.c: #include <X11/cursorfont.h> and "window.h". (x_vertical_scrollbar_cursor): New variable. (x_term_init): Initialize it. (last_mouse_bar, last_mouse_bar_frame, last_mouse_part, last_mouse_scroll_range_start, last_mouse_scroll_range_end): New variables. (XTmouse_position): Use them to return scrollbar movement events. Take new arguments, for that purpose. (x_window_to_scrollbar, x_scrollbar_create, x_scrollbar_set_handle, x_scrollbar_remove, x_scrollbar_move, XTset_scrollbar, XTcondemn_scrollbars, XTredeem_scrollbar, XTjudge_scrollbars, x_scrollbar_expose, x_scrollbar_background_expose, x_scrollbar_handle_click, x_scrollbar_handle_motion): New functions to implement scrollbars. (x_term_init): Set the termhooks.h hooks to point to them. (x_set_window_size): Use new macros to calculate frame size. Set vertical_scrollbar_extra field. (x_make_frame_visible): Use the frame accessor FRAME_HAS_VERTICAL_SCROLLBARS to decide if we need to map the frame's subwindows as well. (XTread_socket): Use new size-calculation macros from xterm.h when processing ConfigureNotify events. (x_wm_set_size_hint): Use PIXEL_TO_CHAR_WIDTH and PIXEL_TO_CHAR_HEIGHT macros. * ymakefile (xdisp.o): This now depends on termhooks.h. (xterm.o): This now depends on window.h. * keyboard.c (Qscrollbar_movement, Qvertical_scrollbar, Qabove_handle, Qhandle, Qbelow_handle): New symbols. (make_lispy_event): New code to build scrollbar clicks. (make_lispy_movement): New code to handle scrollbar movement. (head_table): Include Qscrollbar_movement in the event heads. (syms_of_keyboard): Init and staticpro Qvertical_scrollbar, Qabove_handle, Qhandle, and Qbelow_handle. * keyboard.h (Qscrollbar_movement): Declare this along with the other event types. * lisp.h (Qvertical_scrollbar): Declare this. * window.c (window_from_scrollbar): New function. * xterm.h (struct x_display): Delete v_scrollbar, v_thumbup, v_thumbdown, v_slider, h_scrollbar, h_thumbup, h_thumbdown, h_slider, v_scrollbar_width, h_scrollbar_height fields. * keyboard.c (Qvscrollbar_part, Qvslider_part, Qvthumbup_part, Qvthumbdown_part, Qhscrollbar_part, Qhslider_part, Qhthumbup_part, Qhthumbdown_part, Qscrollbar_click): Deleted; part of an obsolete interface. (head_table): Removed from here as well. (syms_of_keyboard): And here. * keyboard.h: And here. (POSN_SCROLLBAR_BUTTON): Removed. * xscrollbar.h: File removed - no longer necessary. * xfns.c: Don't #include it any more. (Qhorizontal_scroll_bar, Qvertical_scroll_bar): Deleted. (syms_of_xfns): Don't initialize or staticpro them. (gray_bits): Salvaged from xscrollbar.h. (x_window_to_scrollbar): Deleted. (x_set_horizontal_scrollbar): Deleted. (enum x_frame_parm, x_frame_parms): Remove references to x_set_horizontal_scrollbar. (x_set_foreground_color, x_set_background_color, x_set_border_pixel): Remove special code to support scrollbars. (Fx_create_frame): Remove old scrollbar setup code. (install_vertical_scrollbar, install_horizontal_scrollbar, adjust_scrollbars, x_resize_scrollbars): Deleted. * xterm.c (construct_mouse_click): This doesn't need to take care of scrollbar clicks anymore. (XTread_socket): Remove old code to support scrollbars. Call new functions instead for events which occur in scrollbar windows. (XTupdate_end): Remove call to adjust_scrollbars; the main redisplay code takes care of that now. (enum window_type): Deleted. * ymakefile: Note that xfns.o no longer depends on xscrollbar.h. * keyboard.c (Fread_key_sequence): Doc fix. * keyboard.c (make_lispy_event): Buttons are numbered starting with zero now. * keyboard.c (make_lispy_event): Use the proper accessors when manipulating the `x' and `y' fields of struct input_event. * keyboard.c (parse_modifiers_uncached): Remember that strncmp returns zero if the two substrings are equal. * keyboard.c (do_mouse_tracking, Ftrack_mouse): Doc fix. * keyboard.c (read_char): Don't put mouse movements in this_command_keys. Change the meaning of focus redirection to make switching windows work properly. Fredirect_frame_focus has the details. * frame.h (focus_frame): Doc fix. [not MULTI_FRAME] (FRAME_FOCUS_FRAME): Make this Qnil, which indicates no focus redirection, instead of zero, which is selected_frame. * frame.c (make_frame): Initialize f->focus_frame to Qnil, rather than making it point to frame itself. (Fselect_frame): If changing the selected frame from FOO to BAR, make all redirections to FOO shift to BAR as well. Doc fix. (Fredirect_frame_focus): Doc fix. Accept nil as a valid redirection, not just as a default for FRAME. (Fframe_focus): Doc fix. * keyboard.c (kbd_buffer_store_event, kbd_buffer_get_event): Deal with focus redirections being nil. * xterm.c (XTframe_rehighlight): Doc fix. Deal with focus redirections being nil. * keyboard.c (kbd_buffer_frames): New vector, to GCPRO frames in kbd_buffer. (kbd_buffer_store_event): When we add an event to kbd_buffer, make sure to store its frame in kbd_buffer_frames. (kbd_buffer_get_event): When we remove an event from kbd_buffer, make sure to set the corresponding element of kbd_buffer_frames to Qnil, to allow the frame to get GC'd. (Fdiscard_input, init_keyboard): Clear all elements of kbd_buffer_frames to nil. (syms_of_keyboard): Create and staticpro kbd_buffer_frames.
author Jim Blandy <jimb@redhat.com>
date Thu, 24 Dec 1992 06:12:04 +0000
parents fe6f6e55182f
children 1f18bfe28e2f
comparison
equal deleted inserted replaced
1710:26054080a152 1711:4cd44b41f1e3
239 extern char *pending_malloc_warning; 239 extern char *pending_malloc_warning;
240 240
241 /* Circular buffer for pre-read keyboard input. */ 241 /* Circular buffer for pre-read keyboard input. */
242 static struct input_event kbd_buffer[KBD_BUFFER_SIZE]; 242 static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
243 243
244 #ifdef MULTI_FRAME
245 /* Vector of frames, to GCPRO the frames mentioned in kbd_buffer.
246
247 The interrupt-level event handlers will never enqueue a frame which
248 is not in Vframe_list, and once an event is dequeued,
249 Vlast_event_frame or the event itself points to the frame. So
250 that's all fine.
251
252 But while the event is sitting in the queue, it's completely
253 unprotected. Suppose the user types one command which will run for
254 a while and then delete a frame, and then types another event at
255 the frame that will be deleted, before the command gets around to
256 it. Suppose there are no references to this frame elsewhere in
257 Emacs, and a GC occurs before the second event is dequeued. Now we
258 have an event referring to a freed frame, which will crash Emacs
259 when it is dequeued.
260
261 So, we use this vector to protect any frames in the event queue.
262 That way, they'll be dequeued as dead frames, but still valid lisp
263 objects.
264
265 If kbd_buffer[i] != 0, then
266 (XFRAME (XVECTOR (kbd_buffer_frames)->contents[i])
267 == kbd_buffer[i].frame). */
268 static Lisp_Object kbd_buffer_frames;
269 #endif
270
244 /* Pointer to next available character in kbd_buffer. 271 /* Pointer to next available character in kbd_buffer.
245 If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. 272 If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
246 This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the the 273 This may be kbd_buffer + KBD_BUFFER_SIZE, meaning that the the
247 next available char is in kbd_buffer[0]. */ 274 next available char is in kbd_buffer[0]. */
248 static struct input_event *kbd_fetch_ptr; 275 static struct input_event *kbd_fetch_ptr;
256 static struct input_event *kbd_store_ptr; 283 static struct input_event *kbd_store_ptr;
257 284
258 /* The above pair of variables forms a "queue empty" flag. When we 285 /* The above pair of variables forms a "queue empty" flag. When we
259 enqueue a non-hook event, we increment kbd_write_count. When we 286 enqueue a non-hook event, we increment kbd_write_count. When we
260 dequeue a non-hook event, we increment kbd_read_count. We say that 287 dequeue a non-hook event, we increment kbd_read_count. We say that
261 there is input available iff the two counters are equal. 288 there is input available iff the two counters are not equal.
262 289
263 Why not just have a flag set and cleared by the enqueuing and 290 Why not just have a flag set and cleared by the enqueuing and
264 dequeuing functions? Such a flag could be screwed up by interrupts 291 dequeuing functions? Such a flag could be screwed up by interrupts
265 at inopportune times. */ 292 at inopportune times. */
266 293
267 /* If this flag is non-zero, mouse movement events will appear in the 294 /* If this flag is non-zero, we will check mouse_moved to see when the
268 input stream. If is zero, mouse movement will be ignored. */ 295 mouse moves, and motion events will appear in the input stream. If
296 it is zero, mouse motion will be ignored. */
269 int do_mouse_tracking; 297 int do_mouse_tracking;
270 298
271 /* The window system handling code should set this if the mouse has 299 /* The window system handling code should set this if the mouse has
272 moved since the last call to the mouse_position_hook. Calling that 300 moved since the last call to the mouse_position_hook. Calling that
273 hook should clear this. Code assumes that if this is set, it can 301 hook should clear this. Code assumes that if this is set, it can
284 ((kbd_fetch_ptr == kbd_store_ptr) && (!do_mouse_tracking || !mouse_moved)) 312 ((kbd_fetch_ptr == kbd_store_ptr) && (!do_mouse_tracking || !mouse_moved))
285 313
286 314
287 /* Symbols to head events. */ 315 /* Symbols to head events. */
288 Lisp_Object Qmouse_movement; 316 Lisp_Object Qmouse_movement;
289 317 Lisp_Object Qscrollbar_movement;
290 Lisp_Object Qvscrollbar_part;
291 Lisp_Object Qvslider_part;
292 Lisp_Object Qvthumbup_part;
293 Lisp_Object Qvthumbdown_part;
294
295 Lisp_Object Qhscrollbar_part;
296 Lisp_Object Qhslider_part;
297 Lisp_Object Qhthumbleft_part;
298 Lisp_Object Qhthumbright_part;
299 318
300 Lisp_Object Qswitch_frame; 319 Lisp_Object Qswitch_frame;
301 320
302 /* Symbols to denote kinds of events. */ 321 /* Symbols to denote kinds of events. */
303 Lisp_Object Qfunction_key; 322 Lisp_Object Qfunction_key;
304 Lisp_Object Qmouse_click; 323 Lisp_Object Qmouse_click;
305 /* Lisp_Object Qmouse_movement; - also an event header */ 324 /* Lisp_Object Qmouse_movement; - also an event header */
306 Lisp_Object Qscrollbar_click;
307 325
308 /* Properties of event headers. */ 326 /* Properties of event headers. */
309 Lisp_Object Qevent_kind; 327 Lisp_Object Qevent_kind;
310 Lisp_Object Qevent_symbol_elements; 328 Lisp_Object Qevent_symbol_elements;
311 329
323 Lisp_Object Qmodifier_cache; 341 Lisp_Object Qmodifier_cache;
324 342
325 /* Symbols to use for non-text mouse positions. */ 343 /* Symbols to use for non-text mouse positions. */
326 Lisp_Object Qmode_line; 344 Lisp_Object Qmode_line;
327 Lisp_Object Qvertical_line; 345 Lisp_Object Qvertical_line;
346 Lisp_Object Qvertical_scrollbar;
328 347
329 Lisp_Object recursive_edit_unwind (), command_loop (); 348 Lisp_Object recursive_edit_unwind (), command_loop ();
330 Lisp_Object Fthis_command_keys (); 349 Lisp_Object Fthis_command_keys ();
331 350
332 /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt 351 /* Address (if not 0) of EMACS_TIME to zero out if a SIGIO interrupt
1354 1373
1355 from_macro: 1374 from_macro:
1356 reread_first: 1375 reread_first:
1357 echo_char (c); 1376 echo_char (c);
1358 1377
1359 /* Record this character as part of the current key. */ 1378 /* Record this character as part of the current key.
1360 add_command_key (c); 1379 Don't record mouse motion; it should never matter. */
1380 if (! (EVENT_HAS_PARAMETERS (c)
1381 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
1382 add_command_key (c);
1361 1383
1362 /* Re-reading in the middle of a command */ 1384 /* Re-reading in the middle of a command */
1363 reread: 1385 reread:
1364 last_input_char = c; 1386 last_input_char = c;
1365 num_input_chars++; 1387 num_input_chars++;
1460 } 1482 }
1461 } 1483 }
1462 } 1484 }
1463 1485
1464 DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0, 1486 DEFUN ("track-mouse", Ftrack_mouse, Strack_mouse, 0, UNEVALLED, 0,
1465 "Evaluate BODY with mouse movement and button release events enabled.\n\ 1487 "Evaluate BODY with mouse movement events enabled.\n\
1466 Within a `track-mouse', mouse motion and button releases generate input\n\ 1488 Within a `track-mouse' form, mouse motion generates input events that\n\
1467 events that you can read with `read-event'.\n\ 1489 you can read with `read-event'.\n\
1468 Normally, these occurrences don't generate events.") 1490 Normally, mouse motion is ignored.")
1469 (args) 1491 (args)
1470 Lisp_Object args; 1492 Lisp_Object args;
1471 { 1493 {
1472 int count = specpdl_ptr - specpdl; 1494 int count = specpdl_ptr - specpdl;
1473 Lisp_Object val; 1495 Lisp_Object val;
1502 #ifdef MULTI_FRAME 1524 #ifdef MULTI_FRAME
1503 /* If this results in a quit_char being returned to Emacs as 1525 /* If this results in a quit_char being returned to Emacs as
1504 input, set last-event-frame properly. If this doesn't 1526 input, set last-event-frame properly. If this doesn't
1505 get returned to Emacs as an event, the next event read 1527 get returned to Emacs as an event, the next event read
1506 will set Vlast_event_frame again, so this is safe to do. */ 1528 will set Vlast_event_frame again, so this is safe to do. */
1507 Vlast_event_frame = FRAME_FOCUS_FRAME (event->frame); 1529 {
1530 Lisp_Object focus = FRAME_FOCUS_FRAME (event->frame);
1531
1532 if (NILP (focus))
1533 Vlast_event_frame = focus;
1534 else
1535 XSET (Vlast_event_frame, Lisp_Frame, event->frame);
1536 }
1508 #endif 1537 #endif
1509 1538
1510 last_event_timestamp = event->timestamp; 1539 last_event_timestamp = event->timestamp;
1511 interrupt_signal (); 1540 interrupt_signal ();
1512 return; 1541 return;
1536 kbd_store_ptr->frame = event->frame; 1565 kbd_store_ptr->frame = event->frame;
1537 kbd_store_ptr->modifiers = event->modifiers; 1566 kbd_store_ptr->modifiers = event->modifiers;
1538 kbd_store_ptr->x = event->x; 1567 kbd_store_ptr->x = event->x;
1539 kbd_store_ptr->y = event->y; 1568 kbd_store_ptr->y = event->y;
1540 kbd_store_ptr->timestamp = event->timestamp; 1569 kbd_store_ptr->timestamp = event->timestamp;
1570 #ifdef MULTI_FRAME
1571 XSET (XVECTOR (kbd_buffer_frames)->contents[kbd_store_ptr - kbd_buffer],
1572 Lisp_Frame,
1573 event->frame);
1574 #endif
1541 1575
1542 kbd_store_ptr++; 1576 kbd_store_ptr++;
1543 } 1577 }
1544 } 1578 }
1545 1579
1608 ? kbd_fetch_ptr 1642 ? kbd_fetch_ptr
1609 : kbd_buffer); 1643 : kbd_buffer);
1610 1644
1611 last_event_timestamp = event->timestamp; 1645 last_event_timestamp = event->timestamp;
1612 1646
1647 obj = Qnil;
1648
1649 #ifdef MULTI_FRAME
1650 /* If this event is on a different frame, return a switch-frame this
1651 time, and leave the event in the queue for next time. */
1613 { 1652 {
1614 #ifdef MULTI_FRAME 1653 Lisp_Object frame = FRAME_FOCUS_FRAME (event->frame);
1615 Lisp_Object frame; 1654
1616 1655 if (NILP (frame))
1617 /* If this event is on a different frame, return a switch-frame this 1656 XSET (frame, Lisp_Frame, event->frame);
1618 time, and leave the event in the queue for next time. */ 1657
1619 XSET (frame, Lisp_Frame, XFRAME (FRAME_FOCUS_FRAME (event->frame)));
1620 if (! EQ (frame, Vlast_event_frame)) 1658 if (! EQ (frame, Vlast_event_frame))
1621 { 1659 {
1622 Vlast_event_frame = frame; 1660 Vlast_event_frame = frame;
1623 obj = make_lispy_switch_frame (frame); 1661 obj = make_lispy_switch_frame (frame);
1624 } 1662 }
1625 else 1663 }
1626 #endif 1664 #endif
1627 { 1665
1628 obj = make_lispy_event (event); 1666 /* If we didn't decide to make a switch-frame event, go ahead
1629 if (XTYPE (obj) == Lisp_Int) 1667 and build a real event from the queue entry. */
1630 XSET (obj, Lisp_Int, XINT (obj) & (meta_key ? 0377 : 0177)); 1668 if (NILP (obj))
1669 {
1670 obj = make_lispy_event (event);
1671 if (XTYPE (obj) == Lisp_Int)
1672 XSET (obj, Lisp_Int, XINT (obj) & (meta_key ? 0377 : 0177));
1631 1673
1632 /* Wipe out this event, to catch bugs. */ 1674 /* Wipe out this event, to catch bugs. */
1633 event->kind = no_event; 1675 event->kind = no_event;
1634 1676 #ifdef MULTI_FRAME
1635 kbd_fetch_ptr = event + 1; 1677 XVECTOR (kbd_buffer_frames)->contents[event - kbd_buffer] = Qnil;
1636 } 1678 #endif
1637 } 1679
1680 kbd_fetch_ptr = event + 1;
1681 }
1638 } 1682 }
1639 else if (do_mouse_tracking && mouse_moved) 1683 else if (do_mouse_tracking && mouse_moved)
1640 { 1684 {
1641 FRAME_PTR frame; 1685 FRAME_PTR f;
1686 struct scrollbar *bar;
1687 enum scrollbar_part part;
1642 Lisp_Object x, y; 1688 Lisp_Object x, y;
1643 unsigned long time; 1689 unsigned long time;
1644 1690
1645 (*mouse_position_hook) (&frame, &x, &y, &time); 1691 (*mouse_position_hook) (&f, &bar, &part, &x, &y, &time);
1692
1693 obj = Qnil;
1646 1694
1647 #ifdef MULTI_FRAME 1695 #ifdef MULTI_FRAME
1648 /* Decide if we should generate a switch-frame event. Don't generate 1696 /* Decide if we should generate a switch-frame event. Don't
1649 switch-frame events for motion outside of all Emacs frames. */ 1697 generate switch-frame events for motion outside of all Emacs
1650 if (frame 1698 frames. */
1651 && (XTYPE (Vlast_event_frame) != Lisp_Frame 1699 if (f)
1652 || frame != XFRAME (Vlast_event_frame)))
1653 { 1700 {
1654 XSET (Vlast_event_frame, Lisp_Frame, frame); 1701 Lisp_Object frame = FRAME_FOCUS_FRAME (f);
1655 obj = make_lispy_switch_frame (Vlast_event_frame); 1702
1703 if (NILP (frame))
1704 XSET (frame, Lisp_Frame, f);
1705
1706 if (! EQ (frame, Vlast_event_frame))
1707 {
1708 XSET (Vlast_event_frame, Lisp_Frame, frame);
1709 obj = make_lispy_switch_frame (Vlast_event_frame);
1710 }
1656 } 1711 }
1657 else
1658 #endif 1712 #endif
1659 obj = make_lispy_movement (frame, x, y, time); 1713
1660 } 1714 /* If we didn't decide to make a switch-frame event, go ahead and
1715 return a mouse-motion event. */
1716 if (NILP (obj))
1717 obj = make_lispy_movement (f, bar, part, x, y, time);
1718 }
1661 else 1719 else
1662 /* We were promised by the above while loop that there was 1720 /* We were promised by the above while loop that there was
1663 something for us to read! */ 1721 something for us to read! */
1664 abort (); 1722 abort ();
1665 1723
1666 input_pending = readable_events (); 1724 input_pending = readable_events ();
1667 1725
1668 return (obj); 1726 return (obj);
1669 } 1727 }
1728
1670 1729
1671 /* Caches for modify_event_symbol. */ 1730 /* Caches for modify_event_symbol. */
1672 static Lisp_Object func_key_syms; 1731 static Lisp_Object func_key_syms;
1673 static Lisp_Object mouse_syms; 1732 static Lisp_Object mouse_syms;
1674 1733
1751 static char *lispy_mouse_names[] = 1810 static char *lispy_mouse_names[] =
1752 { 1811 {
1753 "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5" 1812 "mouse-1", "mouse-2", "mouse-3", "mouse-4", "mouse-5"
1754 }; 1813 };
1755 1814
1815 /* Scrollbar parts. */
1816 Lisp_Object Qabove_handle, Qhandle, Qbelow_handle;
1817
1818 /* An array of scrollbar parts, indexed by an enum scrollbar_part value. */
1819 Lisp_Object *scrollbar_parts[] = {
1820 &Qabove_handle, &Qhandle, &Qbelow_handle
1821 };
1822
1823
1756 /* make_lispy_event stores the down-going location of the currently 1824 /* make_lispy_event stores the down-going location of the currently
1757 depressed buttons in button_down_locations. */ 1825 depressed buttons in button_down_locations. */
1758 struct mouse_position { 1826 struct mouse_position {
1759 Lisp_Object window; 1827 Lisp_Object window;
1760 Lisp_Object buffer_pos; 1828 Lisp_Object buffer_pos;
1847 /* Now we're releasing a button - check the co-ordinates to 1915 /* Now we're releasing a button - check the co-ordinates to
1848 see if this was a click or a drag. */ 1916 see if this was a click or a drag. */
1849 else if (event->modifiers & up_modifier) 1917 else if (event->modifiers & up_modifier)
1850 { 1918 {
1851 event->modifiers &= ~up_modifier; 1919 event->modifiers &= ~up_modifier;
1852 event->modifiers |= ((event->x == loc->x && event->y == loc->y) 1920 event->modifiers |= ((EQ (event->x, loc->x)
1921 && EQ (event->y, loc->y))
1853 ? click_modifier 1922 ? click_modifier
1854 : drag_modifier); 1923 : drag_modifier);
1855 } 1924 }
1856 else 1925 else
1857 /* Every mouse event should either have the down_modifier or 1926 /* Every mouse event should either have the down_modifier or
1862 /* Build the event. */ 1931 /* Build the event. */
1863 { 1932 {
1864 Lisp_Object head, start, end; 1933 Lisp_Object head, start, end;
1865 1934
1866 /* Build the components of the event. */ 1935 /* Build the components of the event. */
1867 head = modify_event_symbol (button - 1, 1936 head = modify_event_symbol (button,
1868 event->modifiers, 1937 event->modifiers,
1869 Qmouse_click, 1938 Qmouse_click,
1870 lispy_mouse_names, &mouse_syms, 1939 lispy_mouse_names, &mouse_syms,
1871 (sizeof (lispy_mouse_names) 1940 (sizeof (lispy_mouse_names)
1872 / sizeof (lispy_mouse_names[0]))); 1941 / sizeof (lispy_mouse_names[0])));
1893 Fcons (end, 1962 Fcons (end,
1894 Qnil)); 1963 Qnil));
1895 } 1964 }
1896 } 1965 }
1897 1966
1898 /* A scrollbar click. Build a list containing the relevant 1967 /* A scrollbar click. Build a scrollbar click list. */
1899 information. */
1900 case scrollbar_click: 1968 case scrollbar_click:
1901 { 1969 {
1902 Lisp_Object button 1970 Lisp_Object button =
1903 = modify_event_symbol (XFASTINT (event->code) - 1, 1971 modify_event_symbol (button,
1904 event->modifiers, 1972 event->modifiers,
1905 Qmouse_click, 1973 Qmouse_click,
1906 lispy_mouse_names, &mouse_syms, 1974 lispy_mouse_names, &mouse_syms,
1907 (sizeof (lispy_mouse_names) 1975 (sizeof (lispy_mouse_names)
1908 / sizeof (lispy_mouse_names[0]))); 1976 / sizeof (lispy_mouse_names[0])));
1909 return Fcons (event->part, 1977 Lisp_Object window =
1910 Fcons (FRAME_SELECTED_WINDOW (event->frame), 1978 window_from_scrollbar (event->frame, event->scrollbar);
1911 Fcons (button, 1979 Lisp_Object portion_whole = Fcons (event->x, event->y);
1912 Fcons (Fcons (event->x, event->y), 1980 Lisp_Object part = *scrollbar_parts[(int) event->part];
1913 Fcons (make_number 1981 Lisp_Object total_posn =
1914 (event->timestamp), 1982 Fcons (window,
1915 Qnil))))); 1983 Fcons (Qvertical_scrollbar,
1984 Fcons (portion_whole,
1985 Fcons (make_number (event->timestamp),
1986 Fcons (part,
1987 Qnil)))));
1988
1989 return Fcons (button, Fcons (total_posn, Qnil));
1916 } 1990 }
1917 1991
1918 /* The 'kind' field of the event is something we don't recognize. */ 1992 /* The 'kind' field of the event is something we don't recognize. */
1919 default: 1993 default:
1920 abort(); 1994 abort();
1921 } 1995 }
1922 } 1996 }
1923 1997
1924 static Lisp_Object 1998 static Lisp_Object
1925 make_lispy_movement (frame, x, y, time) 1999 make_lispy_movement (frame, bar, part, x, y, time)
1926 FRAME_PTR frame; 2000 FRAME_PTR frame;
2001 struct scrollbar *bar;
2002 enum scrollbar_part part;
1927 Lisp_Object x, y; 2003 Lisp_Object x, y;
1928 unsigned long time; 2004 unsigned long time;
1929 { 2005 {
1930 Lisp_Object window; 2006 /* Is it a scrollbar movement? */
1931 int ix, iy; 2007 if (bar)
1932 Lisp_Object posn; 2008 {
1933 int part; 2009 Lisp_Object window = window_from_scrollbar (frame, bar);
1934 2010 Lisp_Object part = *scrollbar_parts[(int) part];
1935 ix = XINT (x); 2011
1936 iy = XINT (y); 2012 return Fcons (Qscrollbar_movement,
1937 window = (frame 2013 (Fcons (Fcons (window,
1938 ? window_from_coordinates (frame, ix, iy, &part) 2014 Fcons (Qvertical_scrollbar,
1939 : Qnil); 2015 Fcons (Fcons (x, y),
1940 if (XTYPE (window) != Lisp_Window) 2016 Fcons (make_number (time),
1941 posn = Qnil; 2017 Fcons (part,
2018 Qnil))))),
2019 Qnil)));
2020 }
2021
2022 /* Or is it an ordinary mouse movement? */
1942 else 2023 else
1943 { 2024 {
1944 ix -= XINT (XWINDOW (window)->left); 2025 int area;
1945 iy -= XINT (XWINDOW (window)->top); 2026 Lisp_Object window =
1946 if (part == 1) 2027 (frame
1947 posn = Qmode_line; 2028 ? window_from_coordinates (frame, XINT (x), XINT (y), &area)
1948 else if (part == 2) 2029 : Qnil);
1949 posn = Qvertical_line; 2030 Lisp_Object posn;
2031
2032 if (XTYPE (window) == Lisp_Window)
2033 {
2034 XSETINT (x, XINT (x) - XINT (XWINDOW (window)->left));
2035 XSETINT (y, XINT (y) - XINT (XWINDOW (window)->top));
2036
2037 if (area == 1)
2038 posn = Qmode_line;
2039 else if (area == 2)
2040 posn = Qvertical_line;
2041 else
2042 XSET (posn, Lisp_Int,
2043 buffer_posn_from_coords (XWINDOW (window),
2044 XINT (x), XINT (y)));
2045 }
1950 else 2046 else
1951 XSET (posn, Lisp_Int, buffer_posn_from_coords (XWINDOW (window), 2047 {
1952 ix, iy)); 2048 window = Qnil;
1953 } 2049 posn = Qnil;
1954 2050 }
1955 XSETINT (x, ix); 2051
1956 XSETINT (y, iy); 2052 return Fcons (Qmouse_movement,
1957 return Fcons (Qmouse_movement, 2053 Fcons (Fcons (window,
1958 Fcons (Fcons (window, 2054 Fcons (posn,
1959 Fcons (posn, 2055 Fcons (Fcons (x, y),
1960 Fcons (Fcons (x, y), 2056 Fcons (make_number (time),
1961 Fcons (make_number (time), 2057 Qnil)))),
1962 Qnil)))), 2058 Qnil));
1963 Qnil)); 2059 }
1964 } 2060 }
1965 2061
1966 2062
1967 /* Construct a switch frame event. */ 2063 /* Construct a switch frame event. */
1968 static Lisp_Object 2064 static Lisp_Object
2059 no_more_modifiers: 2155 no_more_modifiers:
2060 2156
2061 /* Should we include the `click' modifier? */ 2157 /* Should we include the `click' modifier? */
2062 if (! (modifiers & (down_modifier | drag_modifier)) 2158 if (! (modifiers & (down_modifier | drag_modifier))
2063 && i + 7 == name->size 2159 && i + 7 == name->size
2064 && strncmp (name->data + i, "mouse-", 6) 2160 && strncmp (name->data + i, "mouse-", 6) == 0
2065 && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9')) 2161 && ('0' <= name->data[i + 6] && name->data[i + 6] <= '9'))
2066 modifiers |= click_modifier; 2162 modifiers |= click_modifier;
2067 2163
2068 if (modifier_end) 2164 if (modifier_end)
2069 *modifier_end = i; 2165 *modifier_end = i;
2307 if (symbol_num < 0 || symbol_num >= table_size) 2403 if (symbol_num < 0 || symbol_num >= table_size)
2308 abort (); 2404 abort ();
2309 2405
2310 /* If *symbol_table doesn't seem to be initialized properly, fix that. 2406 /* If *symbol_table doesn't seem to be initialized properly, fix that.
2311 *symbol_table should be a lisp vector TABLE_SIZE elements long, 2407 *symbol_table should be a lisp vector TABLE_SIZE elements long,
2312 where the Nth element is the symbol for NAME_TABLE[N]. */ 2408 where the Nth element is the symbol for NAME_TABLE[N], or nil if
2409 we've never used that symbol before. */
2313 if (XTYPE (*symbol_table) != Lisp_Vector 2410 if (XTYPE (*symbol_table) != Lisp_Vector
2314 || XVECTOR (*symbol_table)->size != table_size) 2411 || XVECTOR (*symbol_table)->size != table_size)
2315 { 2412 {
2316 Lisp_Object size; 2413 Lisp_Object size;
2317 2414
3310 \n\ 3407 \n\
3311 First arg PROMPT is a prompt string. If nil, do not prompt specially.\n\ 3408 First arg PROMPT is a prompt string. If nil, do not prompt specially.\n\
3312 Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos\n\ 3409 Second (optional) arg CONTINUE-ECHO, if non-nil, means this key echos\n\
3313 as a continuation of the previous key.\n\ 3410 as a continuation of the previous key.\n\
3314 \n\ 3411 \n\
3315 If Emacs is running on multiple frames, switching between frames in\n\ 3412
3316 the midst of a keystroke will toss any prefix typed so far. A C-g\n\ 3413 A C-g typed while in this function is treated like any other character,
3317 typed while in this function is treated like any other character, and\n\ 3414 and `quit-flag' is not set.
3318 `quit-flag' is not set.") 3415
3416 If the key sequence starts with a mouse click, then the sequence is read
3417 using the keymaps of the buffer of the window clicked in, not the buffer
3418 of the selected window as normal.
3419
3420 `read-key-sequence' drops unbound button-down events, since you normally
3421 only care about the click or drag events which follow them. If a drag
3422 event is unbound, but the corresponding click event would be bound,
3423 `read-key-sequence' turns the drag event into a click event at the
3424 drag's starting position. This means that you don't have to distinguish
3425 between click and drag events unless you want to.
3426
3427 `read-key-sequence' prefixes mouse events on mode lines, the vertical
3428 lines separating windows, and scrollbars with imaginary keys
3429 `mode-line', `vertical-line', and `vertical-scrollbar'.
3430
3431 If the user switches frames in the middle of a key sequence, the
3432 frame-switch event is put off until after the current key sequence.
3433
3434 `read-key-sequence' checks `function-key-map' for function key
3435 sequences, where they wouldn't conflict with ordinary bindings. See
3436 `function-key-map' for more details.")
3319 (prompt, continue_echo) 3437 (prompt, continue_echo)
3320 Lisp_Object prompt, continue_echo; 3438 Lisp_Object prompt, continue_echo;
3321 { 3439 {
3322 Lisp_Object keybuf[30]; 3440 Lisp_Object keybuf[30];
3323 register int i; 3441 register int i;
3582 3700
3583 /* Without the cast, GCC complains that this assignment loses the 3701 /* Without the cast, GCC complains that this assignment loses the
3584 volatile qualifier of kbd_store_ptr. Is there anything wrong 3702 volatile qualifier of kbd_store_ptr. Is there anything wrong
3585 with that? */ 3703 with that? */
3586 kbd_fetch_ptr = (struct input_event *) kbd_store_ptr; 3704 kbd_fetch_ptr = (struct input_event *) kbd_store_ptr;
3705 #ifdef MULTI_FRAME
3706 Ffillarray (kbd_buffer_frames, Qnil);
3707 #endif
3587 input_pending = 0; 3708 input_pending = 0;
3588 3709
3589 return Qnil; 3710 return Qnil;
3590 } 3711 }
3591 3712
3674 { 3795 {
3675 if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE) 3796 if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
3676 kbd_fetch_ptr = kbd_buffer; 3797 kbd_fetch_ptr = kbd_buffer;
3677 if (kbd_fetch_ptr->kind == ascii_keystroke) 3798 if (kbd_fetch_ptr->kind == ascii_keystroke)
3678 stuff_char (XINT (kbd_fetch_ptr->code)); 3799 stuff_char (XINT (kbd_fetch_ptr->code));
3800 kbd_fetch_ptr->kind = no_event;
3801 #ifdef MULTI_FRAME
3802 XVECTOR (kbd_buffer_frames)->contents[kbd_fetch_ptr - kbd_buffer]
3803 = Qnil;
3804 #endif
3679 kbd_fetch_ptr++; 3805 kbd_fetch_ptr++;
3680 } 3806 }
3681 input_pending = 0; 3807 input_pending = 0;
3682 #endif 3808 #endif
3683 #endif /* BSD and not BSD4_1 */ 3809 #endif /* BSD and not BSD4_1 */
3883 4009
3884 #ifdef MULTI_FRAME 4010 #ifdef MULTI_FRAME
3885 /* This means that command_loop_1 won't try to select anything the first 4011 /* This means that command_loop_1 won't try to select anything the first
3886 time through. */ 4012 time through. */
3887 Vlast_event_frame = Qnil; 4013 Vlast_event_frame = Qnil;
4014
4015 /* If we're running an undumped Emacs, kbd_buffer_frames isn't set
4016 yet. When it does get initialized, it will be filled with the
4017 right value, so it's okay not to fret about it here. */
4018 if (initialized)
4019 Ffillarray (kbd_buffer_frames, Qnil);
3888 #endif 4020 #endif
3889 4021
3890 if (!noninteractive) 4022 if (!noninteractive)
3891 { 4023 {
3892 signal (SIGINT, interrupt_signal); 4024 signal (SIGINT, interrupt_signal);
3935 Lisp_Object *kind; 4067 Lisp_Object *kind;
3936 }; 4068 };
3937 4069
3938 struct event_head head_table[] = { 4070 struct event_head head_table[] = {
3939 &Qmouse_movement, "mouse-movement", &Qmouse_movement, 4071 &Qmouse_movement, "mouse-movement", &Qmouse_movement,
3940 &Qvscrollbar_part, "vscrollbar-part", &Qscrollbar_click, 4072 &Qswitch_frame, "switch-frame", &Qswitch_frame,
3941 &Qvslider_part, "vslider-part", &Qscrollbar_click, 4073 &Qscrollbar_movement, "scrollbar-movement", &Qscrollbar_movement,
3942 &Qvthumbup_part, "vthumbup-part", &Qscrollbar_click,
3943 &Qvthumbdown_part, "vthumbdown-part", &Qscrollbar_click,
3944 &Qhscrollbar_part, "hscrollbar-part", &Qscrollbar_click,
3945 &Qhslider_part, "hslider-part", &Qscrollbar_click,
3946 &Qhthumbleft_part, "hthumbleft-part", &Qscrollbar_click,
3947 &Qhthumbright_part,"hthumbright-part", &Qscrollbar_click,
3948 &Qswitch_frame, "switch-frame", &Qswitch_frame
3949 }; 4074 };
3950 4075
3951 syms_of_keyboard () 4076 syms_of_keyboard ()
3952 { 4077 {
3953 Qself_insert_command = intern ("self-insert-command"); 4078 Qself_insert_command = intern ("self-insert-command");
3964 4089
3965 Qfunction_key = intern ("function-key"); 4090 Qfunction_key = intern ("function-key");
3966 staticpro (&Qfunction_key); 4091 staticpro (&Qfunction_key);
3967 Qmouse_click = intern ("mouse-click"); 4092 Qmouse_click = intern ("mouse-click");
3968 staticpro (&Qmouse_click); 4093 staticpro (&Qmouse_click);
3969 Qmouse_movement = intern ("scrollbar-click");
3970 staticpro (&Qmouse_movement);
3971 4094
3972 Qmode_line = intern ("mode-line"); 4095 Qmode_line = intern ("mode-line");
3973 staticpro (&Qmode_line); 4096 staticpro (&Qmode_line);
3974 Qvertical_line = intern ("vertical-line"); 4097 Qvertical_line = intern ("vertical-line");
3975 staticpro (&Qvertical_line); 4098 staticpro (&Qvertical_line);
4099 Qvertical_scrollbar = intern ("vertical-scrollbar");
4100 staticpro (&Qvertical_scrollbar);
4101
4102 Qabove_handle = intern ("above-handle");
4103 staticpro (&Qabove_handle);
4104 Qhandle = intern ("handle");
4105 staticpro (&Qhandle);
4106 Qbelow_handle = intern ("below-handle");
4107 staticpro (&Qbelow_handle);
3976 4108
3977 Qevent_kind = intern ("event-kind"); 4109 Qevent_kind = intern ("event-kind");
3978 staticpro (&Qevent_kind); 4110 staticpro (&Qevent_kind);
3979 Qevent_symbol_elements = intern ("event-symbol-elements"); 4111 Qevent_symbol_elements = intern ("event-symbol-elements");
3980 staticpro (&Qevent_symbol_elements); 4112 staticpro (&Qevent_symbol_elements);
4017 recent_keys = Fmake_vector (make_number (NUM_RECENT_KEYS), Qnil); 4149 recent_keys = Fmake_vector (make_number (NUM_RECENT_KEYS), Qnil);
4018 staticpro (&recent_keys); 4150 staticpro (&recent_keys);
4019 4151
4020 this_command_keys = Fmake_vector (make_number (40), Qnil); 4152 this_command_keys = Fmake_vector (make_number (40), Qnil);
4021 staticpro (&this_command_keys); 4153 staticpro (&this_command_keys);
4154
4155 #ifdef MULTI_FRAME
4156 kbd_buffer_frames = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
4157 staticpro (&kbd_buffer_frames);
4158 #endif
4022 4159
4023 func_key_syms = Qnil; 4160 func_key_syms = Qnil;
4024 staticpro (&func_key_syms); 4161 staticpro (&func_key_syms);
4025 4162
4026 mouse_syms = Qnil; 4163 mouse_syms = Qnil;