#endif
#endif
-#ifdef USE_LUCID
+#if defined (USE_LUCID) || defined (USE_MOTIF)
#include "../lwlib/xlwmenu.h"
#endif
#ifdef USE_TOOLKIT_SCROLL_BARS
#if defined USE_MOTIF
-#include <Xm/Xm.h> /* for LESSTIF_VERSION */
+#include <Xm/Xm.h> /* For LESSTIF_VERSION */
#include <Xm/ScrollBar.h>
#else /* !USE_MOTIF i.e. use Xaw */
struct x_display_info *x_display_list;
-/* This is a list of cons cells, each of the form (NAME
- . FONT-LIST-CACHE), one for each element of x_display_list and in
- the same order. NAME is the name of the frame. FONT-LIST-CACHE
- records previous values returned by x-list-fonts. */
-
-Lisp_Object x_display_name_list;
-
-/* This is a frame waiting to be auto-raised, within XTread_socket. */
-
-static struct frame *pending_autoraise_frame;
-
#ifdef USE_X_TOOLKIT
+
/* The application context for Xt use. */
XtAppContext Xt_app_con;
static String Xt_default_resources[] = {0};
/* Non-zero means user is interacting with a toolkit scroll bar. */
+static bool toolkit_scroll_bar_interaction;
-static int toolkit_scroll_bar_interaction;
#endif /* USE_X_TOOLKIT */
/* Non-zero timeout value means ignore next mouse click if it arrives
before that timeout elapses (i.e. as part of the same sequence of
events resulting from clicking on a frame to select it). */
-static unsigned long ignore_next_mouse_click_timeout;
-
-/* Mouse movement.
-
- Formerly, we used PointerMotionHintMask (in standard_event_mask)
- so that we would have to call XQueryPointer after each MotionNotify
- event to ask for another such event. However, this made mouse tracking
- slow, and there was a bug that made it eventually stop.
-
- Simply asking for MotionNotify all the time seems to work better.
-
- In order to avoid asking for motion events and then throwing most
- of them away or busy-polling the server for mouse positions, we ask
- the server for pointer motion hints. This means that we get only
- one event per group of mouse movements. "Groups" are delimited by
- other kinds of events (focus changes and button clicks, for
- example), or by XQueryPointer calls; when one of these happens, we
- get another MotionNotify event the next time the mouse moves. This
- is at least as efficient as getting motion events when mouse
- tracking is on, and I suspect only negligibly worse when tracking
- is off. */
-
-/* Where the mouse was last time we reported a mouse event. */
-
-static XRectangle last_mouse_glyph;
-static struct frame *last_mouse_glyph_frame;
-
-/* The scroll bar in which the last X motion event occurred.
-
- If the last X motion event occurred in a scroll bar, we set this so
- XTmouse_position can know whether to report a scroll bar motion or
- an ordinary motion.
-
- If the last X motion event didn't occur in a scroll bar, we set
- this to Qnil, to tell XTmouse_position to return an ordinary motion
- event. */
-
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack. We would really prefer that XTmouse_position would
- return the time associated with the position it returns, but there
- doesn't seem to be any way to wrest the time-stamp from the server
- along with the position query. So, we just keep track of the time
- of the last movement we received, and return that in hopes that
- it's somewhat accurate. */
-
-static Time last_mouse_movement_time;
+static Time ignore_next_mouse_click_timeout;
/* Incremented by XTread_socket whenever it really tries to read
events. */
};
static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, int, int, int);
+static void x_set_window_size_1 (struct frame *, int, int, int, bool);
static void x_raise_frame (struct frame *);
static void x_lower_frame (struct frame *);
static const XColor *x_color_cells (Display *, int *);
enum scroll_bar_part *,
Lisp_Object *, Lisp_Object *,
Time *);
-static int x_handle_net_wm_state (struct frame *, XPropertyEvent *);
+static int x_handle_net_wm_state (struct frame *, const XPropertyEvent *);
static void x_check_fullscreen (struct frame *);
static void x_check_expected_move (struct frame *, int, int);
static void x_sync_with_move (struct frame *, int, int, int);
-static int handle_one_xevent (struct x_display_info *, XEvent *,
- int *, struct input_event *);
+static int handle_one_xevent (struct x_display_info *,
+ const XEvent *, int *,
+ struct input_event *);
#ifdef USE_GTK
static int x_dispatch_event (XEvent *, Display *);
#endif
f->output_data.x->normal_gc, x, y0, x, y1);
}
+/* Draw a window divider from (x0,y0) to (x1,y1) */
+
+static void
+x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct face *face;
+
+ face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+ if (face)
+ XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+ face->foreground);
+
+ XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->normal_gc, x0, y0, x1 - x0, y1 - y0);
+}
+
/* End update of window W.
Draw vertical borders between horizontally adjacent windows, and
w->output_cursor.x, w->output_cursor.y);
if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+ }
unblock_input ();
}
if (sb_width > 0)
{
int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
+ int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
if (bx < 0)
{
get color reference counts right. */
unsigned long
-x_copy_color (struct frame *f, long unsigned int pixel)
+x_copy_color (struct frame *f, unsigned long pixel)
{
XColor color;
Value is non-zero if successful. */
static bool
-x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap, long unsigned int *pixel, double factor, int delta)
+x_alloc_lighter_color (struct frame *f, Display *display, Colormap cmap,
+ unsigned long *pixel, double factor, int delta)
{
XColor color, new;
long bright;
be allocated, use DEFAULT_PIXEL, instead. */
static void
-x_setup_relief_color (struct frame *f, struct relief *relief, double factor, int delta, long unsigned int default_pixel)
+x_setup_relief_color (struct frame *f, struct relief *relief, double factor,
+ int delta, unsigned long default_pixel)
{
XGCValues xgcv;
struct x_output *di = f->output_data.x;
/* Free previously allocated color. The color cell will be reused
when it has been freed as many times as it was allocated, so this
doesn't affect faces using the same colors. */
- if (relief->gc
- && relief->allocated_p)
+ if (relief->gc && relief->pixel != -1)
{
x_free_colors (f, &relief->pixel, 1);
- relief->allocated_p = 0;
+ relief->pixel = -1;
}
/* Allocate new color. */
pixel = background;
if (dpyinfo->n_planes != 1
&& x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
- {
- relief->allocated_p = 1;
- xgcv.foreground = relief->pixel = pixel;
- }
+ xgcv.foreground = relief->pixel = pixel;
if (relief->gc == 0)
{
if (sb_width > 0)
{
int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
- int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
- * FRAME_COLUMN_WIDTH (f));
+ int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
if (bar_area_x + bar_area_width == x)
{
x_lower_frame (old_focus);
if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->x_focus_frame;
+ dpyinfo->x_pending_autoraise_frame = dpyinfo->x_focus_frame;
else
- pending_autoraise_frame = 0;
+ dpyinfo->x_pending_autoraise_frame = NULL;
}
x_frame_rehighlight (dpyinfo);
/* Likewise, but consider only the menu bar widget. */
static struct frame *
-x_menubar_window_to_frame (struct x_display_info *dpyinfo, XEvent *event)
+x_menubar_window_to_frame (struct x_display_info *dpyinfo,
+ const XEvent *event)
{
Window wdesc = event->xany.window;
Lisp_Object tail, frame;
static void
x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame,
- XEvent *event, struct input_event *bufp)
+ const XEvent *event, struct input_event *bufp)
{
if (!frame)
return;
}
-#if defined HAVE_MENUS && !defined USE_X_TOOLKIT && !defined USE_GTK
+#if !defined USE_X_TOOLKIT && !defined USE_GTK
/* Handle an event saying the mouse has moved out of an Emacs frame. */
void
return value;
}
+/* Mouse clicks and mouse movement. Rah.
-\f
-/* Mouse clicks and mouse movement. Rah. */
+ Formerly, we used PointerMotionHintMask (in standard_event_mask)
+ so that we would have to call XQueryPointer after each MotionNotify
+ event to ask for another such event. However, this made mouse tracking
+ slow, and there was a bug that made it eventually stop.
+
+ Simply asking for MotionNotify all the time seems to work better.
+
+ In order to avoid asking for motion events and then throwing most
+ of them away or busy-polling the server for mouse positions, we ask
+ the server for pointer motion hints. This means that we get only
+ one event per group of mouse movements. "Groups" are delimited by
+ other kinds of events (focus changes and button clicks, for
+ example), or by XQueryPointer calls; when one of these happens, we
+ get another MotionNotify event the next time the mouse moves. This
+ is at least as efficient as getting motion events when mouse
+ tracking is on, and I suspect only negligibly worse when tracking
+ is off. */
/* Prepare a mouse-event in *RESULT for placement in the input queue.
the mouse. */
static Lisp_Object
-construct_mouse_click (struct input_event *result, XButtonEvent *event, struct frame *f)
+construct_mouse_click (struct input_event *result,
+ const XButtonEvent *event,
+ struct frame *f)
{
/* Make the event type NO_EVENT; we'll change that when we decide
otherwise. */
the mainstream emacs code by setting mouse_moved. If not, ask for
another motion event, so we can check again the next time it moves. */
-static XMotionEvent last_mouse_motion_event;
-static Lisp_Object last_mouse_motion_frame;
-
static int
-note_mouse_movement (struct frame *frame, XMotionEvent *event)
+note_mouse_movement (struct frame *frame, const XMotionEvent *event)
{
- last_mouse_movement_time = event->time;
- last_mouse_motion_event = *event;
- XSETFRAME (last_mouse_motion_frame, frame);
+ XRectangle *r;
+ struct x_display_info *dpyinfo;
if (!FRAME_X_OUTPUT (frame))
return 0;
+ dpyinfo = FRAME_DISPLAY_INFO (frame);
+ dpyinfo->last_mouse_movement_time = event->time;
+ dpyinfo->last_mouse_motion_frame = frame;
+ dpyinfo->last_mouse_motion_x = event->x;
+ dpyinfo->last_mouse_motion_y = event->y;
+
if (event->window != FRAME_X_WINDOW (frame))
{
frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
+ dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, -1, -1);
- last_mouse_glyph_frame = 0;
+ dpyinfo->last_mouse_glyph_frame = NULL;
return 1;
}
/* Has the mouse moved off the glyph it was on at the last sighting? */
- if (frame != last_mouse_glyph_frame
- || event->x < last_mouse_glyph.x
- || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
- || event->y < last_mouse_glyph.y
- || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
+ r = &dpyinfo->last_mouse_glyph;
+ if (frame != dpyinfo->last_mouse_glyph_frame
+ || event->x < r->x || event->x >= r->x + r->width
+ || event->y < r->y || event->y >= r->y + r->height)
{
frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
+ dpyinfo->last_mouse_scroll_bar = NULL;
note_mouse_highlight (frame, event->x, event->y);
/* Remember which glyph we're now on. */
- remember_mouse_glyph (frame, event->x, event->y, &last_mouse_glyph);
- last_mouse_glyph_frame = frame;
+ remember_mouse_glyph (frame, event->x, event->y, r);
+ dpyinfo->last_mouse_glyph_frame = frame;
return 1;
}
return 0;
}
-\f
-/************************************************************************
- Mouse Face
- ************************************************************************/
-
-static void
-redo_mouse_highlight (void)
-{
- if (!NILP (last_mouse_motion_frame)
- && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
- note_mouse_highlight (XFRAME (last_mouse_motion_frame),
- last_mouse_motion_event.x,
- last_mouse_motion_event.y);
-}
-
-
-
/* Return the current position of the mouse.
*FP should be a frame which indicates which display to ask about.
Time *timestamp)
{
struct frame *f1;
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
block_input ();
- if (! NILP (last_mouse_scroll_bar) && insist == 0)
+ if (dpyinfo->last_mouse_scroll_bar && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, timestamp);
else
{
&& FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
XFRAME (frame)->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
+ dpyinfo->last_mouse_scroll_bar = NULL;
/* Figure out which root window we're on. */
XQueryPointer (FRAME_X_DISPLAY (*fp),
x_catch_errors (FRAME_X_DISPLAY (*fp));
- if (FRAME_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
+ if (x_mouse_grabbed (dpyinfo))
{
/* If mouse was grabbed on a frame, give coords for that frame
even if the mouse is now outside it. */
XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
- /* From-window, to-window. */
- root, FRAME_X_WINDOW (last_mouse_frame),
+ /* From-window. */
+ root,
+
+ /* To-window. */
+ FRAME_X_WINDOW (dpyinfo->last_mouse_frame),
/* From-position, to-position. */
root_x, root_y, &win_x, &win_y,
/* Child of win. */
&child);
- f1 = last_mouse_frame;
+ f1 = dpyinfo->last_mouse_frame;
}
else
{
want the edit window. For non-Gtk+ the innermost
window is the edit window. For Gtk+ it might not
be. It might be the tool bar for example. */
- if (x_window_to_frame (FRAME_DISPLAY_INFO (*fp), win))
+ if (x_window_to_frame (dpyinfo, win))
break;
#endif
win = child;
#ifdef USE_GTK
/* We don't wan't to know the innermost window. We
want the edit window. */
- f1 = x_window_to_frame (FRAME_DISPLAY_INFO (*fp), win);
+ f1 = x_window_to_frame (dpyinfo, win);
#else
/* Is win one of our frames? */
- f1 = x_any_window_to_frame (FRAME_DISPLAY_INFO (*fp), win);
+ f1 = x_any_window_to_frame (dpyinfo, win);
#endif
#ifdef USE_X_TOOLKIT
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
- remember_mouse_glyph (f1, win_x, win_y, &last_mouse_glyph);
- last_mouse_glyph_frame = f1;
+ /* FIXME: what if F1 is not an X frame? */
+ dpyinfo = FRAME_DISPLAY_INFO (f1);
+ remember_mouse_glyph (f1, win_x, win_y, &dpyinfo->last_mouse_glyph);
+ dpyinfo->last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
*fp = f1;
XSETINT (*x, win_x);
XSETINT (*y, win_y);
- *timestamp = last_mouse_movement_time;
+ *timestamp = dpyinfo->last_mouse_movement_time;
}
}
}
#ifdef USE_TOOLKIT_SCROLL_BARS
-static void x_scroll_bar_to_input_event (XEvent *, struct input_event *);
static void x_send_scroll_bar_event (Lisp_Object, int, int, int);
-static void x_create_toolkit_scroll_bar (struct frame *,
- struct scroll_bar *);
-static void x_set_toolkit_scroll_bar_thumb (struct scroll_bar *,
- int, int, int);
-
/* Lisp window being scrolled. Set when starting to interact with
a toolkit scroll bar, reset to nil when ending the interaction. */
}
#endif /* not USE_GTK */
-/* A vector of windows used for communication between
- x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
-
-static struct window **scroll_bar_windows;
-static ptrdiff_t scroll_bar_windows_size;
-
-
/* Send a client message with message type Xatom_Scrollbar for a
scroll action to the frame of WINDOW. PART is a value identifying
the part of the scroll bar that was clicked on. PORTION is the
x_send_scroll_bar_event (Lisp_Object window, int part, int portion, int whole)
{
XEvent event;
- XClientMessageEvent *ev = (XClientMessageEvent *) &event;
+ XClientMessageEvent *ev = &event.xclient;
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
- ptrdiff_t i;
+ intptr_t iw = (intptr_t) w;
+ enum { BITS_PER_INTPTR = CHAR_BIT * sizeof iw };
+ verify (BITS_PER_INTPTR <= 64);
+ int sign_shift = BITS_PER_INTPTR - 32;
block_input ();
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
- /* We can only transfer 32 bits in the XClientMessageEvent, which is
- not enough to store a pointer or Lisp_Object on a 64 bit system.
- So, store the window in scroll_bar_windows and pass the index
- into that array in the event. */
- for (i = 0; i < scroll_bar_windows_size; ++i)
- if (scroll_bar_windows[i] == NULL)
- break;
-
- if (i == scroll_bar_windows_size)
- {
- ptrdiff_t old_nbytes =
- scroll_bar_windows_size * sizeof *scroll_bar_windows;
- ptrdiff_t nbytes;
- enum { XClientMessageEvent_MAX = 0x7fffffff };
- scroll_bar_windows =
- xpalloc (scroll_bar_windows, &scroll_bar_windows_size, 1,
- XClientMessageEvent_MAX, sizeof *scroll_bar_windows);
- nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
- memset (&scroll_bar_windows[i], 0, nbytes - old_nbytes);
- }
-
- scroll_bar_windows[i] = w;
- ev->data.l[0] = (long) i;
- ev->data.l[1] = (long) part;
- ev->data.l[2] = (long) 0;
- ev->data.l[3] = (long) portion;
- ev->data.l[4] = (long) whole;
+ /* A 32-bit X client on a 64-bit X server can pass a window pointer
+ as-is. A 64-bit client on a 32-bit X server is in trouble
+ because a pointer does not fit and would be truncated while
+ passing through the server. So use two slots and hope that X12
+ will resolve such issues someday. */
+ ev->data.l[0] = iw >> 31 >> 1;
+ ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
+ ev->data.l[2] = part;
+ ev->data.l[3] = portion;
+ ev->data.l[4] = whole;
/* Make Xt timeouts work while the scroll bar is active. */
#ifdef USE_X_TOOLKIT
in *IEVENT. */
static void
-x_scroll_bar_to_input_event (XEvent *event, struct input_event *ievent)
+x_scroll_bar_to_input_event (const XEvent *event,
+ struct input_event *ievent)
{
- XClientMessageEvent *ev = (XClientMessageEvent *) event;
+ const XClientMessageEvent *ev = &event->xclient;
Lisp_Object window;
struct window *w;
- w = scroll_bar_windows[ev->data.l[0]];
- scroll_bar_windows[ev->data.l[0]] = NULL;
+ /* See the comment in the function above. */
+ intptr_t iw0 = ev->data.l[0];
+ intptr_t iw1 = ev->data.l[1];
+ intptr_t iw = (iw0 << 31 << 1) + (iw1 & 0xffffffffu);
+ w = (struct window *) iw;
XSETWINDOW (window, w);
ievent->timestamp =
XtLastTimestampProcessed (FRAME_X_DISPLAY (XFRAME (w->frame)));
#endif
- ievent->part = ev->data.l[1];
- ievent->code = ev->data.l[2];
- ievent->x = make_number ((int) ev->data.l[3]);
- ievent->y = make_number ((int) ev->data.l[4]);
+ ievent->code = 0;
+ ievent->part = ev->data.l[2];
+ ievent->x = make_number (ev->data.l[3]);
+ ievent->y = make_number (ev->data.l[4]);
ievent->modifiers = 0;
}
/* Clear the area of W that will serve as a scroll bar. This is
for the case that a window has been split horizontally. In
this case, no clear_frame is generated to reduce flickering. */
- if (width > 0 && height > 0)
+ if (width > 0 && window_box_height (w) > 0)
x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
left, top, width, window_box_height (w));
/* Get window dimensions. */
window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
top = window_y;
- width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
+ width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
height = window_height;
/* Compute the left edge of the scroll bar area. */
unblock_input ();
}
- bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+ bar = x_scroll_bar_create (w, top, sb_left, sb_width, max (height, 1));
}
else
{
previous mode line display is cleared after C-x 2 C-x 1, for
example. */
{
- int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
+ int area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
int rest = area_width - sb_width;
if (rest > 0 && height > 0)
{
mark bits. */
static void
-x_scroll_bar_expose (struct scroll_bar *bar, XEvent *event)
+x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
{
Window w = bar->x_window;
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
static void
-x_scroll_bar_handle_click (struct scroll_bar *bar, XEvent *event, struct input_event *emacs_event)
+x_scroll_bar_handle_click (struct scroll_bar *bar,
+ const XEvent *event,
+ struct input_event *emacs_event)
{
if (! WINDOWP (bar->window))
emacs_abort ();
mark bits. */
static void
-x_scroll_bar_note_movement (struct scroll_bar *bar, XMotionEvent *event)
+x_scroll_bar_note_movement (struct scroll_bar *bar,
+ const XMotionEvent *event)
{
struct frame *f = XFRAME (XWINDOW (bar->window)->frame);
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
- last_mouse_movement_time = event->time;
-
+ dpyinfo->last_mouse_movement_time = event->time;
+ dpyinfo->last_mouse_scroll_bar = bar;
f->mouse_moved = 1;
- XSETVECTOR (last_mouse_scroll_bar, bar);
/* If we're dragging the bar, display it. */
if (bar->dragging != -1)
enum scroll_bar_part *part, Lisp_Object *x,
Lisp_Object *y, Time *timestamp)
{
- struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
+ struct scroll_bar *bar = dpyinfo->last_mouse_scroll_bar;
Window w = bar->x_window;
struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int win_x, win_y;
/* Get the mouse's position relative to the scroll bar window, and
report that. */
- if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
+ if (XQueryPointer (FRAME_X_DISPLAY (f), w,
- /* Root, child, root x and root y. */
- &dummy_window, &dummy_window,
- &dummy_coord, &dummy_coord,
+ /* Root, child, root x and root y. */
+ &dummy_window, &dummy_window,
+ &dummy_coord, &dummy_coord,
- /* Position relative to scroll bar. */
- &win_x, &win_y,
+ /* Position relative to scroll bar. */
+ &win_x, &win_y,
- /* Mouse buttons and modifier keys. */
- &dummy_mask))
- ;
- else
+ /* Mouse buttons and modifier keys. */
+ &dummy_mask))
{
- int top_range
- = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
XSETINT (*y, top_range);
f->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
+ dpyinfo->last_mouse_scroll_bar = NULL;
+ *timestamp = dpyinfo->last_mouse_movement_time;
}
- *timestamp = last_mouse_movement_time;
-
unblock_input ();
}
static struct x_display_info *next_noop_dpyinfo;
-#if defined USE_X_TOOLKIT || defined USE_GTK
-#define SET_SAVED_BUTTON_EVENT \
- do \
- { \
- if (f->output_data.x->saved_menu_event == 0) \
- f->output_data.x->saved_menu_event = \
- xmalloc (sizeof (XEvent)); \
- *f->output_data.x->saved_menu_event = event; \
- inev.ie.kind = MENU_BAR_ACTIVATE_EVENT; \
- XSETFRAME (inev.ie.frame_or_window, f); \
- } \
- while (0)
-#endif
-
enum
{
X_EVENT_NORMAL,
*FINISH is X_EVENT_GOTO_OUT if caller should stop reading events.
*FINISH is zero if caller should continue reading events.
*FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
+ *EVENT is unchanged unless we're processing KeyPress event.
- We return the number of characters stored into the buffer. */
+ We return the number of characters stored into the buffer. */
static int
-handle_one_xevent (struct x_display_info *dpyinfo, XEvent *eventptr,
+handle_one_xevent (struct x_display_info *dpyinfo,
+ const XEvent *event,
int *finish, struct input_event *hold_quit)
{
union {
ptrdiff_t nbytes = 0;
struct frame *any, *f = NULL;
struct coding_system coding;
- XEvent event = *eventptr;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
inev.ie.kind = NO_EVENT;
inev.ie.arg = Qnil;
- any = x_any_window_to_frame (dpyinfo, event.xany.window);
+ any = x_any_window_to_frame (dpyinfo, event->xany.window);
- if (any && any->wait_event_type == event.type)
+ if (any && any->wait_event_type == event->type)
any->wait_event_type = 0; /* Indicates we got it. */
- switch (event.type)
+ switch (event->type)
{
case ClientMessage:
{
- if (event.xclient.message_type
- == dpyinfo->Xatom_wm_protocols
- && event.xclient.format == 32)
+ if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
+ && event->xclient.format == 32)
{
- if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_take_focus)
+ if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_take_focus)
{
/* Use the value returned by x_any_window_to_frame
because this could be the shell widget window
since that might be an event for a deleted frame. */
if (f)
{
- Display *d = event.xclient.display;
+ Display *d = event->xclient.display;
/* Catch and ignore errors, in case window has been
iconified by a window manager such as GWM. */
x_catch_errors (d);
- XSetInputFocus (d, event.xclient.window,
+ XSetInputFocus (d, event->xclient.window,
/* The ICCCM says this is
the only valid choice. */
RevertToParent,
- event.xclient.data.l[1]);
+ event->xclient.data.l[1]);
/* This is needed to detect the error
if there is an error. */
XSync (d, False);
goto done;
}
- if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_save_yourself)
+ if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_save_yourself)
{
/* Save state modify the WM_COMMAND property to
something which can reinstate us. This notifies
#endif
{
f = x_top_window_to_frame (dpyinfo,
- event.xclient.window);
+ event->xclient.window);
/* This is just so we only give real data once
for a single Emacs process. */
if (f == SELECTED_FRAME ())
XSetCommand (FRAME_X_DISPLAY (f),
- event.xclient.window,
+ event->xclient.window,
initial_argv, initial_argc);
else if (f)
XSetCommand (FRAME_X_DISPLAY (f),
- event.xclient.window,
+ event->xclient.window,
0, 0);
}
goto done;
}
- if (event.xclient.data.l[0]
- == dpyinfo->Xatom_wm_delete_window)
+ if (event->xclient.data.l[0] == dpyinfo->Xatom_wm_delete_window)
{
f = any;
if (!f)
goto done;
}
- if (event.xclient.message_type
- == dpyinfo->Xatom_wm_configure_denied)
- {
- goto done;
- }
+ if (event->xclient.message_type == dpyinfo->Xatom_wm_configure_denied)
+ goto done;
- if (event.xclient.message_type
- == dpyinfo->Xatom_wm_window_moved)
+ if (event->xclient.message_type == dpyinfo->Xatom_wm_window_moved)
{
int new_x, new_y;
- f = x_window_to_frame (dpyinfo, event.xclient.window);
+ f = x_window_to_frame (dpyinfo, event->xclient.window);
- new_x = event.xclient.data.s[0];
- new_y = event.xclient.data.s[1];
+ new_x = event->xclient.data.s[0];
+ new_y = event->xclient.data.s[1];
if (f)
{
}
#ifdef HACK_EDITRES
- if (event.xclient.message_type
- == dpyinfo->Xatom_editres)
+ if (event->xclient.message_type == dpyinfo->Xatom_editres)
{
f = any;
if (f)
- _XEditResCheckMessages (f->output_data.x->widget, NULL,
- &event, NULL);
+ _XEditResCheckMessages (f->output_data.x->widget,
+ NULL, (XEvent *) event, NULL);
goto done;
}
#endif /* HACK_EDITRES */
- if ((event.xclient.message_type
- == dpyinfo->Xatom_DONE)
- || (event.xclient.message_type
- == dpyinfo->Xatom_PAGE))
+ if (event->xclient.message_type == dpyinfo->Xatom_DONE
+ || event->xclient.message_type == dpyinfo->Xatom_PAGE)
{
/* Ghostview job completed. Kill it. We could
reply with "Next" if we received "Page", but we
currently never do because we are interested in
images, only, which should have 1 page. */
- Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
- f = x_window_to_frame (dpyinfo, event.xclient.window);
+ Pixmap pixmap = (Pixmap) event->xclient.data.l[1];
+ f = x_window_to_frame (dpyinfo, event->xclient.window);
if (!f)
goto OTHER;
x_kill_gs_process (pixmap, f);
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Scroll bar callbacks send a ClientMessage from which
we construct an input_event. */
- if (event.xclient.message_type
- == dpyinfo->Xatom_Scrollbar)
+ if (event->xclient.message_type == dpyinfo->Xatom_Scrollbar)
{
- x_scroll_bar_to_input_event (&event, &inev.ie);
+ x_scroll_bar_to_input_event (event, &inev.ie);
*finish = X_EVENT_GOTO_OUT;
goto done;
}
#endif /* USE_TOOLKIT_SCROLL_BARS */
/* XEmbed messages from the embedder (if any). */
- if (event.xclient.message_type
- == dpyinfo->Xatom_XEMBED)
+ if (event->xclient.message_type == dpyinfo->Xatom_XEMBED)
{
- enum xembed_message msg = event.xclient.data.l[1];
+ enum xembed_message msg = event->xclient.data.l[1];
if (msg == XEMBED_FOCUS_IN || msg == XEMBED_FOCUS_OUT)
- x_detect_focus_change (dpyinfo, any, &event, &inev.ie);
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
*finish = X_EVENT_GOTO_OUT;
goto done;
}
- xft_settings_event (dpyinfo, &event);
+ xft_settings_event (dpyinfo, event);
f = any;
if (!f)
goto OTHER;
- if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev.ie))
+ if (x_handle_dnd_message (f, &event->xclient, dpyinfo, &inev.ie))
*finish = X_EVENT_DROP;
}
break;
case SelectionNotify:
- dpyinfo->last_user_time = event.xselection.time;
+ dpyinfo->last_user_time = event->xselection.time;
#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
+ if (! x_window_to_frame (dpyinfo, event->xselection.requestor))
goto OTHER;
#endif /* not USE_X_TOOLKIT */
- x_handle_selection_notify (&event.xselection);
+ x_handle_selection_notify (&event->xselection);
break;
case SelectionClear: /* Someone has grabbed ownership. */
- dpyinfo->last_user_time = event.xselectionclear.time;
+ dpyinfo->last_user_time = event->xselectionclear.time;
#ifdef USE_X_TOOLKIT
- if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
+ if (! x_window_to_frame (dpyinfo, event->xselectionclear.window))
goto OTHER;
#endif /* USE_X_TOOLKIT */
{
- XSelectionClearEvent *eventp = &(event.xselectionclear);
+ const XSelectionClearEvent *eventp = &event->xselectionclear;
inev.ie.kind = SELECTION_CLEAR_EVENT;
SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
break;
case SelectionRequest: /* Someone wants our selection. */
- dpyinfo->last_user_time = event.xselectionrequest.time;
+ dpyinfo->last_user_time = event->xselectionrequest.time;
#ifdef USE_X_TOOLKIT
- if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
+ if (!x_window_to_frame (dpyinfo, event->xselectionrequest.owner))
goto OTHER;
#endif /* USE_X_TOOLKIT */
{
- XSelectionRequestEvent *eventp = &(event.xselectionrequest);
-
- inev.ie.kind = SELECTION_REQUEST_EVENT;
- SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
- SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
- SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
- SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
- SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
- SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
+ const XSelectionRequestEvent *eventp = &event->xselectionrequest;
+
+ inev.ie.kind = SELECTION_REQUEST_EVENT;
+ SELECTION_EVENT_DISPLAY (&inev.sie) = eventp->display;
+ SELECTION_EVENT_REQUESTOR (&inev.sie) = eventp->requestor;
+ SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
+ SELECTION_EVENT_TARGET (&inev.sie) = eventp->target;
+ SELECTION_EVENT_PROPERTY (&inev.sie) = eventp->property;
+ SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
}
break;
case PropertyNotify:
- dpyinfo->last_user_time = event.xproperty.time;
- f = x_top_window_to_frame (dpyinfo, event.xproperty.window);
- if (f && event.xproperty.atom == dpyinfo->Xatom_net_wm_state)
- if (x_handle_net_wm_state (f, &event.xproperty)
+ dpyinfo->last_user_time = event->xproperty.time;
+ f = x_top_window_to_frame (dpyinfo, event->xproperty.window);
+ if (f && event->xproperty.atom == dpyinfo->Xatom_net_wm_state)
+ if (x_handle_net_wm_state (f, &event->xproperty)
&& FRAME_ICONIFIED_P (f)
&& f->output_data.x->net_wm_state_hidden_seen)
{
XSETFRAME (inev.ie.frame_or_window, f);
}
- x_handle_property_notify (&event.xproperty);
- xft_settings_event (dpyinfo, &event);
+ x_handle_property_notify (&event->xproperty);
+ xft_settings_event (dpyinfo, event);
goto OTHER;
case ReparentNotify:
- f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
+ f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
if (f)
{
- int x, y;
- f->output_data.x->parent_desc = event.xreparent.parent;
- x_real_positions (f, &x, &y);
- f->left_pos = x;
- f->top_pos = y;
+ f->output_data.x->parent_desc = event->xreparent.parent;
+ x_real_positions (f, &f->left_pos, &f->top_pos);
/* Perhaps reparented due to a WM restart. Reset this. */
FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
goto OTHER;
case Expose:
- f = x_window_to_frame (dpyinfo, event.xexpose.window);
+ f = x_window_to_frame (dpyinfo, event->xexpose.window);
if (f)
{
-#ifdef USE_GTK
- /* This seems to be needed for GTK 2.6. */
- x_clear_area (event.xexpose.display,
- event.xexpose.window,
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
-#endif
if (!FRAME_VISIBLE_P (f))
{
SET_FRAME_VISIBLE (f, 1);
SET_FRAME_GARBAGED (f);
}
else
- expose_frame (f,
- event.xexpose.x, event.xexpose.y,
- event.xexpose.width, event.xexpose.height);
+ {
+#ifdef USE_GTK
+ /* This seems to be needed for GTK 2.6 and later, see
+ http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
+ x_clear_area (event->xexpose.display,
+ event->xexpose.window,
+ event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+#endif
+ expose_frame (f, event->xexpose.x, event->xexpose.y,
+ event->xexpose.width, event->xexpose.height);
+ }
}
else
{
themselves, so there's no way to dispatch events
to them. Recognize this case separately. */
{
- Widget widget
- = x_window_to_menu_bar (event.xexpose.window);
+ Widget widget = x_window_to_menu_bar (event->xexpose.window);
if (widget)
xlwmenu_redisplay (widget);
}
/* Dispatch event to the widget. */
goto OTHER;
#else /* not USE_TOOLKIT_SCROLL_BARS */
- bar = x_window_to_scroll_bar (event.xexpose.display,
- event.xexpose.window);
+ bar = x_window_to_scroll_bar (event->xexpose.display,
+ event->xexpose.window);
if (bar)
- x_scroll_bar_expose (bar, &event);
+ x_scroll_bar_expose (bar, event);
#ifdef USE_X_TOOLKIT
else
goto OTHER;
case GraphicsExpose: /* This occurs when an XCopyArea's
source area was obscured or not
available. */
- f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
+ f = x_window_to_frame (dpyinfo, event->xgraphicsexpose.drawable);
if (f)
- {
- expose_frame (f,
- event.xgraphicsexpose.x, event.xgraphicsexpose.y,
- event.xgraphicsexpose.width,
- event.xgraphicsexpose.height);
- }
+ expose_frame (f, event->xgraphicsexpose.x,
+ event->xgraphicsexpose.y,
+ event->xgraphicsexpose.width,
+ event->xgraphicsexpose.height);
#ifdef USE_X_TOOLKIT
else
goto OTHER;
case UnmapNotify:
/* Redo the mouse-highlight after the tooltip has gone. */
- if (event.xunmap.window == tip_window)
+ if (event->xunmap.window == tip_window)
{
tip_window = 0;
- redo_mouse_highlight ();
+ x_redo_mouse_highlight (dpyinfo);
}
- f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
+ f = x_top_window_to_frame (dpyinfo, event->xunmap.window);
if (f) /* F may no longer exist if
the frame was deleted. */
{
goto OTHER;
case MapNotify:
- if (event.xmap.window == tip_window)
+ if (event->xmap.window == tip_window)
/* The tooltip has been drawn already. Avoid
the SET_FRAME_GARBAGED below. */
goto OTHER;
/* We use x_top_window_to_frame because map events can
come for sub-windows and they don't mean that the
frame is visible. */
- f = x_top_window_to_frame (dpyinfo, event.xmap.window);
+ f = x_top_window_to_frame (dpyinfo, event->xmap.window);
if (f)
{
bool iconified = FRAME_ICONIFIED_P (f);
SET_FRAME_GARBAGED (f);
/* Check if fullscreen was specified before we where mapped the
- first time, i.e. from the command line. */
+ first time, i.e. from the command line. */
if (!f->output_data.x->has_been_visible)
x_check_fullscreen (f);
case KeyPress:
- dpyinfo->last_user_time = event.xkey.time;
+ dpyinfo->last_user_time = event->xkey.time;
ignore_next_mouse_click_timeout = 0;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Scroll bars consume key events, but we want
the keys to go to the scroll bar's frame. */
Widget widget = XtWindowToWidget (dpyinfo->display,
- event.xkey.window);
+ event->xkey.window);
if (widget && XmIsScrollBar (widget))
{
widget = XtParent (widget);
int modifiers;
Lisp_Object coding_system = Qlatin_1;
Lisp_Object c;
+ /* Event will be modified. */
+ XKeyEvent xkey = event->xkey;
#ifdef USE_GTK
/* Don't pass keys to GTK. A Tab will shift focus to the
*finish = X_EVENT_DROP;
#endif
- event.xkey.state
- |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f),
- extra_keyboard_modifiers);
- modifiers = event.xkey.state;
+ xkey.state |= x_emacs_to_x_modifiers (FRAME_DISPLAY_INFO (f),
+ extra_keyboard_modifiers);
+ modifiers = xkey.state;
/* This will have to go some day... */
/* make_lispy_event turns chars into control chars.
Don't do it here because XLookupString is too eager. */
- event.xkey.state &= ~ControlMask;
- event.xkey.state &= ~(dpyinfo->meta_mod_mask
- | dpyinfo->super_mod_mask
- | dpyinfo->hyper_mod_mask
- | dpyinfo->alt_mod_mask);
+ xkey.state &= ~ControlMask;
+ xkey.state &= ~(dpyinfo->meta_mod_mask
+ | dpyinfo->super_mod_mask
+ | dpyinfo->hyper_mod_mask
+ | dpyinfo->alt_mod_mask);
/* In case Meta is ComposeCharacter,
clear its status. According to Markus Ehrnsperger
coding_system = Vlocale_coding_system;
nbytes = XmbLookupString (FRAME_XIC (f),
- &event.xkey, (char *) copy_bufptr,
+ &xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&status_return);
if (status_return == XBufferOverflow)
copy_bufsiz = nbytes + 1;
copy_bufptr = alloca (copy_bufsiz);
nbytes = XmbLookupString (FRAME_XIC (f),
- &event.xkey, (char *) copy_bufptr,
+ &xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&status_return);
}
emacs_abort ();
}
else
- nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
+ nbytes = XLookupString (&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&compose_status);
#else
- nbytes = XLookupString (&event.xkey, (char *) copy_bufptr,
+ nbytes = XLookupString (&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
&compose_status);
#endif
XSETFRAME (inev.ie.frame_or_window, f);
inev.ie.modifiers
= x_x_to_emacs_modifiers (FRAME_DISPLAY_INFO (f), modifiers);
- inev.ie.timestamp = event.xkey.time;
+ inev.ie.timestamp = xkey.time;
/* First deal with keysyms which have defined
translations to characters. */
if (keysym == NoSymbol)
break;
}
+ /* FIXME: check side effects and remove this. */
+ ((XEvent *) event)->xkey = xkey;
}
done_keysym:
#ifdef HAVE_X_I18N
#endif
case KeyRelease:
- dpyinfo->last_user_time = event.xkey.time;
+ dpyinfo->last_user_time = event->xkey.time;
#ifdef HAVE_X_I18N
/* Don't dispatch this event since XtDispatchEvent calls
XFilterEvent, and two calls in a row may freeze the
#endif
case EnterNotify:
- dpyinfo->last_user_time = event.xcrossing.time;
- x_detect_focus_change (dpyinfo, any, &event, &inev.ie);
+ dpyinfo->last_user_time = event->xcrossing.time;
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
f = any;
if (f && x_mouse_click_focus_ignore_position)
- ignore_next_mouse_click_timeout = event.xmotion.time + 200;
+ ignore_next_mouse_click_timeout = event->xmotion.time + 200;
/* EnterNotify counts as mouse movement,
so update things that depend on mouse position. */
if (f && !f->output_data.x->hourglass_p)
- note_mouse_movement (f, &event.xmotion);
+ note_mouse_movement (f, &event->xmotion);
#ifdef USE_GTK
/* We may get an EnterNotify on the buttons in the toolbar. In that
case we moved out of any highlighted area and need to note this. */
- if (!f && last_mouse_glyph_frame)
- note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
+ if (!f && dpyinfo->last_mouse_glyph_frame)
+ note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
#endif
goto OTHER;
case FocusIn:
- x_detect_focus_change (dpyinfo, any, &event, &inev.ie);
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
goto OTHER;
case LeaveNotify:
- dpyinfo->last_user_time = event.xcrossing.time;
- x_detect_focus_change (dpyinfo, any, &event, &inev.ie);
+ dpyinfo->last_user_time = event->xcrossing.time;
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
- f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
+ f = x_top_window_to_frame (dpyinfo, event->xcrossing.window);
if (f)
{
if (f == hlinfo->mouse_face_mouse_frame)
}
#ifdef USE_GTK
/* See comment in EnterNotify above */
- else if (last_mouse_glyph_frame)
- note_mouse_movement (last_mouse_glyph_frame, &event.xmotion);
+ else if (dpyinfo->last_mouse_glyph_frame)
+ note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &event->xmotion);
#endif
goto OTHER;
case FocusOut:
- x_detect_focus_change (dpyinfo, any, &event, &inev.ie);
+ x_detect_focus_change (dpyinfo, any, event, &inev.ie);
goto OTHER;
case MotionNotify:
{
- dpyinfo->last_user_time = event.xmotion.time;
+ dpyinfo->last_user_time = event->xmotion.time;
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
- if (dpyinfo->grabbed && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, event.xmotion.window);
+ f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
+ : x_window_to_frame (dpyinfo, event->xmotion.window));
if (hlinfo->mouse_face_hidden)
{
}
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, &event))
+ if (f && xg_event_is_for_scrollbar (f, event))
f = 0;
#endif
if (f)
{
static Lisp_Object last_mouse_window;
Lisp_Object window = window_from_coordinates
- (f, event.xmotion.x, event.xmotion.y, 0, 0);
+ (f, event->xmotion.x, event->xmotion.y, 0, 0);
/* Window will be selected only when it is not selected now and
last mouse movement event was not in it. Minibuffer window
/* Remember the last window where we saw the mouse. */
last_mouse_window = window;
}
- if (!note_mouse_movement (f, &event.xmotion))
+ if (!note_mouse_movement (f, &event->xmotion))
help_echo_string = previous_help_echo_string;
}
else
{
#ifndef USE_TOOLKIT_SCROLL_BARS
struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xmotion.display,
- event.xmotion.window);
+ = x_window_to_scroll_bar (event->xmotion.display,
+ event->xmotion.window);
if (bar)
- x_scroll_bar_note_movement (bar, &event.xmotion);
+ x_scroll_bar_note_movement (bar, &event->xmotion);
#endif /* USE_TOOLKIT_SCROLL_BARS */
/* If we move outside the frame, then we're
}
case ConfigureNotify:
- f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
+ f = x_top_window_to_frame (dpyinfo, event->xconfigure.window);
#ifdef USE_GTK
if (!f
&& (f = any)
- && event.xconfigure.window == FRAME_X_WINDOW (f))
+ && event->xconfigure.window == FRAME_X_WINDOW (f))
{
- xg_frame_resized (f, event.xconfigure.width,
- event.xconfigure.height);
+ xg_frame_resized (f, event->xconfigure.width,
+ event->xconfigure.height);
f = 0;
}
#endif
{
#ifndef USE_X_TOOLKIT
#ifndef USE_GTK
- int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event.xconfigure.height);
- int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event.xconfigure.width);
+ int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
+ int height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, event->xconfigure.height);
/* In the toolkit version, change_frame_size
is called by the code that handles resizing
/* Even if the number of character rows and columns has
not changed, the font size may have changed, so we need
to check the pixel dimensions as well. */
- if (columns != FRAME_COLS (f)
- || rows != FRAME_LINES (f)
- || event.xconfigure.width != FRAME_PIXEL_WIDTH (f)
- || event.xconfigure.height != FRAME_PIXEL_HEIGHT (f))
+ if (width != FRAME_TEXT_WIDTH (f)
+ || height != FRAME_TEXT_HEIGHT (f)
+ || event->xconfigure.width != FRAME_PIXEL_WIDTH (f)
+ || event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
{
- change_frame_size (f, rows, columns, 0, 1, 0);
+ change_frame_size (f, width, height, 0, 1, 0, 1);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
- FRAME_PIXEL_WIDTH (f) = event.xconfigure.width;
- FRAME_PIXEL_HEIGHT (f) = event.xconfigure.height;
+ FRAME_PIXEL_WIDTH (f) = event->xconfigure.width;
+ FRAME_PIXEL_HEIGHT (f) = event->xconfigure.height;
#endif /* not USE_GTK */
#endif
if (FRAME_GTK_OUTER_WIDGET (f)
&& gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
#endif
- {
- x_real_positions (f, &f->left_pos, &f->top_pos);
- }
+ x_real_positions (f, &f->left_pos, &f->top_pos);
#ifdef HAVE_X_I18N
if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
bool tool_bar_p = 0;
memset (&compose_status, 0, sizeof (compose_status));
- last_mouse_glyph_frame = 0;
- dpyinfo->last_user_time = event.xbutton.time;
+ dpyinfo->last_mouse_glyph_frame = NULL;
+ dpyinfo->last_user_time = event->xbutton.time;
- if (dpyinfo->grabbed
- && last_mouse_frame
- && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
- else
- f = x_window_to_frame (dpyinfo, event.xbutton.window);
+ f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame
+ : x_window_to_frame (dpyinfo, event->xbutton.window));
#ifdef USE_GTK
- if (f && xg_event_is_for_scrollbar (f, &event))
+ if (f && xg_event_is_for_scrollbar (f, event))
f = 0;
#endif
if (f)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
{
Lisp_Object window;
- int x = event.xbutton.x;
- int y = event.xbutton.y;
+ int x = event->xbutton.x;
+ int y = event->xbutton.y;
window = window_from_coordinates (f, x, y, 0, 1);
tool_bar_p = EQ (window, f->tool_bar_window);
- if (tool_bar_p && event.xbutton.button < 4)
+ if (tool_bar_p && event->xbutton.button < 4)
handle_tool_bar_click
- (f, x, y, event.xbutton.type == ButtonPress,
- x_x_to_emacs_modifiers (dpyinfo, event.xbutton.state));
+ (f, x, y, event->xbutton.type == ButtonPress,
+ x_x_to_emacs_modifiers (dpyinfo, event->xbutton.state));
}
#endif /* !USE_GTK */
{
if (ignore_next_mouse_click_timeout)
{
- if (event.type == ButtonPress
- && (int)(event.xbutton.time - ignore_next_mouse_click_timeout) > 0)
+ if (event->type == ButtonPress
+ && event->xbutton.time > ignore_next_mouse_click_timeout)
{
ignore_next_mouse_click_timeout = 0;
- construct_mouse_click (&inev.ie, &event.xbutton, f);
+ construct_mouse_click (&inev.ie, &event->xbutton, f);
}
- if (event.type == ButtonRelease)
+ if (event->type == ButtonRelease)
ignore_next_mouse_click_timeout = 0;
}
else
- construct_mouse_click (&inev.ie, &event.xbutton, f);
+ construct_mouse_click (&inev.ie, &event->xbutton, f);
}
if (FRAME_X_EMBEDDED_P (f))
- xembed_send_message (f, event.xbutton.time,
+ xembed_send_message (f, event->xbutton.time,
XEMBED_REQUEST_FOCUS, 0, 0, 0);
}
else
{
struct scroll_bar *bar
- = x_window_to_scroll_bar (event.xbutton.display,
- event.xbutton.window);
+ = x_window_to_scroll_bar (event->xbutton.display,
+ event->xbutton.window);
#ifdef USE_TOOLKIT_SCROLL_BARS
/* Make the "Ctrl-Mouse-2 splits window" work for toolkit
scroll bars. */
- if (bar && event.xbutton.state & ControlMask)
+ if (bar && event->xbutton.state & ControlMask)
{
- x_scroll_bar_handle_click (bar, &event, &inev.ie);
+ x_scroll_bar_handle_click (bar, event, &inev.ie);
*finish = X_EVENT_DROP;
}
#else /* not USE_TOOLKIT_SCROLL_BARS */
if (bar)
- x_scroll_bar_handle_click (bar, &event, &inev.ie);
+ x_scroll_bar_handle_click (bar, event, &inev.ie);
#endif /* not USE_TOOLKIT_SCROLL_BARS */
}
- if (event.type == ButtonPress)
+ if (event->type == ButtonPress)
{
- dpyinfo->grabbed |= (1 << event.xbutton.button);
- last_mouse_frame = f;
+ dpyinfo->grabbed |= (1 << event->xbutton.button);
+ dpyinfo->last_mouse_frame = f;
if (!tool_bar_p)
last_tool_bar_item = -1;
}
else
- dpyinfo->grabbed &= ~(1 << event.xbutton.button);
+ dpyinfo->grabbed &= ~(1 << event->xbutton.button);
/* Ignore any mouse motion that happened before this event;
any subsequent mouse-movement Emacs events should reflect
f->mouse_moved = 0;
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
- f = x_menubar_window_to_frame (dpyinfo, &event);
+ f = x_menubar_window_to_frame (dpyinfo, event);
/* For a down-event in the menu bar,
don't pass it to Xt right now.
Instead, save it away
if (! popup_activated ()
#ifdef USE_GTK
/* Gtk+ menus only react to the first three buttons. */
- && event.xbutton.button < 3
+ && event->xbutton.button < 3
#endif
- && f && event.type == ButtonPress
+ && f && event->type == ButtonPress
/* Verify the event is really within the menu bar
and not just sent to it due to grabbing. */
- && event.xbutton.x >= 0
- && event.xbutton.x < FRAME_PIXEL_WIDTH (f)
- && event.xbutton.y >= 0
- && event.xbutton.y < f->output_data.x->menubar_height
- && event.xbutton.same_screen)
+ && event->xbutton.x >= 0
+ && event->xbutton.x < FRAME_PIXEL_WIDTH (f)
+ && event->xbutton.y >= 0
+ && event->xbutton.y < f->output_data.x->menubar_height
+ && event->xbutton.same_screen)
{
- SET_SAVED_BUTTON_EVENT;
- *finish = X_EVENT_DROP;
+ if (!f->output_data.x->saved_menu_event)
+ f->output_data.x->saved_menu_event = xmalloc (sizeof *event);
+ *f->output_data.x->saved_menu_event = *event;
+ inev.ie.kind = MENU_BAR_ACTIVATE_EVENT;
+ XSETFRAME (inev.ie.frame_or_window, f);
+ *finish = X_EVENT_DROP;
}
else
goto OTHER;
case MappingNotify:
/* Someone has changed the keyboard mapping - update the
local cache. */
- switch (event.xmapping.request)
+ switch (event->xmapping.request)
{
case MappingModifier:
x_find_modifier_meanings (dpyinfo);
/* This is meant to fall through. */
case MappingKeyboard:
- XRefreshKeyboardMapping (&event.xmapping);
+ XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
}
goto OTHER;
case DestroyNotify:
- xft_settings_event (dpyinfo, &event);
+ xft_settings_event (dpyinfo, event);
break;
default:
#ifdef USE_X_TOOLKIT
block_input ();
if (*finish != X_EVENT_DROP)
- XtDispatchEvent (&event);
+ XtDispatchEvent ((XEvent *) event);
unblock_input ();
#endif /* USE_X_TOOLKIT */
break;
}
SAFE_FREE ();
- *eventptr = event;
return count;
}
{
int count = 0;
int event_found = 0;
+ struct x_display_info *dpyinfo = terminal->display_info.x;
block_input ();
input_signal_count++;
/* For debugging, this gives a way to fake an I/O error. */
- if (terminal->display_info.x == XTread_socket_fake_io_error)
+ if (dpyinfo == XTread_socket_fake_io_error)
{
XTread_socket_fake_io_error = 0;
- x_io_error_quitter (terminal->display_info.x->display);
+ x_io_error_quitter (dpyinfo->display);
}
#ifndef USE_GTK
- while (XPending (terminal->display_info.x->display))
+ while (XPending (dpyinfo->display))
{
int finish;
XEvent event;
- XNextEvent (terminal->display_info.x->display, &event);
+ XNextEvent (dpyinfo->display, &event);
#ifdef HAVE_X_I18N
/* Filter events for the current X input method. */
- if (x_filter_event (terminal->display_info.x, &event))
+ if (x_filter_event (dpyinfo, &event))
continue;
#endif
event_found = 1;
- count += handle_one_xevent (terminal->display_info.x,
- &event, &finish, hold_quit);
+ count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
if (finish == X_EVENT_GOTO_OUT)
- goto out;
+ break;
}
- out:;
-
#else /* USE_GTK */
/* For GTK we must use the GTK event loop. But XEvents gets passed
}
/* If the focus was just given to an auto-raising frame,
- raise it now. */
- /* ??? This ought to be able to handle more than one such frame. */
- if (pending_autoraise_frame)
+ raise it now. FIXME: handle more than one such frame. */
+ if (dpyinfo->x_pending_autoraise_frame)
{
- x_raise_frame (pending_autoraise_frame);
- pending_autoraise_frame = 0;
+ x_raise_frame (dpyinfo->x_pending_autoraise_frame);
+ dpyinfo->x_pending_autoraise_frame = NULL;
}
unblock_input ();
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
{
int wid = FRAME_COLUMN_WIDTH (f);
+
FRAME_CONFIG_SCROLL_BAR_COLS (f)
= (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
}
else
{
int wid = FRAME_COLUMN_WIDTH (f);
+
+ FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 14;
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
}
doing it because it's done in Fx_show_tip, and it leads to
problems because the tip frame has no widget. */
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
- x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+ x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
}
#ifdef HAVE_X_I18N
static int
-x_handle_net_wm_state (struct frame *f, XPropertyEvent *event)
+x_handle_net_wm_state (struct frame *f, const XPropertyEvent *event)
{
int value = FULLSCREEN_NONE;
Lisp_Object lval;
size changes. Otherwise we leave the window gravity unchanged. */
static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
int pixelwidth, pixelheight;
- check_frame_size (f, &rows, &cols);
+ check_frame_size (f, &width, &height, pixelwise);
f->scroll_bar_actual_width
= (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
? 0
compute_fringe_widths (f, 0);
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
+ pixelwidth =
+ (pixelwise ? width : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
+ FRAME_TOOLBAR_WIDTH (f);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
+ pixelheight =
+ (pixelwise ? height : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
+ FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
if (change_gravity) f->win_gravity = NorthWestGravity;
x_wait_for_event (f, ConfigureNotify);
else
{
- change_frame_size (f, rows, cols, 0, 1, 0);
+ change_frame_size (f, width, height, 0, 1, 0, 1);
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
x_sync (f);
Otherwise we leave the window gravity unchanged. */
void
-x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
{
block_input ();
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
{
- int r, c;
+ int r, c, text_width, text_height;
/* When the frame is maximized/fullscreen or running under for
example Xmonad, x_set_window_size_1 will be a no-op.
- In that case, the right thing to do is extend rows/cols to
+ In that case, the right thing to do is extend rows/width to
the current frame size. We do that first if x_set_window_size_1
turns out to not be a no-op (there is no way to know).
The size will be adjusted again if the frame gets a
is however. */
pixelh -= FRAME_MENUBAR_HEIGHT (f);
#endif
+ text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
+ text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
/* Update f->scroll_bar_actual_width because it is used in
FRAME_PIXEL_WIDTH_TO_TEXT_COLS. */
f->scroll_bar_actual_width
= FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
- change_frame_size (f, r, c, 0, 1, 0);
+ change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
}
#ifdef USE_GTK
if (FRAME_GTK_WIDGET (f))
- xg_frame_set_char_size (f, cols, rows);
+ xg_frame_set_char_size (f, width, height);
else
- x_set_window_size_1 (f, change_gravity, cols, rows);
+ x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
#else /* not USE_GTK */
- x_set_window_size_1 (f, change_gravity, cols, rows);
+ x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
#endif /* not USE_GTK */
void
x_make_frame_visible (struct frame *f)
{
- Lisp_Object type;
int original_top, original_left;
int retry_count = 2;
block_input ();
- type = x_icon_type (f);
- if (!NILP (type))
- x_bitmap_icon (f, type);
+ x_set_bitmap_icon (f);
if (! FRAME_VISIBLE_P (f))
{
#ifdef USE_X_TOOLKIT
int result;
#endif
- Lisp_Object type;
/* Don't keep the highlight on an invisible frame. */
if (FRAME_DISPLAY_INFO (f)->x_highlight_frame == f)
block_input ();
- type = x_icon_type (f);
- if (!NILP (type))
- x_bitmap_icon (f, type);
+ x_set_bitmap_icon (f);
#if defined (USE_GTK)
if (FRAME_GTK_OUTER_WIDGET (f))
if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
#endif /* USE_TOOLKIT_SCROLL_BARS */
- if (f->output_data.x->white_relief.allocated_p)
+ if (f->output_data.x->white_relief.pixel != -1)
unload_color (f, f->output_data.x->white_relief.pixel);
- if (f->output_data.x->black_relief.allocated_p)
+ if (f->output_data.x->black_relief.pixel != -1)
unload_color (f, f->output_data.x->black_relief.pixel);
x_free_gcs (f);
base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
- check_frame_size (f, &min_rows, &min_cols);
+ check_frame_size (f, &min_cols, &min_rows, 0);
/* The window manager uses the base width hints to calculate the
current number of rows and columns in the frame while
get to the first bit. With MASK 0x7e0, *BITS is set to 6, and *OFFSET
to 5. */
static void
-get_bits_and_offset (long unsigned int mask, int *bits, int *offset)
+get_bits_and_offset (unsigned long mask, int *bits, int *offset)
{
int nr = 0;
int off = 0;
{
struct x_display_info *share;
- Lisp_Object tail;
- for (share = x_display_list, tail = x_display_name_list; share;
- share = share->next, tail = XCDR (tail))
- if (same_x_server (SSDATA (XCAR (XCAR (tail))),
+ for (share = x_display_list; share; share = share->next)
+ if (same_x_server (SSDATA (XCAR (share->name_list_element)),
SSDATA (display_name)))
break;
if (share)
terminal->kboard = share->terminal->kboard;
else
{
- terminal->kboard = xmalloc (sizeof *terminal->kboard);
- init_kboard (terminal->kboard);
- kset_window_system (terminal->kboard, Qx);
-
- /* Add the keyboard to the list before running Lisp code (via
- Qvendor_specific_keysyms below), since these are not traced
- via terminals but only through all_kboards. */
- terminal->kboard->next_kboard = all_kboards;
- all_kboards = terminal->kboard;
+ terminal->kboard = allocate_kboard (Qx);
if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
{
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
- /* Put it on x_display_name_list as well, to keep them parallel. */
- x_display_name_list = Fcons (Fcons (display_name, Qnil),
- x_display_name_list);
- dpyinfo->name_list_element = XCAR (x_display_name_list);
-
+ dpyinfo->name_list_element = Fcons (display_name, Qnil);
dpyinfo->display = dpy;
/* Set the name of the terminal. */
break;
}
- /* Discard this display from x_display_name_list and x_display_list.
- We can't use Fdelq because that can quit. */
- if (! NILP (x_display_name_list)
- && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
- x_display_name_list = XCDR (x_display_name_list);
- else
- {
- Lisp_Object tail;
-
- tail = x_display_name_list;
- while (CONSP (tail) && CONSP (XCDR (tail)))
- {
- if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
- {
- XSETCDR (tail, XCDR (XCDR (tail)));
- break;
- }
- tail = XCDR (tail);
- }
- }
-
if (next_noop_dpyinfo == dpyinfo)
next_noop_dpyinfo = dpyinfo->next;
x_clear_frame_area,
x_draw_window_cursor,
x_draw_vertical_window_border,
+ x_draw_window_divider,
x_shift_glyphs_for_insert
};
terminal->delete_terminal_hook = x_delete_terminal;
terminal->rif = &x_redisplay_interface;
- terminal->scroll_region_ok = 1; /* We'll scroll partial frames. */
- terminal->char_ins_del_ok = 1;
- terminal->line_ins_del_ok = 1; /* We'll just blt 'em. */
- terminal->fast_clear_end_of_line = 1; /* X does this well. */
- terminal->memory_below_frame = 0; /* We don't remember what scrolls
- off the bottom. */
return terminal;
}
#endif
#endif
- pending_autoraise_frame = 0;
-
/* Note that there is no real way portable across R3/R4 to get the
original error handler. */
XSetErrorHandler (x_error_handler);
{
x_error_message = NULL;
- staticpro (&x_display_name_list);
- x_display_name_list = Qnil;
-
- staticpro (&last_mouse_scroll_bar);
- last_mouse_scroll_bar = Qnil;
-
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFSYM (Qlatin_1, "latin-1");
Vx_toolkit_scroll_bars = Qnil;
#endif
- staticpro (&last_mouse_motion_frame);
- last_mouse_motion_frame = Qnil;
-
- Qmodifier_value = intern_c_string ("modifier-value");
- Qalt = intern_c_string ("alt");
+ DEFSYM (Qmodifier_value, "modifier-value");
+ DEFSYM (Qalt, "alt");
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
- Qhyper = intern_c_string ("hyper");
+ DEFSYM (Qhyper, "hyper");
Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
- Qmeta = intern_c_string ("meta");
+ DEFSYM (Qmeta, "meta");
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
- Qsuper = intern_c_string ("super");
+ DEFSYM (Qsuper, "super");
Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
DEFVAR_LISP ("x-alt-keysym", Vx_alt_keysym,