diff options
| author | Jim Blandy | 1993-01-14 15:11:19 +0000 |
|---|---|---|
| committer | Jim Blandy | 1993-01-14 15:11:19 +0000 |
| commit | 7b4aedb99a873adcac8f217868e175524d94d47e (patch) | |
| tree | a4bdb1c100531803a2f8b14d762740463a2735c7 /src | |
| parent | fa61c7012f7c49b718341e92cdd864b184c5693d (diff) | |
| download | emacs-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.c | 464 |
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 | ||
| 4 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 5 | 5 | ||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | 6 | GNU Emacs is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 1, or (at your option) | 8 | the Free Software Foundation; either version 2, or (at your option) |
| 9 | any later version. | 9 | any later version. |
| 10 | 10 | ||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | 11 | GNU 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. */ |
| 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 | 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. |
| 268 | static 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. */ | ||
| 270 | static 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. |
| 1826 | struct 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 |
| 1832 | static 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 | |||
| 1841 | static 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 | ||
| 1998 | static Lisp_Object | 2006 | static Lisp_Object |
| 1999 | make_lispy_movement (frame, bar, part, x, y, time) | 2007 | make_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 | ||
| 4070 | struct event_head head_table[] = { | 4125 | struct 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 | ||
| 4076 | syms_of_keyboard () | 4131 | syms_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); |