/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-Lisp_Object Qmouse_wheel;
-#endif
#ifdef WINDOWSNT
Lisp_Object Qlanguage_change;
#endif
sp = kbd_buffer;
if (sp->kind == MOUSE_CLICK_EVENT
+ || sp->kind == WHEEL_EVENT
#ifdef WINDOWSNT
|| sp->kind == W32_SCROLL_BAR_CLICK_EVENT
#endif
static Lisp_Object accent_key_syms;
static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-static Lisp_Object mouse_wheel_syms;
-#endif
+static Lisp_Object wheel_syms;
static Lisp_Object drag_n_drop_syms;
/* This is a list of keysym codes for special "accent" characters.
Lisp_Object Vlispy_mouse_stem;
-#if defined(WINDOWSNT) || defined(MAC_OSX)
-/* mouse-wheel events are generated by the wheel on devices such as
- the MS Intellimouse. The wheel sits in between the left and right
- mouse buttons, and is typically used to scroll or zoom the window
- underneath the pointer. mouse-wheel events specify the object on
- which they operate, and a delta corresponding to the amount and
- direction that the wheel is rotated. Clicking the mouse-wheel
- generates a mouse-2 event. */
-static char *lispy_mouse_wheel_names[] =
-{
- "mouse-wheel"
+static char *lispy_wheel_names[] =
+{
+ "wheel-up", "wheel-down"
};
-#endif /* WINDOWSNT */
-
/* drag-n-drop events are generated when a set of selected files are
dragged from another application and dropped onto an Emacs window. */
static char *lispy_drag_n_drop_names[] =
case MULTIBYTE_CHAR_KEYSTROKE_EVENT:
{
Lisp_Object lispy_c;
+ int c = event->code;
- XSETFASTINT (lispy_c, event->code);
+ /* Add in the other modifier bits. We took care of ctrl_modifier
+ just above, and the shift key was taken care of by the X code,
+ and applied to control characters by make_ctrl_char. */
+ c |= (event->modifiers
+ & (meta_modifier | alt_modifier
+ | hyper_modifier | super_modifier | ctrl_modifier));
+ /* What about the `shift' modifier ? */
+ button_down_time = 0;
+ XSETFASTINT (lispy_c, c);
return lispy_c;
}
Lisp_Object posn;
Lisp_Object string_info = Qnil;
int row, column;
+ int wx, wy;
/* Ignore mouse events that were made on frame that
have been deleted. */
/* Set `window' to the window under frame pixel coordinates
event->x/event->y. */
window = window_from_coordinates (f, XINT (event->x),
- XINT (event->y), &part, 0);
+ XINT (event->y),
+ &part, &wx, &wy, 0);
if (!WINDOWP (window))
{
event->x/ event->y. */
struct window *w = XWINDOW (window);
- /* Get window relative coordinates. Original code
- `rounded' this to glyph boundaries. */
- int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
- int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
-
/* Set event coordinates to window-relative coordinates
for constructing the Lisp event below. */
XSETINT (event->x, wx);
}
}
+ case WHEEL_EVENT:
+ {
+ Lisp_Object position;
+ Lisp_Object window;
+ Lisp_Object head;
+
+ /* Build the position as appropriate for this mouse click. */
+ enum window_part part;
+ struct frame *f = XFRAME (event->frame_or_window);
+ Lisp_Object posn;
+ Lisp_Object string_info = Qnil;
+ int row, column;
+ int wx, wy;
+ position = Qnil;
+
+ /* Ignore wheel events that were made on frame that have been
+ deleted. */
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+
+ /* EVENT->x and EVENT->y are frame-relative pixel
+ coordinates at this place. Under old redisplay, COLUMN
+ and ROW are set to frame relative glyph coordinates
+ which are then used to determine whether this click is
+ in a menu (non-toolkit version). */
+ pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
+ &column, &row, NULL, 1);
+
+ /* Set `window' to the window under frame pixel coordinates
+ event->x/event->y. */
+ window = window_from_coordinates (f, XINT (event->x),
+ XINT (event->y),
+ &part, &wx, &wy, 0);
+
+ if (!WINDOWP (window))
+ {
+ window = event->frame_or_window;
+ posn = Qnil;
+ }
+ else
+ {
+ /* It's a click in window window at frame coordinates
+ event->x/ event->y. */
+ struct window *w = XWINDOW (window);
+
+ /* Set event coordinates to window-relative coordinates
+ for constructing the Lisp event below. */
+ XSETINT (event->x, wx);
+ XSETINT (event->y, wy);
+
+ if (part == ON_MODE_LINE || part == ON_HEADER_LINE)
+ {
+ /* Mode line or header line. Look for a string under
+ the mouse that may have a `local-map' property. */
+ Lisp_Object string;
+ int charpos;
+
+ posn = part == ON_MODE_LINE ? Qmode_line : Qheader_line;
+ string = mode_line_string (w, wx, wy, part, &charpos);
+ if (STRINGP (string))
+ string_info = Fcons (string, make_number (charpos));
+ }
+ else if (part == ON_VERTICAL_BORDER)
+ posn = Qvertical_line;
+ else if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
+ {
+ int charpos;
+ Lisp_Object object = marginal_area_string (w, wx, wy, part,
+ &charpos);
+ posn = (part == ON_LEFT_MARGIN) ? Qleft_margin : Qright_margin;
+ if (STRINGP (object))
+ string_info = Fcons (object, make_number (charpos));
+ }
+ else
+ {
+ Lisp_Object object;
+ struct display_pos p;
+ buffer_posn_from_coords (w, &wx, &wy, &object, &p);
+ posn = make_number (CHARPOS (p.pos));
+ if (STRINGP (object))
+ string_info
+ = Fcons (object,
+ make_number (CHARPOS (p.string_pos)));
+ }
+ }
+
+ position
+ = Fcons (window,
+ Fcons (posn,
+ Fcons (Fcons (event->x, event->y),
+ Fcons (make_number (event->timestamp),
+ (NILP (string_info)
+ ? Qnil
+ : Fcons (string_info, Qnil))))));
+
+ /* Set double or triple modifiers to indicate the wheel speed. */
+ {
+ /* On window-system frames, use the value of
+ double-click-fuzz as is. On other frames, interpret it
+ as a multiple of 1/8 characters. */
+ struct frame *f;
+ int fuzz;
+ int is_double;
+
+ if (WINDOWP (event->frame_or_window))
+ f = XFRAME (XWINDOW (event->frame_or_window)->frame);
+ else if (FRAMEP (event->frame_or_window))
+ f = XFRAME (event->frame_or_window);
+ else
+ abort ();
+
+ if (FRAME_WINDOW_P (f))
+ fuzz = double_click_fuzz;
+ else
+ fuzz = double_click_fuzz / 8;
+
+ is_double = (last_mouse_button < 0
+ && (abs (XINT (event->x) - last_mouse_x) <= fuzz)
+ && (abs (XINT (event->y) - last_mouse_y) <= fuzz)
+ && button_down_time != 0
+ && (EQ (Vdouble_click_time, Qt)
+ || (INTEGERP (Vdouble_click_time)
+ && ((int)(event->timestamp - button_down_time)
+ < XINT (Vdouble_click_time)))));
+ if (is_double)
+ {
+ double_click_count++;
+ event->modifiers |= ((double_click_count > 2)
+ ? triple_modifier
+ : double_modifier);
+ }
+ else
+ {
+ double_click_count = 1;
+ event->modifiers |= click_modifier;
+ }
+
+ button_down_time = event->timestamp;
+ /* Use a negative value to distinguish wheel from mouse button. */
+ last_mouse_button = -1;
+ last_mouse_x = XINT (event->x);
+ last_mouse_y = XINT (event->y);
+ }
+
+ {
+ int symbol_num;
+
+ if (event->modifiers & up_modifier)
+ {
+ /* Emit a wheel-up event. */
+ event->modifiers &= ~up_modifier;
+ symbol_num = 0;
+ }
+ else if (event->modifiers & down_modifier)
+ {
+ /* Emit a wheel-down event. */
+ event->modifiers &= ~down_modifier;
+ symbol_num = 1;
+ }
+ else
+ /* Every wheel event should either have the down_modifier or
+ the up_modifier set. */
+ abort ();
+
+ /* Get the symbol we should use for the wheel event. */
+ head = modify_event_symbol (symbol_num,
+ event->modifiers,
+ Qmouse_click,
+ Qnil,
+ lispy_wheel_names,
+ &wheel_syms,
+ ASIZE (wheel_syms));
+ }
+
+ if (event->modifiers & (double_modifier | triple_modifier))
+ return Fcons (head,
+ Fcons (position,
+ Fcons (make_number (double_click_count),
+ Qnil)));
+ else
+ return Fcons (head,
+ Fcons (position,
+ Qnil));
+ }
+
+
#ifdef USE_TOOLKIT_SCROLL_BARS
/* We don't have down and up events if using toolkit scroll bars,
}
}
#endif /* WINDOWSNT */
-#if defined(WINDOWSNT) || defined(MAC_OSX)
- case MOUSE_WHEEL_EVENT:
- {
- enum window_part part;
- FRAME_PTR f = XFRAME (event->frame_or_window);
- Lisp_Object window;
- Lisp_Object posn;
- Lisp_Object head, position;
- int row, column;
-
- /* Ignore mouse events that were made on frame that
- have been deleted. */
- if (! FRAME_LIVE_P (f))
- return Qnil;
- pixel_to_glyph_coords (f, XINT (event->x), XINT (event->y),
- &column, &row, NULL, 1);
- window = window_from_coordinates (f, XINT (event->x),
- XINT (event->y), &part, 0);
-
- if (!WINDOWP (window))
- {
- window = event->frame_or_window;
- posn = Qnil;
- }
- else
- {
- int pixcolumn, pixrow;
- column -= XINT (XWINDOW (window)->left);
- row -= XINT (XWINDOW (window)->top);
- glyph_to_pixel_coords (XWINDOW(window), column, row,
- &pixcolumn, &pixrow);
- XSETINT (event->x, pixcolumn);
- XSETINT (event->y, pixrow);
-
- if (part == ON_MODE_LINE)
- posn = Qmode_line;
- else if (part == ON_VERTICAL_BORDER)
- posn = Qvertical_line;
- else if (part == ON_HEADER_LINE)
- posn = Qheader_line;
- else
- {
- Lisp_Object object;
- struct display_pos p;
- buffer_posn_from_coords (XWINDOW (window), &column, &row,
- &object, &p);
- posn = make_number (CHARPOS (p.pos));
- }
- }
-
- {
- Lisp_Object head, position;
-
- position
- = Fcons (window,
- Fcons (posn,
- Fcons (Fcons (event->x, event->y),
- Fcons (make_number (event->timestamp),
- Qnil))));
-
- head = modify_event_symbol (0, event->modifiers,
- Qmouse_wheel, Qnil,
- lispy_mouse_wheel_names,
- &mouse_wheel_syms, 1);
- return Fcons (head,
- Fcons (position,
- /* Insert 1 here so event-click-count works. */
- Fcons (make_number (1),
- Fcons (make_number (event->code),
- Qnil))));
- }
- }
-#endif /* WINDOWSNT || MAC_OSX */
case DRAG_N_DROP_EVENT:
{
Lisp_Object window;
Lisp_Object posn;
Lisp_Object files;
+ int wx, wy;
/* The frame_or_window field should be a cons of the frame in
which the event occurred and a list of the filenames
return Qnil;
window = window_from_coordinates (f, XINT (event->x),
- XINT (event->y), &part, 0);
+ XINT (event->y),
+ &part, &wx, &wy, 0);
if (!WINDOWP (window))
{
event->x/ event->y. */
struct window *w = XWINDOW (window);
- /* Get window relative coordinates. */
- int wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (event->x));
- int wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (event->y));
-
/* Set event coordinates to window-relative coordinates
for constructing the Lisp event below. */
XSETINT (event->x, wx);
enum window_part area;
Lisp_Object window;
Lisp_Object posn;
+ int wx, wy;
if (frame)
/* It's in a frame; which window on that frame? */
- window = window_from_coordinates (frame, XINT (x), XINT (y), &area, 0);
+ window = window_from_coordinates (frame, XINT (x), XINT (y),
+ &area, &wx, &wy, 0);
else
window = Qnil;
if (WINDOWP (window))
{
struct window *w = XWINDOW (window);
- int wx, wy;
- /* Get window relative coordinates. */
- wx = FRAME_TO_WINDOW_PIXEL_X (w, XINT (x));
- wy = FRAME_TO_WINDOW_PIXEL_Y (w, XINT (y));
+ /* Set window relative coordinates. */
XSETINT (x, wx);
XSETINT (y, wy);
entry = Fcons (index, new_symbol);
Fput (base, Qmodifier_cache, Fcons (entry, cache));
- /* We have the parsing info now for free, so add it to the caches. */
- XSETFASTINT (index, modifiers);
- Fput (new_symbol, Qevent_symbol_element_mask,
- Fcons (base, Fcons (index, Qnil)));
- Fput (new_symbol, Qevent_symbol_elements,
- Fcons (base, lispy_modifier_list (modifiers)));
+ /* We have the parsing info now for free, so we could add it to
+ the caches:
+ XSETFASTINT (index, modifiers);
+ Fput (new_symbol, Qevent_symbol_element_mask,
+ Fcons (base, Fcons (index, Qnil)));
+ Fput (new_symbol, Qevent_symbol_elements,
+ Fcons (base, lispy_modifier_list (modifiers)));
+ Sadly, this is only correct if `base' is indeed a base event,
+ which is not necessarily the case. -stef */
}
/* Make sure this symbol is of the same kind as BASE.
{
struct input_event event;
Lisp_Object tem;
+ EVENT_INIT (event);
event.kind = BUFFER_SWITCH_EVENT;
event.frame_or_window = Qnil;
register int i;
int nread;
+ for (i = 0; i < KBD_BUFFER_SIZE; i++)
+ EVENT_INIT (buf[i]);
+
if (read_socket_hook)
/* No need for FIONREAD or fcntl; just say don't wait. */
nread = (*read_socket_hook) (input_fd, buf, KBD_BUFFER_SIZE, expected);
/* ??? Is it really right to send the signal just to this process
rather than to the whole process group?
Perhaps on systems with FIONREAD Emacs is alone in its group. */
- kill (getpid (), SIGHUP);
+ {
+ if (! noninteractive)
+ kill (getpid (), SIGHUP);
+ else
+ n_to_read = 0;
+ }
if (n_to_read == 0)
return 0;
if (n_to_read > sizeof cbuf)
register Lisp_Object name;
int nlength;
/* FIXME: Use the minibuffer's frame width. */
- int width = FRAME_WIDTH (SELECTED_FRAME ()) - 4;
+ int width = FRAME_COLS (SELECTED_FRAME ()) - 4;
int idx = -1;
int nobindings = 1;
Lisp_Object rest, vector;
such as Vfunction_key_map and Vkey_translation_map. */
typedef struct keyremap
{
- Lisp_Object map;
+ Lisp_Object map, parent;
int start, end;
} keyremap;
The return value is non-zero if the remapping actually took place. */
static int
-keyremap_step (keybuf, bufsize, fkey, input, doit, diff, parent, prompt)
- Lisp_Object *keybuf, prompt, parent;
+keyremap_step (keybuf, bufsize, fkey, input, doit, diff, prompt)
+ Lisp_Object *keybuf, prompt;
keyremap *fkey;
int input, doit, *diff, bufsize;
{
= Faref (next, make_number (i));
fkey->start = fkey->end += *diff;
- fkey->map = parent;
+ fkey->map = fkey->parent;
return 1;
}
if (!CONSP (fkey->map))
{
fkey->end = ++fkey->start;
- fkey->map = parent;
+ fkey->map = fkey->parent;
}
return 0;
}
last_nonmenu_event = Qnil;
delayed_switch_frame = Qnil;
- fkey.map = Vfunction_key_map;
- keytran.map = Vkey_translation_map;
+ fkey.map = fkey.parent = Vfunction_key_map;
+ keytran.map = keytran.parent = Vkey_translation_map;
/* If there is no translation-map, turn off scanning. */
fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
keybuf[i - first_unbound - 1] = keybuf[i];
mock_input = t - first_unbound - 1;
fkey.end = fkey.start -= first_unbound + 1;
- fkey.map = Vfunction_key_map;
+ fkey.map = fkey.parent;
keytran.end = keytran.start -= first_unbound + 1;
- keytran.map = Vkey_translation_map;
+ keytran.map = keytran.parent;
goto replay_sequence;
}
xterm-mouse-mode. -stef
Isn't this just the most wonderful code ever? */
+
+ /* If mock_input > t + 1, the above simplification
+ will actually end up dropping keys on the floor.
+ This is probably OK for now, but even
+ if mock_input <= t + 1, we need to adjust fkey
+ and keytran.
+ Typical case [header-line down-mouse-N]:
+ mock_input = 2, t = 1, fkey.end = 1,
+ last_real_key_start = 0. */
+ if (fkey.end > last_real_key_start)
+ {
+ fkey.end = fkey.start
+ = min (last_real_key_start, fkey.start);
+ fkey.map = fkey.parent;
+ if (keytran.end > last_real_key_start)
+ {
+ keytran.end = keytran.start
+ = min (last_real_key_start, keytran.start);
+ keytran.map = keytran.parent;
+ }
+ }
if (t == last_real_key_start)
{
mock_input = 0;
invariant that keytran.end <= fkey.start). */
{
if (fkey.start < t)
- (fkey.start = fkey.end = t, fkey.map = Vfunction_key_map);
+ (fkey.start = fkey.end = t, fkey.map = fkey.parent);
}
else
/* If the sequence is unbound, see if we can hang a function key
first_binding >= nmaps) we don't want
to apply this function-key-mapping. */
fkey.end + 1 == t && first_binding >= nmaps,
- &diff, Vfunction_key_map, prompt);
+ &diff, prompt);
UNGCPRO;
if (done)
{
GCPRO3 (fkey.map, keytran.map, delayed_switch_frame);
done = keyremap_step (keybuf, bufsize, &keytran, max (t, mock_input),
- 1, &diff, Vkey_translation_map, prompt);
+ 1, &diff, prompt);
UNGCPRO;
if (done)
{
keybuf[t - 1] = new_key;
mock_input = max (t, mock_input);
+ fkey.start = fkey.end = KEYMAPP (fkey.map) ? 0 : bufsize + 1;
+ keytran.start = keytran.end = KEYMAPP (keytran.map) ? 0 : bufsize + 1;
goto replay_sequence;
}
staticpro (&Qfunction_key);
Qmouse_click = intern ("mouse-click");
staticpro (&Qmouse_click);
-#if defined(WINDOWSNT) || defined(MAC_OSX)
- Qmouse_wheel = intern ("mouse-wheel");
- staticpro (&Qmouse_wheel);
-#endif
#ifdef WINDOWSNT
Qlanguage_change = intern ("language-change");
staticpro (&Qlanguage_change);
staticpro (&button_down_location);
mouse_syms = Fmake_vector (make_number (1), Qnil);
staticpro (&mouse_syms);
+ wheel_syms = Fmake_vector (make_number (2), Qnil);
+ staticpro (&wheel_syms);
{
int i;
func_key_syms = Qnil;
staticpro (&func_key_syms);
-#if defined(WINDOWSNT) || defined(MAC_OSX)
- mouse_wheel_syms = Qnil;
- staticpro (&mouse_wheel_syms);
drag_n_drop_syms = Qnil;
staticpro (&drag_n_drop_syms);
-#endif
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
initial_define_lispy_key (Vspecial_event_map, "save-session",
"handle-save-session");
}
+
+/* Mark the pointers in the kboard objects.
+ Called by the Fgarbage_collector. */
+void
+mark_kboards ()
+{
+ KBOARD *kb;
+ Lisp_Object *p;
+ for (kb = all_kboards; kb; kb = kb->next_kboard)
+ {
+ if (kb->kbd_macro_buffer)
+ for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
+ mark_object (*p);
+ mark_object (kb->Voverriding_terminal_local_map);
+ mark_object (kb->Vlast_command);
+ mark_object (kb->Vreal_last_command);
+ mark_object (kb->Vprefix_arg);
+ mark_object (kb->Vlast_prefix_arg);
+ mark_object (kb->kbd_queue);
+ mark_object (kb->defining_kbd_macro);
+ mark_object (kb->Vlast_kbd_macro);
+ mark_object (kb->Vsystem_key_alist);
+ mark_object (kb->system_key_syms);
+ mark_object (kb->Vdefault_minibuffer_frame);
+ mark_object (kb->echo_string);
+ }
+ {
+ struct input_event *event;
+ for (event = kbd_fetch_ptr; event != kbd_store_ptr; event++)
+ {
+ if (event == kbd_buffer + KBD_BUFFER_SIZE)
+ event = kbd_buffer;
+ mark_object (event->x);
+ mark_object (event->y);
+ mark_object (event->frame_or_window);
+ mark_object (event->arg);
+ }
+ }
+}