#include "lisp.h"
-/* On 4.3 this loses if it comes after xterm.h. */
+/* On 4.3 these lose if they come after xterm.h. */
+#include <stdio.h>
#include <signal.h>
/* This may include sys/types.h, and that somehow loses
#include "systime.h"
#include <fcntl.h>
-#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <setjmp.h>
/* Any buttons grabbed. */
unsigned int x_mouse_grabbed;
+/* Which modifier keys are on which modifier bits?
+
+ With each keystroke, X returns eight bits indicating which modifier
+ keys were held down when the key was pressed. The interpretation
+ of the top five modifier bits depends on what keys are attached
+ to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
+ is the meta bit.
+
+ x_meta_mod_mask is a mask containing the bits used for the meta key.
+ It may have more than one bit set, if more than one modifier bit
+ has meta keys on it. Basically, if EVENT is a KeyPress event,
+ the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
+
+ x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
+ lock modifier bit, or zero otherwise. Non-alphabetic keys should
+ only be affected by the lock modifier bit if XK_Shift_Lock is in
+ use; XK_Caps_Lock should only affect alphabetic keys. With this
+ arrangement, the lock modifier should shift the character if
+ (EVENT.state & x_shift_lock_mask) != 0. */
+static int x_meta_mod_mask, x_shift_lock_mask;
+
+/* Initialize mode_switch_bit and modifier_meaning. */
+static void
+x_find_modifier_meanings ()
+{
+ int min_code, max_code;
+ KeySym *syms;
+ int syms_per_code;
+ XModifierKeymap *mods;
+ int alt_mod_mask = 0;
+
+ x_meta_mod_mask = 0;
+ x_shift_lock_mask = 0;
+
+ XDisplayKeycodes (x_current_display, &min_code, &max_code);
+ syms = XGetKeyboardMapping (x_current_display,
+ min_code, max_code - min_code + 1,
+ &syms_per_code);
+ mods = XGetModifierMapping (x_current_display);
+
+ /* Scan the modifier table to see which modifier bits the Meta and
+ Alt keysyms are on. */
+ {
+ int row, col; /* The row and column in the modifier table. */
+
+ for (row = 3; row < 8; row++)
+ for (col = 0; col < mods->max_keypermod; col++)
+ {
+ KeyCode code =
+ mods->modifiermap[(row * mods->max_keypermod) + col];
+
+ /* Are any of this keycode's keysyms a meta key? */
+ {
+ int code_col;
+
+ for (code_col = 0; code_col < syms_per_code; code_col++)
+ {
+ int sym = syms[((code - min_code) * syms_per_code) + code_col];
+
+ switch (sym)
+ {
+ case XK_Meta_L:
+ case XK_Meta_R:
+ x_meta_mod_mask |= (1 << row);
+ break;
+
+ case XK_Alt_L:
+ case XK_Alt_R:
+ alt_mod_mask |= (1 << row);
+ break;
+
+ case XK_Shift_Lock:
+ /* Ignore this if it's not on the lock modifier. */
+ if ((1 << row) == LockMask)
+ x_shift_lock_mask = LockMask;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
+ if (! x_meta_mod_mask)
+ x_meta_mod_mask = alt_mod_mask;
+
+ XFree ((char *) syms);
+ XFreeModifiermap (mods);
+}
+
+
/* Convert a set of X modifier bits to the proper form for a
struct input_event modifiers value. */
-static Lisp_Object
+static unsigned int
x_convert_modifiers (state)
unsigned int state;
{
- return ( ((state & (ShiftMask | LockMask)) ? shift_modifier : 0)
- | ((state & ControlMask) ? ctrl_modifier : 0)
- | ((state & Mod1Mask) ? meta_modifier : 0));
+ return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
+ | ((state & ControlMask) ? ctrl_modifier : 0)
+ | ((state & x_meta_mod_mask) ? meta_modifier : 0));
}
extern struct frame *x_window_to_scrollbar ();
XSET (result->code, Lisp_Int, event->button);
result->timestamp = event->time;
result->modifiers = (x_convert_modifiers (event->state)
- | (event->type == ButtonRelease ? up_modifier : 0));
+ | (event->type == ButtonRelease
+ ? up_modifier
+ : down_modifier));
/* Notice if the mouse is still grabbed. */
if (event->type == ButtonPress)
Vmouse_depressed = Qnil;
}
- if (part) /* Scrollbar event */
+ if (! NILP (part)) /* Scrollbar event */
{
int pos, len;
pos = event->y - (f->display.x->v_scrollbar_width - 2);
- XSET (x_mouse_x, Lisp_Int, pos);
+ x_mouse_x = pos;
len = ((FONT_HEIGHT (f->display.x->font) * f->height)
+ f->display.x->internal_border_width
- (2 * (f->display.x->v_scrollbar_width - 2)));
- XSET (x_mouse_y, Lisp_Int, len);
+ x_mouse_y = len;
result->kind = scrollbar_click;
result->part = part;
pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
result->kind = mouse_click;
- result->x = column;
- result->y = row;
+ XFASTINT (result->x) = column;
+ XFASTINT (result->y) = row;
result->frame = f;
}
}
sometimes don't work. */
static Time enter_timestamp;
+/* This holds the state XLookupString needs to implement dead keys
+ and other tricks known as "compose processing". _X Window System_
+ says that a portable program can't use this, but Stephen Gildea assures
+ me that letting the compiler initialize it to zeros will work okay.
+
+ This must be defined outside of XTread_socket, for the same reasons
+ given for enter_timestamp, above. */
+static XComposeStatus compose_status;
+
/* Communication with window managers. */
Atom Xatom_wm_protocols;
WAITP is nonzero if we should block until input arrives.
EXPECTED is nonzero if the caller knows input is available. */
-Lisp_Object
+int
XTread_socket (sd, bufp, numchars, waitp, expected)
register int sd;
register struct input_event *bufp;
break;
case PropertyNotify:
- /* If we were to do this synchronously, there'd be no worry
- about re-selecting. */
- x_send_incremental (event);
+
+ /* If we're being told about a root window property, then it's
+ a cut buffer change. */
+ if (event.xproperty.window == ROOT_WINDOW)
+ x_invalidate_cut_buffer_cache (&event.xproperty);
+
+ /* Otherwise, we're probably handling an incremental
+ selection transmission. */
+ else
+ {
+ /* If we were to do this synchronously, there'd be no worry
+ about re-selecting. */
+ x_send_incremental (event);
+ }
break;
case Expose:
if (f != 0)
{
KeySym keysym;
- XComposeStatus status;
char copy_buffer[80];
int modifiers = event.xkey.state;
just clear the meta-key flag to get the 'pure' character. */
event.xkey.state &= ~Mod1Mask;
- /* This will have to go some day... */
- nbytes = XLookupString (&event.xkey,
- copy_buffer,
- 80,
- &keysym,
- &status);
+ /* This will have to go some day... */
+ nbytes =
+ XLookupString (&event.xkey, copy_buffer, 80, &keysym,
+ &compose_status);
/* Strip off the vendor-specific keysym bit, and take a shot
at recognizing the codes. HP servers have extra keysyms
if (nbytes == 1)
{
- if (modifiers & Mod1Mask)
+ if (modifiers & x_meta_mod_mask)
*copy_buffer |= METABIT;
bufp->kind = ascii_keystroke;
XSET (bufp->code, Lisp_Int, *copy_buffer);
if (f)
if (!x_focus_frame || (f == x_focus_frame))
construct_mouse_click (&emacs_event,
- &event, f, 0, 0);
+ &event, f, Qnil, 0);
else
continue;
else
#endif /* ! defined (HAVE_X11) */
case MappingNotify:
- if (event.xmapping.request == MappingKeyboard)
- /* Someone has changed the keyboard mapping - flush the
- local cache. */
- XRefreshKeyboardMapping (&event.xmapping);
+ /* Someone has changed the keyboard mapping - update the
+ local cache. */
+ switch (event.xmapping.request)
+ {
+ case MappingModifier:
+ x_find_modifier_meanings ();
+ /* This is meant to fall through. */
+ case MappingKeyboard:
+ XRefreshKeyboardMapping (&event.xmapping);
+ }
break;
default:
/* Set up the error buffer. */
x_caught_error_message =
(char (*)[]) xmalloc (sizeof (*x_caught_error_message));
+ (*x_caught_error_message)[0] = '\0';
/* Install our little error handler. */
XHandleError (x_error_catcher);
#ifdef HAVE_X11
if (f->display.x->left_pos < 0)
f->display.x->left_pos
- = XINT (x_screen_width) - PIXEL_WIDTH (f) + f->display.x->left_pos;
+ = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
if (f->display.x->top_pos < 0)
f->display.x->top_pos
- = XINT (x_screen_height) - PIXEL_HEIGHT (f) + f->display.x->top_pos;
+ = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
#else /* ! defined (HAVE_X11) */
WINDOWINFO_TYPE parentinfo;
(x_screen_height - ((2 * f->display.x->internal_border_width)
+ f->display.x->h_scrollbar_height));
{
- int min_rows = 0, min_cols = 0;
- check_frame_size (f, &min_rows, &min_cols);
- size_hints.min_width = ((2 * f->display.x->internal_border_width)
- + min_cols * size_hints.width_inc
- + f->display.x->v_scrollbar_width);
- size_hints.min_height = ((2 * f->display.x->internal_border_width)
- + min_rows * size_hints.height_inc
- + f->display.x->h_scrollbar_height);
+ int base_width, base_height;
+
+ base_width = ((2 * f->display.x->internal_border_width)
+ + f->display.x->v_scrollbar_width);
+ base_height = ((2 * f->display.x->internal_border_width)
+ + f->display.x->h_scrollbar_height);
+
+ {
+ int min_rows = 0, min_cols = 0;
+ check_frame_size (f, &min_rows, &min_cols);
+
+ /* The window manager uses the base width hints to calculate the
+ current number of rows and columns in the frame while
+ resizing; min_width and min_height aren't useful for this
+ purpose, since they might not give the dimensions for a
+ zero-row, zero-column frame.
+
+ We use the base_width and base_height members if we have
+ them; otherwise, we set the min_width and min_height members
+ to the size for a zero x zero frame. */
+
+#ifdef HAVE_X11R4
+ size_hints.flags |= PBaseSize;
+ size_hints.base_width = base_width;
+ size_hints.base_height = base_height;
+ size_hints.min_width = base_width + min_cols * size_hints.width_inc;
+ size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+#else
+ size_hints.min_width = base_width;
+ size_hints.min_height = base_height;
+#endif
+ }
}
size_hints.flags |= USSize;
}
+#ifdef HAVE_X11R4
+ XSetWMNormalHints (x_current_display, window, &size_hints);
+#else
XSetNormalHints (x_current_display, window, &size_hints);
+#endif
}
/* Used for IconicState or NormalState */
+ 2);
sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
}
+
+ /* Figure out which modifier bits mean what. */
+ x_find_modifier_meanings ();
+ /* Watch for PropertyNotify events on the root window; we use them
+ to figure out when to invalidate our cache of the cut buffers. */
+ x_watch_cut_buffer_cache ();
+
dup2 (ConnectionNumber (x_current_display), 0);
#ifndef SYSV_STREAMS