aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJim Blandy1993-01-14 15:11:19 +0000
committerJim Blandy1993-01-14 15:11:19 +0000
commit7b4aedb99a873adcac8f217868e175524d94d47e (patch)
treea4bdb1c100531803a2f8b14d762740463a2735c7 /src
parentfa61c7012f7c49b718341e92cdd864b184c5693d (diff)
downloademacs-7b4aedb99a873adcac8f217868e175524d94d47e.tar.gz
emacs-7b4aedb99a873adcac8f217868e175524d94d47e.zip
* termhooks.h (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return anything any more, and doesn't take a struct scrollbar * argument any more. (condemn_scrollbars_hook, redeem_scrollbar_hook, judge_scrollbars_hook): Doc fixes. * term.c (mouse_position_hook): Doc fix. (set_vertical_scrollbar_hook): This doesn't return anything any more. Doc fixes. * keyboard.c (kbd_buffer_get_event): Receive the scrollbar's window from *mouse_position_hook and pass it to make_lispy_movement, instead of working with a pointer to a struct scrollbar. (make_lispy_event): We don't need a window_from_scrollbar function anymore; we are given the window directly in *EVENT. Unify the code which generates text-area mouse clicks and scrollbar clicks; use the same code to distinguish clicks from drags on the scrollbar as in the text area. Distinguish clicks from drags by storing a copy of the lispy position list returned as part of the event. (button_down_location): Make this a lisp vector, rather than an array of random structures. (struct mouse_position): Remove this; it's been replaced by a lisp list. (make_lispy_movement): Accept the scrollbar's window as a parameter, rather than the scrollbar itself. If FRAME is zero, assume that the other arguments are garbage. (syms_of_keyboard): No need to staticpro each window of button_down_location now; just initialize and staticpro it. * window.c (window_from_scrollbar): Function deleted; no longer needed. * xdisp.c (redisplay_window): Just pass the window to set_vertical_scrollbar hook; don't pass the scrollbar object too. * xterm.c (XTmouse_position): Don't return a pointer to the scrollbar for scrollbar motion; instead, return the scrollbar's window. * keyboard.c (apply_modifiers): Don't assume that the Qevent_kind property of BASE is set when we first create the new modified symbol. Check that the Qevent_kind property is properly set each time we return any symbol. * termhooks.h (struct input_event): Replace the frame member with a Lisp_Object member by the name of frame_or_window. Doc fixes. Remove the scrollbar member; instead, use frame_or_window to hold the window whose scrollbar was clicked. * keyboard.c (kbd_buffer_store_event, kbd_buffer_get_event, make_lispy_event): Adjust references to frame member of struct input_event to use frame_or_window now. * xterm.c (construct_mouse_click, XTread_socket): Same. * keyboard.c (kbd_buffer_frames): Renamed to kbd_buffer_frame_or_window, and made to exist even when MULTI_FRAME isn't defined; single-frame systems might have scrollbars. Use it to GCPRO the frame_or_window field in the event queue. (kbd_buffer_store_event, kbd_buffer_get_event, stuff_buffered_input): Set and clear the appropriate element of kbd_buffer_frame_or_window, whether or not MULTI_FRAME is #defined. (read_avail_input): When reading characters directly from stdin, set the frame_or_window field of the event appropriately, depending on whether or not MULTI_FRAME is #defined. (Fdiscard_input, init_keyboard): Zap kbd_buffer_frame_or_window, not kbd_buffer_frames. (syms_of_keyboard): Initialize and staticpro kbd_buffer_frame_or_window, whether or not MULTI_FRAME is #defined. * keyboard.c (head_table): Make Qscrollbar_movement have a Qevent_kind property of Qmouse_movement, not Qscrollbar_movement. * keyboard.c (read_key_sequence): If we decide to throw away a mouse event which has prefix symbols (`mode-line', `vertical-scrollbar', etcetera), remember that we may have to unwind two characters, not just one. * keyboard.c (read_key_sequence): Doc fixes. * keyboard.c (kbd_buffer_store_event): Fix reversed sense of test for focus redirection. * keyboard.c (read_char): Don't echo mouse movements.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c464
1 files changed, 257 insertions, 207 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index a3817a94bd3..50e39fdabcf 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -1,11 +1,11 @@
1/* Keyboard and mouse input; editor command loop. 1/* Keyboard and mouse input; editor command loop.
2 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1992 Free Software Foundation, Inc. 2 Copyright (C) 1985, 1986, 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
3 3
4This file is part of GNU Emacs. 4This file is part of GNU Emacs.
5 5
6GNU Emacs is free software; you can redistribute it and/or modify 6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by 7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option) 8the Free Software Foundation; either version 2, or (at your option)
9any later version. 9any later version.
10 10
11GNU Emacs is distributed in the hope that it will be useful, 11GNU Emacs is distributed in the hope that it will be useful,
@@ -241,11 +241,10 @@ extern char *pending_malloc_warning;
241/* Circular buffer for pre-read keyboard input. */ 241/* Circular buffer for pre-read keyboard input. */
242static struct input_event kbd_buffer[KBD_BUFFER_SIZE]; 242static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
243 243
244#ifdef MULTI_FRAME 244/* Vector to GCPRO the frames and windows mentioned in kbd_buffer.
245/* Vector of frames, to GCPRO the frames mentioned in kbd_buffer.
246 245
247 The interrupt-level event handlers will never enqueue a frame which 246 The interrupt-level event handlers will never enqueue an event on a
248 is not in Vframe_list, and once an event is dequeued, 247 frame which is not in Vframe_list, and once an event is dequeued,
249 Vlast_event_frame or the event itself points to the frame. So 248 Vlast_event_frame or the event itself points to the frame. So
250 that's all fine. 249 that's all fine.
251 250
@@ -258,15 +257,17 @@ static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
258 have an event referring to a freed frame, which will crash Emacs 257 have an event referring to a freed frame, which will crash Emacs
259 when it is dequeued. 258 when it is dequeued.
260 259
261 So, we use this vector to protect any frames in the event queue. 260 Similar things happen when an event on a scrollbar is enqueued; the
262 That way, they'll be dequeued as dead frames, but still valid lisp 261 window may be deleted while the event is in the queue.
263 objects.
264 262
265 If kbd_buffer[i] != 0, then 263 So, we use this vector to protect the frame_or_window field in the
266 (XFRAME (XVECTOR (kbd_buffer_frames)->contents[i]) 264 event queue. That way, they'll be dequeued as dead frames or
267 == kbd_buffer[i].frame). */ 265 windows, but still valid lisp objects.
268static Lisp_Object kbd_buffer_frames; 266
269#endif 267 If kbd_buffer[i].kind != no_event, then
268 (XVECTOR (kbd_buffer_frame_or_window)->contents[i]
269 == kbd_buffer[i].frame_or_window. */
270static Lisp_Object kbd_buffer_frame_or_window;
270 271
271/* Pointer to next available character in kbd_buffer. 272/* Pointer to next available character in kbd_buffer.
272 If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty. 273 If kbd_fetch_ptr == kbd_store_ptr, the buffer is empty.
@@ -1373,13 +1374,15 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
1373 1374
1374 from_macro: 1375 from_macro:
1375 reread_first: 1376 reread_first:
1376 echo_char (c);
1377 1377
1378 /* Record this character as part of the current key. 1378 /* Record this character as part of the current key.
1379 Don't record mouse motion; it should never matter. */ 1379 Don't record mouse motion; it should never matter. */
1380 if (! (EVENT_HAS_PARAMETERS (c) 1380 if (! (EVENT_HAS_PARAMETERS (c)
1381 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement))) 1381 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
1382 add_command_key (c); 1382 {
1383 echo_char (c);
1384 add_command_key (c);
1385 }
1383 1386
1384 /* Re-reading in the middle of a command */ 1387 /* Re-reading in the middle of a command */
1385 reread: 1388 reread:
@@ -1527,12 +1530,13 @@ kbd_buffer_store_event (event)
1527 get returned to Emacs as an event, the next event read 1530 get returned to Emacs as an event, the next event read
1528 will set Vlast_event_frame again, so this is safe to do. */ 1531 will set Vlast_event_frame again, so this is safe to do. */
1529 { 1532 {
1530 Lisp_Object focus = FRAME_FOCUS_FRAME (event->frame); 1533 Lisp_Object focus =
1534 FRAME_FOCUS_FRAME (XFRAME (event->frame_or_window));
1531 1535
1532 if (NILP (focus)) 1536 if (NILP (focus))
1533 Vlast_event_frame = focus; 1537 Vlast_event_frame = event->frame_or_window;
1534 else 1538 else
1535 XSET (Vlast_event_frame, Lisp_Frame, event->frame); 1539 Vlast_event_frame = focus;
1536 } 1540 }
1537#endif 1541#endif
1538 1542
@@ -1562,16 +1566,14 @@ kbd_buffer_store_event (event)
1562 kbd_store_ptr->kind = event->kind; 1566 kbd_store_ptr->kind = event->kind;
1563 kbd_store_ptr->code = event->code; 1567 kbd_store_ptr->code = event->code;
1564 kbd_store_ptr->part = event->part; 1568 kbd_store_ptr->part = event->part;
1565 kbd_store_ptr->frame = event->frame; 1569 kbd_store_ptr->frame_or_window = event->frame_or_window;
1566 kbd_store_ptr->modifiers = event->modifiers; 1570 kbd_store_ptr->modifiers = event->modifiers;
1567 kbd_store_ptr->x = event->x; 1571 kbd_store_ptr->x = event->x;
1568 kbd_store_ptr->y = event->y; 1572 kbd_store_ptr->y = event->y;
1569 kbd_store_ptr->timestamp = event->timestamp; 1573 kbd_store_ptr->timestamp = event->timestamp;
1570#ifdef MULTI_FRAME 1574 (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_store_ptr
1571 XSET (XVECTOR (kbd_buffer_frames)->contents[kbd_store_ptr - kbd_buffer], 1575 - kbd_buffer]
1572 Lisp_Frame, 1576 = event->frame_or_window);
1573 event->frame);
1574#endif
1575 1577
1576 kbd_store_ptr++; 1578 kbd_store_ptr++;
1577 } 1579 }
@@ -1650,10 +1652,15 @@ kbd_buffer_get_event ()
1650 /* If this event is on a different frame, return a switch-frame this 1652 /* 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. */ 1653 time, and leave the event in the queue for next time. */
1652 { 1654 {
1653 Lisp_Object frame = FRAME_FOCUS_FRAME (event->frame); 1655 Lisp_Object frame = event->frame_or_window;
1656 Lisp_Object focus;
1657
1658 if (XTYPE (frame) == Lisp_Window)
1659 frame = WINDOW_FRAME (XWINDOW (frame));
1654 1660
1655 if (NILP (frame)) 1661 focus = FRAME_FOCUS_FRAME (XFRAME (frame));
1656 XSET (frame, Lisp_Frame, event->frame); 1662 if (! NILP (focus))
1663 frame = focus;
1657 1664
1658 if (! EQ (frame, Vlast_event_frame)) 1665 if (! EQ (frame, Vlast_event_frame))
1659 { 1666 {
@@ -1673,9 +1680,8 @@ kbd_buffer_get_event ()
1673 1680
1674 /* Wipe out this event, to catch bugs. */ 1681 /* Wipe out this event, to catch bugs. */
1675 event->kind = no_event; 1682 event->kind = no_event;
1676#ifdef MULTI_FRAME 1683 (XVECTOR (kbd_buffer_frame_or_window)->contents[event - kbd_buffer]
1677 XVECTOR (kbd_buffer_frames)->contents[event - kbd_buffer] = Qnil; 1684 = Qnil);
1678#endif
1679 1685
1680 kbd_fetch_ptr = event + 1; 1686 kbd_fetch_ptr = event + 1;
1681 } 1687 }
@@ -1683,12 +1689,12 @@ kbd_buffer_get_event ()
1683 else if (do_mouse_tracking && mouse_moved) 1689 else if (do_mouse_tracking && mouse_moved)
1684 { 1690 {
1685 FRAME_PTR f; 1691 FRAME_PTR f;
1686 struct scrollbar *bar; 1692 Lisp_Object bar_window;
1687 enum scrollbar_part part; 1693 enum scrollbar_part part;
1688 Lisp_Object x, y; 1694 Lisp_Object x, y;
1689 unsigned long time; 1695 unsigned long time;
1690 1696
1691 (*mouse_position_hook) (&f, &bar, &part, &x, &y, &time); 1697 (*mouse_position_hook) (&f, &bar_window, &part, &x, &y, &time);
1692 1698
1693 obj = Qnil; 1699 obj = Qnil;
1694 1700
@@ -1714,7 +1720,7 @@ kbd_buffer_get_event ()
1714 /* If we didn't decide to make a switch-frame event, go ahead and 1720 /* If we didn't decide to make a switch-frame event, go ahead and
1715 return a mouse-motion event. */ 1721 return a mouse-motion event. */
1716 if (NILP (obj)) 1722 if (NILP (obj))
1717 obj = make_lispy_movement (f, bar, part, x, y, time); 1723 obj = make_lispy_movement (f, bar_window, part, x, y, time);
1718 } 1724 }
1719 else 1725 else
1720 /* We were promised by the above while loop that there was 1726 /* We were promised by the above while loop that there was
@@ -1821,15 +1827,18 @@ Lisp_Object *scrollbar_parts[] = {
1821}; 1827};
1822 1828
1823 1829
1824/* make_lispy_event stores the down-going location of the currently 1830/* A vector, indexed by button number, giving the down-going location
1825 depressed buttons in button_down_locations. */ 1831 of currently depressed buttons, both scrollbar and non-scrollbar.
1826struct mouse_position { 1832
1827 Lisp_Object window; 1833 The elements have the form
1828 Lisp_Object buffer_pos; 1834 (BUTTON-NUMBER MODIFIER-MASK . REST)
1829 Lisp_Object x, y; 1835 where REST is the cdr of a position as it would be reported in the event.
1830 Lisp_Object timestamp; 1836
1831}; 1837 The make_lispy_event function stores positions here to tell the
1832static struct mouse_position button_down_location[NUM_MOUSE_BUTTONS]; 1838 difference between click and drag events, and to store the starting
1839 location to be included in drag events. */
1840
1841static Lisp_Object button_down_location;
1833 1842
1834/* Given a struct input_event, build the lisp event which represents 1843/* Given a struct input_event, build the lisp event which represents
1835 it. If EVENT is 0, build a mouse movement event from the mouse 1844 it. If EVENT is 0, build a mouse movement event from the mouse
@@ -1867,128 +1876,127 @@ make_lispy_event (event)
1867 /* A mouse click. Figure out where it is, decide whether it's 1876 /* A mouse click. Figure out where it is, decide whether it's
1868 a press, click or drag, and build the appropriate structure. */ 1877 a press, click or drag, and build the appropriate structure. */
1869 case mouse_click: 1878 case mouse_click:
1879 case scrollbar_click:
1870 { 1880 {
1871 int button = XFASTINT (event->code); 1881 int button = XFASTINT (event->code);
1872 int part; 1882 Lisp_Object position;
1873 Lisp_Object window; 1883 Lisp_Object *start_pos;
1874 Lisp_Object posn;
1875 struct mouse_position *loc;
1876 1884
1877 if (button < 0 || button >= NUM_MOUSE_BUTTONS) 1885 if (button < 0 || button >= NUM_MOUSE_BUTTONS)
1878 abort (); 1886 abort ();
1879 1887
1880 /* Where did this mouse click occur? */ 1888 /* Build the position as appropriate for this mouse click. */
1881 window = window_from_coordinates (event->frame, 1889 if (event->kind == mouse_click)
1882 XINT (event->x), XINT (event->y),
1883 &part);
1884 if (XTYPE (window) != Lisp_Window)
1885 posn = Qnil;
1886 else
1887 { 1890 {
1888 XSETINT (event->x, (XINT (event->x) 1891 int part;
1889 - XINT (XWINDOW (window)->left))); 1892 Lisp_Object window =
1890 XSETINT (event->y, (XINT (event->y) 1893 window_from_coordinates (XFRAME (event->frame_or_window),
1891 - XINT (XWINDOW (window)->top))); 1894 XINT (event->x), XINT (event->y),
1892 if (part == 1) 1895 &part);
1893 posn = Qmode_line; 1896 Lisp_Object posn;
1894 else if (part == 2) 1897
1895 posn = Qvertical_line; 1898 if (XTYPE (window) != Lisp_Window)
1899 posn = Qnil;
1896 else 1900 else
1897 XSET (posn, Lisp_Int, 1901 {
1898 buffer_posn_from_coords (XWINDOW (window), 1902 if (part == 1)
1899 XINT (event->x), 1903 posn = Qmode_line;
1900 XINT (event->y))); 1904 else if (part == 2)
1905 posn = Qvertical_line;
1906 else
1907 {
1908 XSETINT (event->x, (XINT (event->x)
1909 - XINT (XWINDOW (window)->left)));
1910 XSETINT (event->y, (XINT (event->y)
1911 - XINT (XWINDOW (window)->top)));
1912 XSET (posn, Lisp_Int,
1913 buffer_posn_from_coords (XWINDOW (window),
1914 XINT (event->x),
1915 XINT (event->y)));
1916 }
1917 }
1918
1919 position =
1920 Fcons (window,
1921 Fcons (posn,
1922 Fcons (Fcons (event->x, event->y),
1923 Fcons (make_number (event->timestamp),
1924 Qnil))));
1901 } 1925 }
1902 1926 else
1903 /* If this is a button press, squirrel away the location, so we
1904 can decide later whether it was a click or a drag. */
1905 loc = button_down_location + button;
1906 if (event->modifiers & down_modifier)
1907 { 1927 {
1908 loc->window = window; 1928 Lisp_Object window = event->frame_or_window;
1909 loc->buffer_pos = posn; 1929 Lisp_Object portion_whole = Fcons (event->x, event->y);
1910 loc->x = event->x; 1930 Lisp_Object part = *scrollbar_parts[(int) event->part];
1911 loc->y = event->y; 1931
1912 loc->timestamp = event->timestamp; 1932 position =
1933 Fcons (window,
1934 Fcons (Qvertical_scrollbar,
1935 Fcons (portion_whole,
1936 Fcons (make_number (event->timestamp),
1937 Fcons (part,
1938 Qnil)))));
1913 } 1939 }
1914 1940
1941 start_pos = &XVECTOR (button_down_location)->contents[button];
1942
1943 /* If this is a button press, squirrel away the location, so
1944 we can decide later whether it was a click or a drag. */
1945 if (event->modifiers & down_modifier)
1946 *start_pos = Fcopy_alist (position);
1947
1915 /* Now we're releasing a button - check the co-ordinates to 1948 /* Now we're releasing a button - check the co-ordinates to
1916 see if this was a click or a drag. */ 1949 see if this was a click or a drag. */
1917 else if (event->modifiers & up_modifier) 1950 else if (event->modifiers & up_modifier)
1918 { 1951 {
1952 Lisp_Object down = Fnth (make_number (2), *start_pos);
1953
1954 /* The third element of every position should be the (x,y)
1955 pair. */
1956 if (! CONSP (down))
1957 abort ();
1958
1919 event->modifiers &= ~up_modifier; 1959 event->modifiers &= ~up_modifier;
1920 event->modifiers |= ((EQ (event->x, loc->x) 1960 event->modifiers |= ((EQ (event->x, XCONS (down)->car)
1921 && EQ (event->y, loc->y)) 1961 && EQ (event->y, XCONS (down)->cdr))
1922 ? click_modifier 1962 ? click_modifier
1923 : drag_modifier); 1963 : drag_modifier);
1924 } 1964 }
1925 else 1965 else
1926 /* Every mouse event should either have the down_modifier or 1966 /* Every mouse event should either have the down_modifier or
1927 the up_modifier set. */ 1967 the up_modifier set. */
1928 abort (); 1968 abort ();
1929 1969
1930
1931 /* Build the event. */
1932 { 1970 {
1933 Lisp_Object head, start, end; 1971 /* Get the symbol we should use for the mouse click. */
1934 1972 Lisp_Object head =
1935 /* Build the components of the event. */ 1973 modify_event_symbol (button,
1936 head = modify_event_symbol (button, 1974 event->modifiers,
1937 event->modifiers, 1975 Qmouse_click,
1938 Qmouse_click, 1976 lispy_mouse_names, &mouse_syms,
1939 lispy_mouse_names, &mouse_syms, 1977 (sizeof (lispy_mouse_names)
1940 (sizeof (lispy_mouse_names) 1978 / sizeof (lispy_mouse_names[0])));
1941 / sizeof (lispy_mouse_names[0]))); 1979
1942 end = Fcons (window,
1943 Fcons (posn,
1944 Fcons (Fcons (event->x, event->y),
1945 Fcons (make_number (event->timestamp),
1946 Qnil))));
1947 if (event->modifiers & drag_modifier) 1980 if (event->modifiers & drag_modifier)
1948 start = Fcons (loc->window, 1981 {
1949 Fcons (loc->buffer_pos, 1982 Lisp_Object lispy_event =
1950 Fcons (Fcons (loc->x, loc->y), 1983 Fcons (head,
1951 Fcons (make_number (loc->timestamp), 1984 Fcons (*start_pos,
1952 Qnil)))); 1985 Fcons (position,
1986 Qnil)));
1987
1988 /* Allow this to be GC'd. */
1989 *start_pos = Qnil;
1953 1990
1954 /* Assemble the pieces. */ 1991 return lispy_event;
1955 if (event->modifiers & drag_modifier) 1992 }
1956 return Fcons (head,
1957 Fcons (start,
1958 Fcons (end,
1959 Qnil)));
1960 else 1993 else
1961 return Fcons (head, 1994 return Fcons (head,
1962 Fcons (end, 1995 Fcons (position,
1963 Qnil)); 1996 Qnil));
1964 } 1997 }
1965 } 1998 }
1966 1999
1967 /* A scrollbar click. Build a scrollbar click list. */
1968 case scrollbar_click:
1969 {
1970 Lisp_Object button =
1971 modify_event_symbol (button,
1972 event->modifiers,
1973 Qmouse_click,
1974 lispy_mouse_names, &mouse_syms,
1975 (sizeof (lispy_mouse_names)
1976 / sizeof (lispy_mouse_names[0])));
1977 Lisp_Object window =
1978 window_from_scrollbar (event->frame, event->scrollbar);
1979 Lisp_Object portion_whole = Fcons (event->x, event->y);
1980 Lisp_Object part = *scrollbar_parts[(int) event->part];
1981 Lisp_Object total_posn =
1982 Fcons (window,
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));
1990 }
1991
1992 /* The 'kind' field of the event is something we don't recognize. */ 2000 /* The 'kind' field of the event is something we don't recognize. */
1993 default: 2001 default:
1994 abort(); 2002 abort();
@@ -1996,21 +2004,20 @@ make_lispy_event (event)
1996} 2004}
1997 2005
1998static Lisp_Object 2006static Lisp_Object
1999make_lispy_movement (frame, bar, part, x, y, time) 2007make_lispy_movement (frame, bar_window, part, x, y, time)
2000 FRAME_PTR frame; 2008 FRAME_PTR frame;
2001 struct scrollbar *bar; 2009 Lisp_Object bar_window;
2002 enum scrollbar_part part; 2010 enum scrollbar_part part;
2003 Lisp_Object x, y; 2011 Lisp_Object x, y;
2004 unsigned long time; 2012 unsigned long time;
2005{ 2013{
2006 /* Is it a scrollbar movement? */ 2014 /* Is it a scrollbar movement? */
2007 if (bar) 2015 if (frame && ! NILP (bar_window))
2008 { 2016 {
2009 Lisp_Object window = window_from_scrollbar (frame, bar);
2010 Lisp_Object part = *scrollbar_parts[(int) part]; 2017 Lisp_Object part = *scrollbar_parts[(int) part];
2011 2018
2012 return Fcons (Qscrollbar_movement, 2019 return Fcons (Qscrollbar_movement,
2013 (Fcons (Fcons (window, 2020 (Fcons (Fcons (bar_window,
2014 Fcons (Qvertical_scrollbar, 2021 Fcons (Qvertical_scrollbar,
2015 Fcons (Fcons (x, y), 2022 Fcons (Fcons (x, y),
2016 Fcons (make_number (time), 2023 Fcons (make_number (time),
@@ -2304,7 +2311,7 @@ apply_modifiers (modifiers, base)
2304 int modifiers; 2311 int modifiers;
2305 Lisp_Object base; 2312 Lisp_Object base;
2306{ 2313{
2307 Lisp_Object cache, index, entry; 2314 Lisp_Object cache, index, entry, new_symbol;
2308 2315
2309 /* The click modifier never figures into cache indices. */ 2316 /* The click modifier never figures into cache indices. */
2310 cache = Fget (base, Qmodifier_cache); 2317 cache = Fget (base, Qmodifier_cache);
@@ -2312,31 +2319,42 @@ apply_modifiers (modifiers, base)
2312 entry = Fassq (index, cache); 2319 entry = Fassq (index, cache);
2313 2320
2314 if (CONSP (entry)) 2321 if (CONSP (entry))
2315 return XCONS (entry)->cdr; 2322 new_symbol = XCONS (entry)->cdr;
2323 else
2324 {
2325 /* We have to create the symbol ourselves. */
2326 new_symbol = apply_modifiers_uncached (modifiers,
2327 XSYMBOL (base)->name->data,
2328 XSYMBOL (base)->name->size);
2329
2330 /* Add the new symbol to the base's cache. */
2331 entry = Fcons (index, new_symbol);
2332 Fput (base, Qmodifier_cache, Fcons (entry, cache));
2333
2334 /* We have the parsing info now for free, so add it to the caches. */
2335 XFASTINT (index) = modifiers;
2336 Fput (new_symbol, Qevent_symbol_element_mask,
2337 Fcons (base, Fcons (index, Qnil)));
2338 Fput (new_symbol, Qevent_symbol_elements,
2339 Fcons (base, lispy_modifier_list (modifiers)));
2340 }
2316 2341
2317 /* We have to create the symbol ourselves. */ 2342 /* Make sure this symbol is of the same kind as BASE.
2318 { 2343
2319 Lisp_Object new_symbol 2344 You'd think we could just set this once and for all when we
2320 = apply_modifiers_uncached (modifiers, 2345 intern the symbol above, but reorder_modifiers may call us when
2321 XSYMBOL (base)->name->data, 2346 BASE's property isn't set right; we can't assume that just
2322 XSYMBOL (base)->name->size); 2347 because we found something in the cache it must have its kind set
2323 2348 right. */
2324 /* Add the new symbol to the base's cache. */ 2349 if (NILP (Fget (new_symbol, Qevent_kind)))
2325 Fput (base, Qmodifier_cache, 2350 {
2326 Fcons (Fcons (index, new_symbol), cache)); 2351 Lisp_Object kind = Fget (base, Qevent_kind);
2327 2352
2328 /* We have the parsing info now for free, so add it to the caches. */ 2353 if (! NILP (kind))
2329 XFASTINT (index) = modifiers; 2354 Fput (new_symbol, Qevent_kind, kind);
2330 Fput (new_symbol, Qevent_symbol_element_mask, 2355 }
2331 Fcons (base, Fcons (index, Qnil))); 2356
2332 Fput (new_symbol, Qevent_symbol_elements, 2357 return new_symbol;
2333 Fcons (base, lispy_modifier_list (modifiers)));
2334
2335 /* This symbol is of the same kind as BASE. */
2336 Fput (new_symbol, Qevent_kind, Fget (new_symbol, Qevent_kind));
2337
2338 return new_symbol;
2339 }
2340} 2358}
2341 2359
2342 2360
@@ -2573,8 +2591,12 @@ read_avail_input (expected)
2573 for (i = 0; i < nread; i++) 2591 for (i = 0; i < nread; i++)
2574 { 2592 {
2575 buf[i].kind = ascii_keystroke; 2593 buf[i].kind = ascii_keystroke;
2576 XSET (buf[i].code, Lisp_Int, cbuf[i]); 2594 XSET (buf[i].code, Lisp_Int, cbuf[i]);
2577 buf[i].frame = selected_frame; 2595#ifdef MULTI_FRAME
2596 XSET (buf[i].frame_or_window, Lisp_Frame, selected_frame);
2597#else
2598 buf[i].frame_or_window = Qnil;
2599#endif
2578 } 2600 }
2579 } 2601 }
2580 2602
@@ -3077,7 +3099,11 @@ read_key_sequence (keybuf, bufsize, prompt)
3077 echo_start = echo_length (); 3099 echo_start = echo_length ();
3078 keys_start = this_command_key_count; 3100 keys_start = this_command_key_count;
3079 3101
3102 /* We jump here when the key sequence has been thoroughly changed, and
3103 we need to rescan it starting from the beginning. When we jump here,
3104 keybuf[0..mock_input] holds the sequence we should reread. */
3080 replay_sequence: 3105 replay_sequence:
3106
3081 /* Build our list of keymaps. 3107 /* Build our list of keymaps.
3082 If we recognize a function key and replace its escape sequence in 3108 If we recognize a function key and replace its escape sequence in
3083 keybuf with its symbol, or if the sequence starts with a mouse 3109 keybuf with its symbol, or if the sequence starts with a mouse
@@ -3123,6 +3149,13 @@ read_key_sequence (keybuf, bufsize, prompt)
3123 Lisp_Object key; 3149 Lisp_Object key;
3124 int used_mouse_menu = 0; 3150 int used_mouse_menu = 0;
3125 3151
3152 /* Where the last real key started. If we need to throw away a
3153 key that has expanded into more than one element of keybuf
3154 (say, a mouse click on the mode line which is being treated
3155 as [mode-line (mouse-...)], then we backtrack to this point
3156 of keybuf. */
3157 int last_real_key_start;
3158
3126 /* These variables are analogous to echo_start and keys_start; 3159 /* These variables are analogous to echo_start and keys_start;
3127 while those allow us to restart the entire key sequence, 3160 while those allow us to restart the entire key sequence,
3128 echo_local_start and keys_local_start allow us to throw away 3161 echo_local_start and keys_local_start allow us to throw away
@@ -3158,6 +3191,8 @@ read_key_sequence (keybuf, bufsize, prompt)
3158 /* If not, we should actually read a character. */ 3191 /* If not, we should actually read a character. */
3159 else 3192 else
3160 { 3193 {
3194 last_real_key_start = t;
3195
3161 key = read_char (!prompt, nmaps, submaps, last_nonmenu_event, 3196 key = read_char (!prompt, nmaps, submaps, last_nonmenu_event,
3162 &used_mouse_menu); 3197 &used_mouse_menu);
3163 3198
@@ -3263,27 +3298,47 @@ read_key_sequence (keybuf, bufsize, prompt)
3263 /* We drop unbound `down-' events altogether. */ 3298 /* We drop unbound `down-' events altogether. */
3264 if (modifiers & down_modifier) 3299 if (modifiers & down_modifier)
3265 { 3300 {
3266 /* To make sure that mock_input doesn't just give 3301 /* Dispose of this event by simply jumping back to
3267 this event back to us; we want to delete this 3302 replay_key, to get another event.
3268 event from the mock input queue. We could delete 3303
3269 keybuf[t] and shift everything after that to the 3304 Note that if this event came from mock input,
3270 left by one spot, but we'd also have to fix up 3305 then just jumping back to replay_key will just
3271 any variable that points into keybuf, and shifting 3306 hand it to us again. So we have to wipe out any
3272 isn't really necessary anyway. 3307 mock input.
3273 3308
3274 Adding prefixes for non-textual mouse clicks creates 3309 We could delete keybuf[t] and shift everything
3275 two characters of mock input, and this must be the 3310 after that to the left by one spot, but we'd also
3276 second, so mock_input would be over anyway; it's okay 3311 have to fix up any variable that points into
3277 to zero it. 3312 keybuf, and shifting isn't really necessary
3278 3313 anyway.
3314
3315 Adding prefixes for non-textual mouse clicks
3316 creates two characters of mock input, and both
3317 must be thrown away. If we're only looking at
3318 the prefix now, we can just jump back to
3319 replay_key. On the other hand, if we've already
3320 processed the prefix, and now the actual click
3321 itself is giving us trouble, then we've lost the
3322 state of the keymaps we want to backtrack to, and
3323 we need to replay the whole sequence to rebuild
3324 it.
3325
3279 Beyond that, only function key expansion could 3326 Beyond that, only function key expansion could
3280 create more than two keys, but that should never 3327 create more than two keys, but that should never
3281 generate mouse events, so it's okay to zero 3328 generate mouse events, so it's okay to zero
3282 mock_input in that case too. 3329 mock_input in that case too.
3283 3330
3284 Isn't this just the most wonderful code ever? */ 3331 Isn't this just the most wonderful code ever? */
3285 mock_input = 0; 3332 if (t == last_real_key_start)
3286 goto replay_key; 3333 {
3334 mock_input = 0;
3335 goto replay_key;
3336 }
3337 else
3338 {
3339 mock_input = last_real_key_start;
3340 goto replay_sequence;
3341 }
3287 } 3342 }
3288 3343
3289 /* We turn unbound `drag-' events into `click-' 3344 /* We turn unbound `drag-' events into `click-'
@@ -3702,9 +3757,7 @@ Also cancel any kbd macro being defined.")
3702 volatile qualifier of kbd_store_ptr. Is there anything wrong 3757 volatile qualifier of kbd_store_ptr. Is there anything wrong
3703 with that? */ 3758 with that? */
3704 kbd_fetch_ptr = (struct input_event *) kbd_store_ptr; 3759 kbd_fetch_ptr = (struct input_event *) kbd_store_ptr;
3705#ifdef MULTI_FRAME 3760 Ffillarray (kbd_buffer_frame_or_window, Qnil);
3706 Ffillarray (kbd_buffer_frames, Qnil);
3707#endif
3708 input_pending = 0; 3761 input_pending = 0;
3709 3762
3710 return Qnil; 3763 return Qnil;
@@ -3798,10 +3851,9 @@ stuff_buffered_input (stuffstring)
3798 if (kbd_fetch_ptr->kind == ascii_keystroke) 3851 if (kbd_fetch_ptr->kind == ascii_keystroke)
3799 stuff_char (XINT (kbd_fetch_ptr->code)); 3852 stuff_char (XINT (kbd_fetch_ptr->code));
3800 kbd_fetch_ptr->kind = no_event; 3853 kbd_fetch_ptr->kind = no_event;
3801#ifdef MULTI_FRAME 3854 (XVECTOR (kbd_buffer_frame_or_window)->contents[kbd_fetch_ptr
3802 XVECTOR (kbd_buffer_frames)->contents[kbd_fetch_ptr - kbd_buffer] 3855 - kbd_buffer]
3803 = Qnil; 3856 = Qnil);
3804#endif
3805 kbd_fetch_ptr++; 3857 kbd_fetch_ptr++;
3806 } 3858 }
3807 input_pending = 0; 3859 input_pending = 0;
@@ -4011,13 +4063,16 @@ init_keyboard ()
4011 /* This means that command_loop_1 won't try to select anything the first 4063 /* This means that command_loop_1 won't try to select anything the first
4012 time through. */ 4064 time through. */
4013 Vlast_event_frame = Qnil; 4065 Vlast_event_frame = Qnil;
4066#endif
4067
4068 /* If we're running a dumped Emacs, we need to clear out
4069 kbd_buffer_frame_or_window, in case some events got into it
4070 before we dumped.
4014 4071
4015 /* If we're running an undumped Emacs, kbd_buffer_frames isn't set 4072 If we're running an undumped Emacs, it hasn't been initialized by
4016 yet. When it does get initialized, it will be filled with the 4073 syms_of_keyboard yet. */
4017 right value, so it's okay not to fret about it here. */
4018 if (initialized) 4074 if (initialized)
4019 Ffillarray (kbd_buffer_frames, Qnil); 4075 Ffillarray (kbd_buffer_frame_or_window, Qnil);
4020#endif
4021 4076
4022 if (!noninteractive) 4077 if (!noninteractive)
4023 { 4078 {
@@ -4068,9 +4123,9 @@ struct event_head {
4068}; 4123};
4069 4124
4070struct event_head head_table[] = { 4125struct event_head head_table[] = {
4071 &Qmouse_movement, "mouse-movement", &Qmouse_movement, 4126 &Qmouse_movement, "mouse-movement", &Qmouse_movement,
4072 &Qswitch_frame, "switch-frame", &Qswitch_frame, 4127 &Qscrollbar_movement, "scrollbar-movement", &Qmouse_movement,
4073 &Qscrollbar_movement, "scrollbar-movement", &Qscrollbar_movement, 4128 &Qswitch_frame, "switch-frame", &Qswitch_frame,
4074}; 4129};
4075 4130
4076syms_of_keyboard () 4131syms_of_keyboard ()
@@ -4129,12 +4184,8 @@ syms_of_keyboard ()
4129 } 4184 }
4130 } 4185 }
4131 4186
4132 { 4187 button_down_location = Fmake_vector (make_number (NUM_MOUSE_BUTTONS), Qnil);
4133 int i; 4188 staticpro (&button_down_location);
4134
4135 for (i = 0; i < NUM_MOUSE_BUTTONS; i++)
4136 staticpro (&button_down_location[i].window);
4137 }
4138 4189
4139 { 4190 {
4140 int i; 4191 int i;
@@ -4152,10 +4203,9 @@ syms_of_keyboard ()
4152 this_command_keys = Fmake_vector (make_number (40), Qnil); 4203 this_command_keys = Fmake_vector (make_number (40), Qnil);
4153 staticpro (&this_command_keys); 4204 staticpro (&this_command_keys);
4154 4205
4155#ifdef MULTI_FRAME 4206 kbd_buffer_frame_or_window
4156 kbd_buffer_frames = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil); 4207 = Fmake_vector (make_number (KBD_BUFFER_SIZE), Qnil);
4157 staticpro (&kbd_buffer_frames); 4208 staticpro (&kbd_buffer_frame_or_window);
4158#endif
4159 4209
4160 func_key_syms = Qnil; 4210 func_key_syms = Qnil;
4161 staticpro (&func_key_syms); 4211 staticpro (&func_key_syms);