/* -*-C-*-
-$Id: x11.h,v 1.20 2005/11/12 22:53:29 cph Exp $
+$Id: x11.h,v 1.21 2006/10/21 16:05:58 riastradh Exp $
Copyright 1989,1990,1991,1992,1993,2000 Massachusetts Institute of Technology
-Copyright 2005 Massachusetts Institute of Technology
+Copyright 2005,2006 Massachusetts Institute of Technology
This file is part of MIT/GNU Scheme.
XEvent cached_event;
char cached_event_p;
+ /* X key events have 8-bit modifier masks, three bits of which are
+ defined to be Shift, Lock, and Control, identified with ShiftMask,
+ LockMask, and ControlMask; and five bits of which are unspecified
+ named only mod1 to mod5. Which ones mean Meta, Super, Hyper, &c.,
+ vary from system to system, however, so, on initializing the display
+ record, we grovel through some tables (XGetKeyboardMapping and
+ XGetModifierMapping) to find which ones the various modifier
+ keysyms are assigned to, and cache them here.
+
+ Scheme knows about Shift, Control, Meta, Super, and Hyper. Of
+ these, only Meta, Super, and Hyper are identified by numbered
+ modifier masks. All other modifiers are ignored. */
+ int modifier_mask_meta;
+ int modifier_mask_super;
+ int modifier_mask_hyper;
+
/* The type of window manager we have. If we move FRAME_OUTER_WINDOW
to x/y 0/0, some window managers (type A) puts the window manager
decorations outside the screen and FRAME_OUTER_WINDOW exactly at 0/0.
#define XD_WM_TAKE_FOCUS(xd) ((xd) -> wm_take_focus)
#define XD_CACHED_EVENT(xd) ((xd) -> cached_event)
#define XD_CACHED_EVENT_P(xd) ((xd) -> cached_event_p)
+#define XD_MODIFIER_MASK_SHIFT(xd) (ShiftMask)
+#define XD_MODIFIER_MASK_CONTROL(xd) (ControlMask)
+#define XD_MODIFIER_MASK_LOCK(xd) (LockMask)
+#define XD_MODIFIER_MASK_META(xd) ((xd) -> modifier_mask_meta)
+#define XD_MODIFIER_MASK_SUPER(xd) ((xd) -> modifier_mask_super)
+#define XD_MODIFIER_MASK_HYPER(xd) ((xd) -> modifier_mask_hyper)
#define XD_WM_TYPE(xd) ((xd) -> wm_type)
#define XD_TO_OBJECT(xd) (LONG_TO_UNSIGNED_FIXNUM (XD_ALLOCATION_INDEX (xd)))
+#define X_MODIFIER_MASK_SHIFT_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_SHIFT (xd)))
+#define X_MODIFIER_MASK_CONTROL_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_CONTROL (xd)))
+#define X_MODIFIER_MASK_LOCK_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_LOCK (xd)))
+#define X_MODIFIER_MASK_META_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_META (xd)))
+#define X_MODIFIER_MASK_SUPER_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_SUPER (xd)))
+#define X_MODIFIER_MASK_HYPER_P(modifier_mask, xd) \
+ ((modifier_mask) & (XD_MODIFIER_MASK_HYPER (xd)))
+
extern struct xdisplay * EXFUN (x_display_arg, (unsigned int arg));
struct drawing_attributes
/* -*-C-*-
-$Id: x11base.c,v 1.85 2005/11/16 04:00:16 cph Exp $
+$Id: x11base.c,v 1.86 2006/10/21 16:05:58 riastradh Exp $
Copyright 1989,1990,1991,1992,1993,1994 Massachusetts Institute of Technology
Copyright 1995,1996,1997,1998,2000,2001 Massachusetts Institute of Technology
-Copyright 2003,2004,2005 Massachusetts Institute of Technology
+Copyright 2003,2004,2005,2006 Massachusetts Institute of Technology
This file is part of MIT/GNU Scheme.
return (decor != (XW_WINDOW (xw)));
}
\f
-/* Open/Close Windows and Displays */
+/* Open/Close Windows */
#define MAKE_GC(gc, fore, back) \
{ \
XSetIOErrorHandler (x_io_error_handler);
free (xw);
}
+\f
+/* Initialize/Close Displays */
+
+#define MODIFIER_INDEX_TO_MASK(N) (1 << (N))
+
+/* Grovel through the X server's keycode and modifier mappings to find
+ out what we ought to interpret as Meta, Hyper, and Super, based on
+ what modifiers are associated with keycodes that are associated with
+ keysyms Meta_L, Meta_R, Alt_L, Alt_R, Hyper_L, &c.
+
+ Adapted from GNU Emacs. */
+
+static void
+DEFUN (x_initialize_display_modifier_masks, (xd), struct xdisplay * xd)
+{
+ int min_keycode;
+ int max_keycode;
+ XModifierKeymap * modifier_keymap;
+ KeyCode * modifier_to_keycodes_table;
+ int keycodes_per_modifier;
+ KeySym * keycode_to_keysyms_table;
+ int keysyms_per_keycode;
+
+ (XD_MODIFIER_MASK_META (xd)) = 0;
+ (XD_MODIFIER_MASK_SUPER (xd)) = 0;
+ (XD_MODIFIER_MASK_HYPER (xd)) = 0;
+
+ modifier_keymap = (XGetModifierMapping ((XD_DISPLAY (xd))));
+ modifier_to_keycodes_table = (modifier_keymap -> modifiermap);
+ keycodes_per_modifier = (modifier_keymap -> max_keypermod);
+
+ XDisplayKeycodes ((XD_DISPLAY (xd)), (& min_keycode), (& max_keycode));
+
+ keycode_to_keysyms_table =
+ (XGetKeyboardMapping ((XD_DISPLAY (xd)),
+ min_keycode,
+ (max_keycode - min_keycode + 1),
+ (& keysyms_per_keycode)));
+
+ /* Go through each of the 8 non-preassigned modifiers, which start at
+ 3 (Mod1), after Shift, Control, and Lock. For each modifier, go
+ through all of the (non-zero) keycodes attached to it; for each
+ keycode, go through all of the keysyms attached to it; check each
+ keysym for the modifiers that we're interested in (Meta, Hyper,
+ and Super). */
+
+ {
+ int modifier_index;
+
+ for (modifier_index = 3; (modifier_index < 8); modifier_index += 1)
+ {
+ int modifier_mask = (MODIFIER_INDEX_TO_MASK (modifier_index));
+ KeyCode * keycodes =
+ (& (modifier_to_keycodes_table
+ [modifier_index * keycodes_per_modifier]));
+
+ /* This is a flag specifying whether the modifier has already
+ been identified as Meta, which takes precedence over Hyper
+ and Super. (What about precedence between Hyper and
+ Super...? This is GNU Emacs's behaviour.) */
+ int modifier_is_meta_p = 0;
+
+ int keycode_index;
+
+ for (keycode_index = 0;
+ (keycode_index < keycodes_per_modifier);
+ keycode_index += 1)
+ {
+ KeyCode keycode = (keycodes [keycode_index]);
+
+ if (keycode == 0)
+ continue;
+
+ {
+ int keysym_index;
+ KeySym * keysyms =
+ (& (keycode_to_keysyms_table
+ [(keycode - min_keycode) * keysyms_per_keycode]));
+
+ for (keysym_index = 0;
+ (keysym_index < keysyms_per_keycode);
+ keysym_index += 1)
+ switch (keysyms [keysym_index])
+ {
+ case XK_Meta_L:
+ case XK_Meta_R:
+ case XK_Alt_L:
+ case XK_Alt_R:
+ modifier_is_meta_p = 1;
+ (XD_MODIFIER_MASK_META (xd)) |= modifier_mask;
+ break;
+
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ if (! modifier_is_meta_p)
+ (XD_MODIFIER_MASK_HYPER (xd)) |= modifier_mask;
+ goto next_modifier;
+
+ case XK_Super_L:
+ case XK_Super_R:
+ if (! modifier_is_meta_p)
+ (XD_MODIFIER_MASK_SUPER (xd)) |= modifier_mask;
+ goto next_modifier;
+ }
+ }
+ }
+
+ next_modifier:
+ continue;
+ }
+ }
+
+ XFree (((char *) keycode_to_keysyms_table));
+ XFreeModifiermap (modifier_keymap);
+}
static void
DEFUN (x_close_display, (xd), struct xdisplay * xd)
default: button_number = 0; break;
}
if (button_number) {
+ struct xdisplay * xd = (XW_XD (xw));
--button_number;
- if ((event -> state) & ShiftMask) {
+ if (X_MODIFIER_MASK_SHIFT_P ((event -> state), xd)) {
button_number += 5;
}
- if ((event -> state) & ControlMask) {
+ if (X_MODIFIER_MASK_CONTROL_P ((event -> state), xd)) {
button_number += 10;
}
- if ((event -> state) & Mod1Mask) {
+ if (X_MODIFIER_MASK_META_P ((event -> state), xd)) {
button_number += 20;
}
conversion = (LONG_TO_UNSIGNED_FIXNUM (button_number));
return (result);
}
+/* This handles only the modifier bits that Scheme supports.
+ At the moment, these are Control, Meta, Super, and Hyper.
+ This might want to change if the character abstraction were ever to
+ change, or if the X11 interface were to be changed to use something
+ other than Scheme characters to convey key presses. */
+
static SCHEME_OBJECT
-DEFUN (convert_bucky_bits, (state, allp), unsigned int state AND int allp)
+DEFUN (x_modifier_mask_to_bucky_bits, (mask, xd),
+ unsigned int mask AND
+ struct xdisplay * xd)
{
long bucky = 0;
- if (state & Mod1Mask) bucky |= 0x0001; /* meta */
- if (state & ControlMask) bucky |= 0x0002; /* control */
- if (allp)
- {
- if (state & Mod2Mask) bucky |= 0x0004; /* super */
- if (state & Mod3Mask) bucky |= 0x0008; /* hyper */
- if (state & ShiftMask) bucky |= 0x0010;
- if (state & LockMask) bucky |= 0x0020;
- if (state & Mod4Mask) bucky |= 0x0040;
- if (state & Mod5Mask) bucky |= 0x0080;
- if (state & Button1Mask) bucky |= 0x0100;
- if (state & Button2Mask) bucky |= 0x0200;
- if (state & Button3Mask) bucky |= 0x0400;
- if (state & Button4Mask) bucky |= 0x0800;
- if (state & Button5Mask) bucky |= 0x1000;
- }
+ if (X_MODIFIER_MASK_CONTROL_P (mask, xd)) bucky |= CHAR_BITS_CONTROL;
+ if (X_MODIFIER_MASK_META_P (mask, xd)) bucky |= CHAR_BITS_META;
+ if (X_MODIFIER_MASK_SUPER_P (mask, xd)) bucky |= CHAR_BITS_SUPER;
+ if (X_MODIFIER_MASK_HYPER_P (mask, xd)) bucky |= CHAR_BITS_HYPER;
return (LONG_TO_UNSIGNED_FIXNUM (bucky));
}
+/* I'm not sure why we have a function for this. */
+
+static SCHEME_OBJECT
+DEFUN (x_key_button_mask_to_scheme, (x_state), unsigned int x_state)
+{
+ long scheme_state = 0;
+ if (x_state & ControlMask) scheme_state |= 0x0001;
+ if (x_state & Mod1Mask) scheme_state |= 0x0002;
+ if (x_state & Mod2Mask) scheme_state |= 0x0004;
+ if (x_state & Mod3Mask) scheme_state |= 0x0008;
+ if (x_state & ShiftMask) scheme_state |= 0x0010;
+ if (x_state & LockMask) scheme_state |= 0x0020;
+ if (x_state & Mod4Mask) scheme_state |= 0x0040;
+ if (x_state & Mod5Mask) scheme_state |= 0x0080;
+ if (x_state & Button1Mask) scheme_state |= 0x0100;
+ if (x_state & Button2Mask) scheme_state |= 0x0200;
+ if (x_state & Button3Mask) scheme_state |= 0x0400;
+ if (x_state & Button4Mask) scheme_state |= 0x0800;
+ if (x_state & Button5Mask) scheme_state |= 0x1000;
+ return (LONG_TO_UNSIGNED_FIXNUM (scheme_state));
+}
+
static XComposeStatus compose_status;
static SCHEME_OBJECT
/* Create Scheme bucky bits (kept independent of the character).
X has already controlified, so Scheme may choose to ignore
the control bucky bit. */
- VECTOR_SET (result, EVENT_1, (convert_bucky_bits ((event -> state), 0)));
+ VECTOR_SET (result, EVENT_1,
+ (x_modifier_mask_to_bucky_bits ((event -> state),
+ (XW_XD (xw)))));
/* Move vendor-specific bit from bit 28 (zero-based) to bit 23
so that all keysym values will fit in Scheme fixnums. */
VECTOR_SET
EVENT_INTEGER (result, EVENT_0, ((event -> xmotion) . x));
EVENT_INTEGER (result, EVENT_1, ((event -> xmotion) . y));
VECTOR_SET (result, EVENT_2,
- (convert_bucky_bits (((event -> xmotion) . state), 1)));
+ (x_key_button_mask_to_scheme
+ (((event -> xmotion) . state))));
}
break;
case ConfigureNotify:
(XD_WM_TAKE_FOCUS (xd)) =
(XInternAtom ((XD_DISPLAY (xd)), "WM_TAKE_FOCUS", False));
(XD_CACHED_EVENT_P (xd)) = 0;
+ x_initialize_display_modifier_masks (xd);
XRebindKeysym ((XD_DISPLAY (xd)), XK_BackSpace, 0, 0, "\177", 1);
PRIMITIVE_RETURN (XD_TO_OBJECT (xd));
}
VECTOR_SET (result, 1, (long_to_integer (root_y)));
VECTOR_SET (result, 2, (long_to_integer (win_x)));
VECTOR_SET (result, 3, (long_to_integer (win_y)));
- VECTOR_SET (result, 4, (convert_bucky_bits (keys_buttons, 1)));
+ VECTOR_SET (result, 4, (x_key_button_mask_to_scheme (keys_buttons)));
PRIMITIVE_RETURN (result);
}
}