WPrefs.app: zero X11 deps, zero #ifdef USE_X11_BACKEND

Complete architectural separation: all WPrefs.app panel code is now
backend-neutral. No X11 calls, no X11 types, no X11 includes, no
backend-specific #ifdef guards in shared sources.

New W_EventBackend vtable methods (implemented in X11, stubbed in WL):
  - grab_keyboard / ungrab_keyboard / allow_events
  - grab_pointer / ungrab_pointer / query_pointer
  - get_window_geometry / move_window / translate_coordinates
  - get_root_window / query_tree
  - get_pointer_control / set_pointer_control
  - modifier_from_key / get_modifier_keysyms
  - keysym_to_string / keysym_to_keycode / keycode_to_keysym
  - keysym_convert_case
  - send_wm_command
  - set_window_hints / set_window_property_string / set_window_property_data
  - recolor_cursor
  - set_error_handler / restore_error_handler

Panel changes:
  - xmodifier.c: thin wrapper calling eventBackend->modifier_from_key()
  - main.c: X11 locale init removed (belongs in backend screen_init)
  - WPrefs.c: eventBackend->send_wm_command("Reconfigure")
  - MouseSettings.c: vtable for pointer control + modifier keysyms
  - KeyboardShortcuts.c: vtable for grab/keysym/modifier ops
  - Menu.c: RImage crosshair icon, vtable keyboard grab
  - editmenu.c: vtable for all window/pointer/property ops

Verified: nm audit shows zero X11 symbol refs in WPrefs .o files.
grep shows zero #ifdef USE_X11_BACKEND in WPrefs.app/.
This commit is contained in:
Window Maker 2026-05-24 14:04:14 +02:00
parent b996a0e274
commit 8119bfe098
11 changed files with 802 additions and 686 deletions

View File

@ -471,6 +471,87 @@ typedef struct W_EventBackend {
int (*fd)(void *ectx);
void (*put_back)(void *ectx, WMEvent *ev);
void (*post_dispatch)(void *ectx, WMEvent *ev, struct W_View *toplevel);
/* --- Keyboard grab for shortcut capture --- */
/* Grab the keyboard so all key events come to `window`.
* Returns True on success. */
Bool (*grab_keyboard)(void *ectx, WNativeWindow window);
void (*ungrab_keyboard)(void *ectx);
/* Allow queued events to be replayed after a grab. */
void (*allow_events)(void *ectx);
/* --- Pointer grab for window picking --- */
/* Grab the pointer with the given cursor. Returns True on success. */
Bool (*grab_pointer)(void *ectx, WNativeWindow window, WMNativePixmap cursor);
void (*ungrab_pointer)(void *ectx);
/* Query pointer position relative to `window`. Returns child window. */
WNativeWindow (*query_pointer)(void *ectx, WNativeWindow window,
int *root_x, int *root_y,
int *win_x, int *win_y,
unsigned int *mask);
/* --- Window geometry queries --- */
Bool (*get_window_geometry)(void *ectx, WNativeWindow window,
int *x, int *y,
unsigned int *width, unsigned int *height);
void (*move_window)(void *ectx, WNativeWindow window, int x, int y);
WNativeWindow (*translate_coordinates)(void *ectx,
WNativeWindow src, WNativeWindow dst,
int src_x, int src_y,
int *dst_x, int *dst_y);
/* Get the root window (or equivalent top-level surface). */
WNativeWindow (*get_root_window)(void *ectx);
/* Get children of a window. Caller must free *children with wfree(). */
Bool (*query_tree)(void *ectx, WNativeWindow window,
WNativeWindow **children, unsigned int *nchildren);
/* --- Pointer control (acceleration) --- */
void (*get_pointer_control)(void *ectx, int *accel_num, int *accel_denom, int *threshold);
void (*set_pointer_control)(void *ectx, int accel_num, int accel_denom, int threshold);
/* --- Modifier mapping --- */
/* Returns the modifier index (ShiftMapIndex..Mod5MapIndex) for a named
* modifier ("SHIFT","CONTROL","ALT","META","SUPER","HYPER","MOD1".."MOD5").
* Returns -1 if unknown. */
int (*modifier_from_key)(void *ectx, const char *key_name);
/* --- Keysym helpers --- */
const char *(*keysym_to_string)(void *ectx, WMNativeKeysym keysym);
unsigned int (*keysym_to_keycode)(void *ectx, WMNativeKeysym keysym);
WMNativeKeysym (*keycode_to_keysym)(void *ectx, unsigned int keycode, int index);
void (*keysym_convert_case)(void *ectx, WMNativeKeysym sym,
WMNativeKeysym *lower, WMNativeKeysym *upper);
/* Get keysyms assigned to each modifier index (0..7).
* For each modifier index, returns up to max_per_mod keysyms in
* keysyms_out[index * max_per_mod .. (index+1)*max_per_mod - 1].
* Unused slots are set to 0 (NoSymbol).
* Returns the actual max_keypermod from the server. */
int (*get_modifier_keysyms)(void *ectx, WMNativeKeysym *keysyms_out,
int max_per_mod);
/* --- WM notification --- */
/* Send a command string to the running window manager. */
void (*send_wm_command)(void *ectx, const char *command);
/* --- Window properties --- */
void (*set_window_hints)(void *ectx, WNativeWindow window,
int min_w, int min_h, int max_w, int max_h,
int base_w, int base_h);
void (*set_window_property_string)(void *ectx, WNativeWindow window,
const char *atom_name, const char *value);
void (*set_window_property_data)(void *ectx, WNativeWindow window,
WMNativeAtom property, WMNativeAtom type,
int format, const void *data, int nelements);
/* --- Cursor --- */
void (*recolor_cursor)(void *ectx, WMNativePixmap cursor,
unsigned short fr, unsigned short fg, unsigned short fb,
unsigned short br, unsigned short bg, unsigned short bb);
/* --- Error handling --- */
void (*set_error_handler)(void *ectx, void *handler);
void (*restore_error_handler)(void *ectx);
} W_EventBackend;
extern const W_EventBackend W_EventBackendX11 __attribute__((weak));

View File

@ -16,6 +16,7 @@
#include "WINGsP.h"
#include <string.h>
#include <strings.h>
/* ------------------------------------------------------------------ */
@ -186,6 +187,117 @@ wl_put_back(void *ectx, WMEvent *ev)
ctx->head = prev;
}
/* ------------------------------------------------------------------ */
/* Stubs for new vtable methods (Wayland: not yet implemented) */
/* ------------------------------------------------------------------ */
static Bool wl_grab_keyboard(void *ectx, WNativeWindow w)
{ (void)ectx; (void)w; return False; }
static void wl_ungrab_keyboard(void *ectx) { (void)ectx; }
static void wl_allow_events(void *ectx) { (void)ectx; }
static Bool wl_grab_pointer(void *ectx, WNativeWindow w, WMNativePixmap c)
{ (void)ectx; (void)w; (void)c; return False; }
static void wl_ungrab_pointer(void *ectx) { (void)ectx; }
static WNativeWindow wl_query_pointer(void *ectx, WNativeWindow w,
int *rx, int *ry, int *wx, int *wy, unsigned int *m)
{ (void)ectx; (void)w;
if (rx) *rx = 0; if (ry) *ry = 0;
if (wx) *wx = 0; if (wy) *wy = 0; if (m) *m = 0;
return 0; }
static Bool wl_get_window_geometry(void *ectx, WNativeWindow w,
int *x, int *y, unsigned int *width, unsigned int *height)
{ (void)ectx; (void)w;
if (x) *x = 0; if (y) *y = 0;
if (width) *width = 0; if (height) *height = 0;
return False; }
static void wl_move_window(void *ectx, WNativeWindow w, int x, int y)
{ (void)ectx; (void)w; (void)x; (void)y; }
static WNativeWindow wl_translate_coordinates(void *ectx,
WNativeWindow src, WNativeWindow dst, int sx, int sy, int *dx, int *dy)
{ (void)ectx; (void)src; (void)dst; (void)sx; (void)sy;
if (dx) *dx = 0; if (dy) *dy = 0; return 0; }
static WNativeWindow wl_get_root_window(void *ectx)
{ (void)ectx; return 0; }
static Bool wl_query_tree(void *ectx, WNativeWindow w,
WNativeWindow **children, unsigned int *nc)
{ (void)ectx; (void)w;
if (children) *children = NULL; if (nc) *nc = 0; return False; }
static void wl_get_pointer_control(void *ectx, int *an, int *ad, int *t)
{ (void)ectx; if (an) *an = 2; if (ad) *ad = 1; if (t) *t = 4; }
static void wl_set_pointer_control(void *ectx, int an, int ad, int t)
{ (void)ectx; (void)an; (void)ad; (void)t; }
static int wl_modifier_from_key(void *ectx, const char *key)
{
(void)ectx;
/* Sensible defaults matching common Wayland compositors */
if (strcasecmp(key, "SHIFT") == 0) return 0;
if (strcasecmp(key, "CONTROL") == 0) return 2;
if (strcasecmp(key, "ALT") == 0) return 3;
if (strcasecmp(key, "META") == 0) return 3;
if (strcasecmp(key, "SUPER") == 0) return 6;
if (strcasecmp(key, "HYPER") == 0) return 0;
if (strcasecmp(key, "MOD1") == 0) return 3;
if (strcasecmp(key, "MOD2") == 0) return 4;
if (strcasecmp(key, "MOD3") == 0) return 5;
if (strcasecmp(key, "MOD4") == 0) return 6;
if (strcasecmp(key, "MOD5") == 0) return 7;
return -1;
}
static const char *wl_keysym_to_string(void *ectx, WMNativeKeysym ks)
{ (void)ectx; (void)ks; return NULL; /* TODO: xkb_keysym_get_name */ }
static int wl_get_modifier_keysyms(void *ectx, WMNativeKeysym *out, int max_per_mod)
{ (void)ectx; memset(out, 0, 8 * max_per_mod * sizeof(WMNativeKeysym)); return 0; }
static unsigned int wl_keysym_to_keycode(void *ectx, WMNativeKeysym ks)
{ (void)ectx; (void)ks; return 0; }
static WMNativeKeysym wl_keycode_to_keysym(void *ectx, unsigned int kc, int idx)
{ (void)ectx; (void)kc; (void)idx; return 0; }
static void wl_keysym_convert_case(void *ectx, WMNativeKeysym sym,
WMNativeKeysym *lower, WMNativeKeysym *upper)
{ (void)ectx; if (lower) *lower = sym; if (upper) *upper = sym; }
static void wl_send_wm_command(void *ectx, const char *cmd)
{ (void)ectx; (void)cmd; /* TODO: signal wmaker via PID file */ }
static void wl_set_window_hints(void *ectx, WNativeWindow w,
int minw, int minh, int maxw, int maxh, int bw, int bh)
{ (void)ectx; (void)w; (void)minw; (void)minh; (void)maxw; (void)maxh; (void)bw; (void)bh; }
static void wl_set_window_property_string(void *ectx, WNativeWindow w,
const char *atom, const char *val)
{ (void)ectx; (void)w; (void)atom; (void)val; }
static void wl_set_window_property_data(void *ectx, WNativeWindow w,
WMNativeAtom prop, WMNativeAtom type, int fmt, const void *data, int nel)
{ (void)ectx; (void)w; (void)prop; (void)type; (void)fmt; (void)data; (void)nel; }
static void wl_recolor_cursor(void *ectx, WMNativePixmap c,
unsigned short fr, unsigned short fg, unsigned short fb,
unsigned short br, unsigned short bg, unsigned short bb)
{ (void)ectx; (void)c; (void)fr; (void)fg; (void)fb; (void)br; (void)bg; (void)bb; }
static void wl_set_error_handler(void *ectx, void *h)
{ (void)ectx; (void)h; }
static void wl_restore_error_handler(void *ectx)
{ (void)ectx; }
const W_EventBackend W_EventBackendWL = {
.screen_init = wl_screen_init,
.screen_fini = wl_screen_fini,
@ -197,6 +309,32 @@ const W_EventBackend W_EventBackendWL = {
.fd = wl_fd,
.put_back = wl_put_back,
.post_dispatch = NULL,
.grab_keyboard = wl_grab_keyboard,
.ungrab_keyboard = wl_ungrab_keyboard,
.allow_events = wl_allow_events,
.grab_pointer = wl_grab_pointer,
.ungrab_pointer = wl_ungrab_pointer,
.query_pointer = wl_query_pointer,
.get_window_geometry = wl_get_window_geometry,
.move_window = wl_move_window,
.translate_coordinates = wl_translate_coordinates,
.get_root_window = wl_get_root_window,
.query_tree = wl_query_tree,
.get_pointer_control = wl_get_pointer_control,
.set_pointer_control = wl_set_pointer_control,
.modifier_from_key = wl_modifier_from_key,
.keysym_to_string = wl_keysym_to_string,
.keysym_to_keycode = wl_keysym_to_keycode,
.keycode_to_keysym = wl_keycode_to_keysym,
.keysym_convert_case = wl_keysym_convert_case,
.get_modifier_keysyms = wl_get_modifier_keysyms,
.send_wm_command = wl_send_wm_command,
.set_window_hints = wl_set_window_hints,
.set_window_property_string = wl_set_window_property_string,
.set_window_property_data = wl_set_window_property_data,
.recolor_cursor = wl_recolor_cursor,
.set_error_handler = wl_set_error_handler,
.restore_error_handler = wl_restore_error_handler,
};
/* ------------------------------------------------------------------ */

View File

@ -10,7 +10,10 @@
#include "WINGs/WINGsX11.h"
#include <string.h>
#include <strings.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
/* ------------------------------------------------------------------ */
/* XEvent → WMEvent translation (inline, X11 backend only) */
@ -338,6 +341,405 @@ x11_post_dispatch(void *ectx, WMEvent *ev, W_View *toplevel)
}
}
/* ------------------------------------------------------------------ */
/* Keyboard/pointer grab */
/* ------------------------------------------------------------------ */
static Bool
x11_grab_keyboard(void *ectx, WNativeWindow window)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
int r = XGrabKeyboard(ctx->dpy, (Window)window, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
return (r == GrabSuccess) ? True : False;
}
static void
x11_ungrab_keyboard(void *ectx)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XUngrabKeyboard(ctx->dpy, CurrentTime);
}
static void
x11_allow_events(void *ectx)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XAllowEvents(ctx->dpy, AsyncKeyboard, CurrentTime);
}
static Bool
x11_grab_pointer(void *ectx, WNativeWindow window, WMNativePixmap cursor)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
int r = XGrabPointer(ctx->dpy, (Window)window, True,
ButtonPressMask | ButtonReleaseMask |
ButtonMotionMask | PointerMotionMask,
GrabModeAsync, GrabModeAsync,
None, (Cursor)cursor, CurrentTime);
return (r == GrabSuccess) ? True : False;
}
static void
x11_ungrab_pointer(void *ectx)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XUngrabPointer(ctx->dpy, CurrentTime);
}
static WNativeWindow
x11_query_pointer(void *ectx, WNativeWindow window,
int *root_x, int *root_y,
int *win_x, int *win_y, unsigned int *mask)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
Window root_ret, child_ret;
int rx, ry, wx, wy;
unsigned int m;
XQueryPointer(ctx->dpy, (Window)window, &root_ret, &child_ret,
&rx, &ry, &wx, &wy, &m);
if (root_x) *root_x = rx;
if (root_y) *root_y = ry;
if (win_x) *win_x = wx;
if (win_y) *win_y = wy;
if (mask) *mask = m;
return (WNativeWindow)child_ret;
}
/* ------------------------------------------------------------------ */
/* Window geometry */
/* ------------------------------------------------------------------ */
static Bool
x11_get_window_geometry(void *ectx, WNativeWindow window,
int *x, int *y, unsigned int *width, unsigned int *height)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
Window root;
int xr, yr;
unsigned int w, h, bw, depth;
Status s = XGetGeometry(ctx->dpy, (Window)window, &root,
&xr, &yr, &w, &h, &bw, &depth);
if (!s) return False;
if (x) *x = xr;
if (y) *y = yr;
if (width) *width = w;
if (height) *height = h;
return True;
}
static void
x11_move_window(void *ectx, WNativeWindow window, int x, int y)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XMoveWindow(ctx->dpy, (Window)window, x, y);
}
static WNativeWindow
x11_translate_coordinates(void *ectx, WNativeWindow src, WNativeWindow dst,
int src_x, int src_y, int *dst_x, int *dst_y)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
Window child;
int dx, dy;
XTranslateCoordinates(ctx->dpy, (Window)src, (Window)dst,
src_x, src_y, &dx, &dy, &child);
if (dst_x) *dst_x = dx;
if (dst_y) *dst_y = dy;
return (WNativeWindow)child;
}
static WNativeWindow
x11_get_root_window(void *ectx)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
return (WNativeWindow)DefaultRootWindow(ctx->dpy);
}
static Bool
x11_query_tree(void *ectx, WNativeWindow window,
WNativeWindow **children, unsigned int *nchildren)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
Window root, parent;
Window *kids = NULL;
unsigned int nkids = 0;
if (!XQueryTree(ctx->dpy, (Window)window, &root, &parent, &kids, &nkids)) {
if (children) *children = NULL;
if (nchildren) *nchildren = 0;
return False;
}
if (children) {
if (nkids > 0) {
*children = wmalloc(nkids * sizeof(WNativeWindow));
for (unsigned int i = 0; i < nkids; i++)
(*children)[i] = (WNativeWindow)kids[i];
} else {
*children = NULL;
}
}
if (nchildren) *nchildren = nkids;
if (kids) XFree(kids);
return True;
}
/* ------------------------------------------------------------------ */
/* Pointer control */
/* ------------------------------------------------------------------ */
static void
x11_get_pointer_control(void *ectx, int *accel_num, int *accel_denom, int *threshold)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XGetPointerControl(ctx->dpy, accel_num, accel_denom, threshold);
}
static void
x11_set_pointer_control(void *ectx, int accel_num, int accel_denom, int threshold)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XChangePointerControl(ctx->dpy, True, True, accel_num, accel_denom, threshold);
}
/* ------------------------------------------------------------------ */
/* Modifier mapping */
/* ------------------------------------------------------------------ */
#include <X11/keysym.h>
#include <X11/XKBlib.h>
static int x11_MetaIndex, x11_HyperIndex, x11_SuperIndex, x11_AltIndex, x11_ModeIndex;
static int x11_modmap_done;
static void
x11_compute_modifier_mapping(Display *display)
{
int modifier_index, modifier_key, column, mkpm;
int meta_bit = 0, hyper_bit = 0, super_bit = 0, alt_bit = 0, mode_bit = 0;
XModifierKeymap *xmk = XGetModifierMapping(display);
if (!xmk) return;
mkpm = xmk->max_keypermod;
for (modifier_index = 0; modifier_index < 8; modifier_index++) {
for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
KeyCode code = xmk->modifiermap[modifier_index * mkpm + modifier_key];
if (!code) continue;
for (column = 0; column < 4; column += 2) {
KeySym sym = XkbKeycodeToKeysym(display, code, 0, column);
if (sym == NoSymbol) continue;
switch (sym) {
case XK_Meta_L: case XK_Meta_R: meta_bit = modifier_index; break;
case XK_Super_L: case XK_Super_R: super_bit = modifier_index; break;
case XK_Hyper_L: case XK_Hyper_R: hyper_bit = modifier_index; break;
case XK_Alt_L: case XK_Alt_R: alt_bit = modifier_index; break;
case XK_Mode_switch: mode_bit = modifier_index; break;
default: break;
}
}
}
}
XFreeModifiermap(xmk);
if (!meta_bit && alt_bit) meta_bit = alt_bit, alt_bit = 0;
if (mode_bit) {
if (mode_bit == meta_bit) meta_bit = 0;
else if (mode_bit == hyper_bit) hyper_bit = 0;
else if (mode_bit == super_bit) super_bit = 0;
else if (mode_bit == alt_bit) alt_bit = 0;
}
x11_MetaIndex = meta_bit;
x11_HyperIndex = hyper_bit;
x11_SuperIndex = super_bit;
x11_AltIndex = alt_bit;
x11_ModeIndex = mode_bit;
x11_modmap_done = 1;
}
static int
x11_modifier_from_key(void *ectx, const char *key)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
if (!x11_modmap_done)
x11_compute_modifier_mapping(ctx->dpy);
if (strcasecmp(key, "SHIFT") == 0) return ShiftMapIndex;
if (strcasecmp(key, "CONTROL") == 0) return ControlMapIndex;
if (strcasecmp(key, "ALT") == 0) return x11_AltIndex;
if (strcasecmp(key, "META") == 0) return x11_MetaIndex;
if (strcasecmp(key, "SUPER") == 0) return x11_SuperIndex;
if (strcasecmp(key, "HYPER") == 0) return x11_HyperIndex;
if (strcasecmp(key, "MOD1") == 0) return Mod1MapIndex;
if (strcasecmp(key, "MOD2") == 0) return Mod2MapIndex;
if (strcasecmp(key, "MOD3") == 0) return Mod3MapIndex;
if (strcasecmp(key, "MOD4") == 0) return Mod4MapIndex;
if (strcasecmp(key, "MOD5") == 0) return Mod5MapIndex;
return -1;
}
/* ------------------------------------------------------------------ */
/* Keysym helpers */
/* ------------------------------------------------------------------ */
static int
x11_get_modifier_keysyms(void *ectx, WMNativeKeysym *keysyms_out, int max_per_mod)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XModifierKeymap *xmk = XGetModifierMapping(ctx->dpy);
if (!xmk) return 0;
int mkpm = xmk->max_keypermod;
int out_per_mod = (mkpm < max_per_mod) ? mkpm : max_per_mod;
memset(keysyms_out, 0, 8 * max_per_mod * sizeof(WMNativeKeysym));
for (int j = 0; j < 8; j++) {
int slot = 0;
for (int i = 0; i < mkpm && slot < out_per_mod; i++) {
KeyCode kc = xmk->modifiermap[j * mkpm + i];
if (!kc) continue;
KeySym ks = XkbKeycodeToKeysym(ctx->dpy, kc, 0, 0);
if (ks == NoSymbol) {
ks = XkbKeycodeToKeysym(ctx->dpy, kc, 0, 1);
}
if (ks != NoSymbol) {
keysyms_out[j * max_per_mod + slot] = (WMNativeKeysym)ks;
slot++;
}
}
}
XFreeModifiermap(xmk);
return mkpm;
}
static const char *
x11_keysym_to_string(void *ectx, WMNativeKeysym keysym)
{
(void)ectx;
return XKeysymToString((KeySym)keysym);
}
static unsigned int
x11_keysym_to_keycode(void *ectx, WMNativeKeysym keysym)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
return (unsigned int)XKeysymToKeycode(ctx->dpy, (KeySym)keysym);
}
static WMNativeKeysym
x11_keycode_to_keysym(void *ectx, unsigned int keycode, int index)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
return (WMNativeKeysym)XkbKeycodeToKeysym(ctx->dpy, (KeyCode)keycode, 0, index);
}
static void
x11_keysym_convert_case(void *ectx, WMNativeKeysym sym,
WMNativeKeysym *lower, WMNativeKeysym *upper)
{
(void)ectx;
KeySym lo, up;
XConvertCase((KeySym)sym, &lo, &up);
if (lower) *lower = (WMNativeKeysym)lo;
if (upper) *upper = (WMNativeKeysym)up;
}
/* ------------------------------------------------------------------ */
/* WM notification */
/* ------------------------------------------------------------------ */
static void
x11_send_wm_command(void *ectx, const char *command)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XEvent ev;
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.message_type = XInternAtom(ctx->dpy, "_WINDOWMAKER_COMMAND", False);
ev.xclient.window = DefaultRootWindow(ctx->dpy);
ev.xclient.format = 8;
strncpy(ev.xclient.data.b, command, sizeof(ev.xclient.data.b));
XSendEvent(ctx->dpy, DefaultRootWindow(ctx->dpy), False,
SubstructureRedirectMask, &ev);
XFlush(ctx->dpy);
}
/* ------------------------------------------------------------------ */
/* Window properties */
/* ------------------------------------------------------------------ */
static void
x11_set_window_hints(void *ectx, WNativeWindow window,
int min_w, int min_h, int max_w, int max_h,
int base_w, int base_h)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XSizeHints *hints = XAllocSizeHints();
if (!hints) return;
hints->flags = PMinSize | PMaxSize | PBaseSize;
hints->min_width = min_w; hints->min_height = min_h;
hints->max_width = max_w; hints->max_height = max_h;
hints->base_width = base_w; hints->base_height = base_h;
XSetWMNormalHints(ctx->dpy, (Window)window, hints);
XFree(hints);
}
static void
x11_set_window_property_string(void *ectx, WNativeWindow window,
const char *atom_name, const char *value)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
Atom atom = XInternAtom(ctx->dpy, atom_name, False);
XChangeProperty(ctx->dpy, (Window)window, atom, XA_STRING, 8,
PropModeReplace, (unsigned char *)value, strlen(value));
}
static void
x11_set_window_property_data(void *ectx, WNativeWindow window,
WMNativeAtom property, WMNativeAtom type,
int format, const void *data, int nelements)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XChangeProperty(ctx->dpy, (Window)window, (Atom)property, (Atom)type,
format, PropModeReplace, (const unsigned char *)data, nelements);
}
/* ------------------------------------------------------------------ */
/* Cursor */
/* ------------------------------------------------------------------ */
static void
x11_recolor_cursor(void *ectx, WMNativePixmap cursor,
unsigned short fr, unsigned short fg, unsigned short fb,
unsigned short br, unsigned short bg, unsigned short bb)
{
X11EventCtx *ctx = (X11EventCtx *)ectx;
XColor fg_c, bg_c;
fg_c.red = fr; fg_c.green = fg; fg_c.blue = fb; fg_c.flags = DoRed|DoGreen|DoBlue;
bg_c.red = br; bg_c.green = bg; bg_c.blue = bb; bg_c.flags = DoRed|DoGreen|DoBlue;
XRecolorCursor(ctx->dpy, (Cursor)cursor, &fg_c, &bg_c);
}
/* ------------------------------------------------------------------ */
/* Error handling */
/* ------------------------------------------------------------------ */
static int (*x11_saved_error_handler)(Display *, XErrorEvent *);
static void
x11_set_error_handler(void *ectx, void *handler)
{
(void)ectx;
x11_saved_error_handler = XSetErrorHandler((int (*)(Display *, XErrorEvent *))handler);
}
static void
x11_restore_error_handler(void *ectx)
{
(void)ectx;
XSetErrorHandler(x11_saved_error_handler);
x11_saved_error_handler = NULL;
}
const W_EventBackend W_EventBackendX11 = {
.screen_init = x11_screen_init,
.screen_fini = x11_screen_fini,
@ -349,4 +751,30 @@ const W_EventBackend W_EventBackendX11 = {
.fd = x11_fd,
.put_back = x11_put_back,
.post_dispatch = x11_post_dispatch,
.grab_keyboard = x11_grab_keyboard,
.ungrab_keyboard = x11_ungrab_keyboard,
.allow_events = x11_allow_events,
.grab_pointer = x11_grab_pointer,
.ungrab_pointer = x11_ungrab_pointer,
.query_pointer = x11_query_pointer,
.get_window_geometry = x11_get_window_geometry,
.move_window = x11_move_window,
.translate_coordinates = x11_translate_coordinates,
.get_root_window = x11_get_root_window,
.query_tree = x11_query_tree,
.get_pointer_control = x11_get_pointer_control,
.set_pointer_control = x11_set_pointer_control,
.modifier_from_key = x11_modifier_from_key,
.keysym_to_string = x11_keysym_to_string,
.keysym_to_keycode = x11_keysym_to_keycode,
.keycode_to_keysym = x11_keycode_to_keysym,
.keysym_convert_case = x11_keysym_convert_case,
.get_modifier_keysyms = x11_get_modifier_keysyms,
.send_wm_command = x11_send_wm_command,
.set_window_hints = x11_set_window_hints,
.set_window_property_string = x11_set_window_property_string,
.set_window_property_data = x11_set_window_property_data,
.recolor_cursor = x11_recolor_cursor,
.set_error_handler = x11_set_error_handler,
.restore_error_handler = x11_restore_error_handler,
};

View File

@ -19,15 +19,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h" /* for HAVE_XCONVERTCASE */
#include "config.h"
#include "WPrefs.h"
#include <WINGs/WINGsX11.h>
#include <ctype.h>
#include <X11/keysym.h>
#include <X11/XKBlib.h>
typedef struct _Panel {
WMBox *box;
@ -169,169 +165,66 @@ static struct keyOption {
#endif /* XKB_MODELOCK */
};
#ifndef HAVE_XCONVERTCASE
/* from Xlib */
static void XConvertCase(register WMNativeKeysym sym, WMNativeKeysym * lower, WMNativeKeysym * upper)
static int NumLockMask(WMScreen *scr)
{
*lower = sym;
*upper = sym;
switch (sym >> 8) {
case 0: /* Latin 1 */
if ((sym >= XK_A) && (sym <= XK_Z))
*lower += (XK_a - XK_A);
else if ((sym >= XK_a) && (sym <= XK_z))
*upper -= (XK_a - XK_A);
else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
*lower += (XK_agrave - XK_Agrave);
else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
*upper -= (XK_agrave - XK_Agrave);
else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
*lower += (XK_oslash - XK_Ooblique);
else if ((sym >= XK_oslash) && (sym <= XK_thorn))
*upper -= (XK_oslash - XK_Ooblique);
break;
case 1: /* Latin 2 */
/* Assume the WMNativeKeysym is a legal value (ignore discontinuities) */
if (sym == XK_Aogonek)
*lower = XK_aogonek;
else if (sym >= XK_Lstroke && sym <= XK_Sacute)
*lower += (XK_lstroke - XK_Lstroke);
else if (sym >= XK_Scaron && sym <= XK_Zacute)
*lower += (XK_scaron - XK_Scaron);
else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
*lower += (XK_zcaron - XK_Zcaron);
else if (sym == XK_aogonek)
*upper = XK_Aogonek;
else if (sym >= XK_lstroke && sym <= XK_sacute)
*upper -= (XK_lstroke - XK_Lstroke);
else if (sym >= XK_scaron && sym <= XK_zacute)
*upper -= (XK_scaron - XK_Scaron);
else if (sym >= XK_zcaron && sym <= XK_zabovedot)
*upper -= (XK_zcaron - XK_Zcaron);
else if (sym >= XK_Racute && sym <= XK_Tcedilla)
*lower += (XK_racute - XK_Racute);
else if (sym >= XK_racute && sym <= XK_tcedilla)
*upper -= (XK_racute - XK_Racute);
break;
case 2: /* Latin 3 */
/* Assume the WMNativeKeysym is a legal value (ignore discontinuities) */
if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
*lower += (XK_hstroke - XK_Hstroke);
else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
*lower += (XK_gbreve - XK_Gbreve);
else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
*upper -= (XK_hstroke - XK_Hstroke);
else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
*upper -= (XK_gbreve - XK_Gbreve);
else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
*lower += (XK_cabovedot - XK_Cabovedot);
else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
*upper -= (XK_cabovedot - XK_Cabovedot);
break;
case 3: /* Latin 4 */
/* Assume the WMNativeKeysym is a legal value (ignore discontinuities) */
if (sym >= XK_Rcedilla && sym <= XK_Tslash)
*lower += (XK_rcedilla - XK_Rcedilla);
else if (sym >= XK_rcedilla && sym <= XK_tslash)
*upper -= (XK_rcedilla - XK_Rcedilla);
else if (sym == XK_ENG)
*lower = XK_eng;
else if (sym == XK_eng)
*upper = XK_ENG;
else if (sym >= XK_Amacron && sym <= XK_Umacron)
*lower += (XK_amacron - XK_Amacron);
else if (sym >= XK_amacron && sym <= XK_umacron)
*upper -= (XK_amacron - XK_Amacron);
break;
case 6: /* Cyrillic */
/* Assume the WMNativeKeysym is a legal value (ignore discontinuities) */
if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
*lower -= (XK_Serbian_DJE - XK_Serbian_dje);
else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
*upper += (XK_Serbian_DJE - XK_Serbian_dje);
else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
*lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
*upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
break;
case 7: /* Greek */
/* Assume the WMNativeKeysym is a legal value (ignore discontinuities) */
if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
*lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
sym != XK_Greek_iotaaccentdieresis && sym != XK_Greek_upsilonaccentdieresis)
*upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
*lower += (XK_Greek_alpha - XK_Greek_ALPHA);
else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && sym != XK_Greek_finalsmallsigma)
*upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
break;
case 0x14: /* Armenian */
if (sym >= XK_Armenian_AYB && sym <= XK_Armenian_fe) {
*lower = sym | 1;
*upper = sym & ~1;
}
break;
}
}
#endif
static int NumLockMask(Display *dpy)
{
int i, mask;
XModifierKeymap *map;
int i, j;
static int mask_table[8] = {
WM_MOD_SHIFT, WM_MOD_LOCK, WM_MOD_CONTROL, WM_MOD_MOD1,
WM_MOD_MOD2, WM_MOD_MOD3, WM_MOD_MOD4, WM_MOD_MOD5
};
KeyCode numlock_keycode = XKeysymToKeycode(dpy, XK_Num_Lock);
unsigned int numlock_keycode = scr->eventBackend->keysym_to_keycode(
scr->eventBackendCtx, WMK_Num_Lock);
if (numlock_keycode == NoSymbol)
if (numlock_keycode == 0)
return 0;
map = XGetModifierMapping(dpy);
if (!map)
#define NL_MAX_PER_MOD 16
WMNativeKeysym keysyms[8 * NL_MAX_PER_MOD];
int mkpm = scr->eventBackend->get_modifier_keysyms(scr->eventBackendCtx,
keysyms, NL_MAX_PER_MOD);
if (mkpm == 0)
return 0;
mask = 0;
for (i = 0; i < 8 * map->max_keypermod; i++) {
if (map->modifiermap[i] == numlock_keycode && mask == 0) {
mask = mask_table[i/map->max_keypermod];
break;
for (j = 0; j < 8; j++) {
for (i = 0; i < NL_MAX_PER_MOD; i++) {
WMNativeKeysym ks = keysyms[j * NL_MAX_PER_MOD + i];
if (ks == WMK_Num_Lock)
return mask_table[j];
}
}
if (map)
XFreeModifiermap(map);
return mask;
#undef NL_MAX_PER_MOD
return 0;
}
char *capture_shortcut(WMScreen *scr, Bool *capturing, Bool convert_case)
{
Display *dpy = WMScreenDisplay(scr);
WMEvent ev;
WMNativeKeysym ksym, lksym, uksym;
char buffer[64];
char *key = NULL;
const char *key = NULL;
unsigned int numlock_mask;
while (*capturing) {
XAllowEvents(dpy, AsyncKeyboard, WM_CURRENT_TIME);
scr->eventBackend->allow_events(scr->eventBackendCtx);
WMNextEvent(scr, &ev);
if (ev.type == KeyPress && ev.u.key.keycode != 0) {
numlock_mask = NumLockMask(dpy);
if (ev.type == WME_KEY_PRESS && ev.u.key.keycode != 0) {
numlock_mask = NumLockMask(scr);
/* conditional mask check to get numeric keypad keys */
ksym = W_KeycodeToKeysym(dpy, ev.u.key.keycode, ev.u.key.state & numlock_mask?1:0);
ksym = scr->eventBackend->keycode_to_keysym(
scr->eventBackendCtx, ev.u.key.keycode,
(ev.u.key.state & numlock_mask) ? 1 : 0);
if (!IsModifierKey(ksym)) {
if (!WM_IsModifierKey(ksym)) {
if (convert_case) {
XConvertCase(ksym, &lksym, &uksym);
key = XKeysymToString(uksym);
scr->eventBackend->keysym_convert_case(
scr->eventBackendCtx, ksym, &lksym, &uksym);
key = scr->eventBackend->keysym_to_string(
scr->eventBackendCtx, uksym);
} else {
key = XKeysymToString(ksym);
key = scr->eventBackend->keysym_to_string(
scr->eventBackendCtx, ksym);
}
*capturing = 0;
@ -406,7 +299,6 @@ static void captureClick(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
WMScreen *scr = WMWidgetScreen(panel->parent);
Display *dpy = WMScreenDisplay(scr);
char *shortcut;
if (!panel->capturing) {
@ -414,7 +306,7 @@ static void captureClick(WMWidget * w, void *data)
WMSetButtonText(w, _("Cancel"));
WMSetLabelText(panel->instructionsL,
_("Press the desired shortcut key(s) or click Cancel to stop capturing."));
XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, WM_CURRENT_TIME);
scr->eventBackend->grab_keyboard(scr->eventBackendCtx, WMWidgetXID(panel->parent));
shortcut = capture_shortcut(scr, &panel->capturing, 1);
if (shortcut) {
int key_idx = -1;
@ -448,7 +340,7 @@ static void captureClick(WMWidget * w, void *data)
panel->capturing = 0;
WMSetButtonText(w, _("Capture"));
WMSetLabelText(panel->instructionsL, _("Click on Capture to interactively define the shortcut key."));
XUngrabKeyboard(dpy, WM_CURRENT_TIME);
scr->eventBackend->ungrab_keyboard(scr->eventBackendCtx);
}
static void clearShortcut(WMWidget * w, void *data)
@ -527,7 +419,6 @@ static void paintItem(WMList * lPtr, int index, WMDrawable d, char *text, int st
int width, height, x, y;
_Panel *panel = (_Panel *) WMGetHangedData(lPtr);
WMScreen *scr = WMWidgetScreen(lPtr);
Display *dpy = WMScreenDisplay(scr);
WMColor *backColor = (state & WLDSSelected) ? panel->white : panel->gray;
width = rect->size.width;
@ -535,7 +426,7 @@ static void paintItem(WMList * lPtr, int index, WMDrawable d, char *text, int st
x = rect->pos.x;
y = rect->pos.y;
XFillRectangle(dpy, d, WMColorGC(backColor), x, y, width, height);
scr->renderBackend->fill_rect(scr->renderBackendCtx, d, backColor, x, y, width, height);
if (panel->shortcuts[index]) {
WMPixmap *pix = WMGetSystemPixmap(scr, WSICheckMark);

View File

@ -24,9 +24,6 @@
#include <ctype.h>
#include <unistd.h>
#include <X11/keysym.h>
#include <X11/cursorfont.h>
#include "editmenu.h"
typedef enum {
@ -261,7 +258,7 @@ static void browseForFile(WMWidget * self, void *clientData)
static void sgrabClicked(WMWidget * w, void *data)
{
_Panel *panel = (_Panel *) data;
Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
WMScreen *scr = WMWidgetScreen(panel->parent);
char *shortcut;
if (w == panel->sclearB) {
@ -273,8 +270,8 @@ static void sgrabClicked(WMWidget * w, void *data)
if (!panel->capturing) {
panel->capturing = 1;
WMSetButtonText(w, _("Cancel"));
XGrabKeyboard(dpy, WMWidgetXID(panel->parent), True, WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, WM_CURRENT_TIME);
shortcut = capture_shortcut(WMWidgetScreen(panel->parent), &panel->capturing, 0);
scr->eventBackend->grab_keyboard(scr->eventBackendCtx, WMWidgetXID(panel->parent));
shortcut = capture_shortcut(scr, &panel->capturing, 0);
if (shortcut) {
WMSetTextFieldText(panel->shortT, shortcut);
updateMenuItem(panel, panel->currentItem, panel->shortT);
@ -283,7 +280,7 @@ static void sgrabClicked(WMWidget * w, void *data)
}
panel->capturing = 0;
WMSetButtonText(w, _("Capture"));
XUngrabKeyboard(dpy, WM_CURRENT_TIME);
scr->eventBackend->ungrab_keyboard(scr->eventBackendCtx);
}
static void changedItemPad(WMWidget * w, void *data)
@ -367,33 +364,18 @@ static void createPanel(_Panel * p)
panel->gray = gray;
{
WMNativePixmap pix;
Display *dpy = WMScreenDisplay(scr);
GC gc;
WMPixmap *pixm;
RImage *img;
RColor blk = {0, 0, 0, 255};
pixm = WMCreatePixmap(scr, 7, 7, WMScreenDepth(scr), True);
/* Create a 7x7 crosshair marker icon */
img = RCreateImage(7, 7, True);
RClearImage(img, &(RColor){0, 0, 0, 0});
RDrawLine(img, 0, 3, 6, 3, &blk);
RDrawLine(img, 3, 0, 3, 6, &blk);
pix = WMGetPixmapXID(pixm);
XDrawLine(dpy, pix, WMColorGC(black), 0, 3, 6, 3);
XDrawLine(dpy, pix, WMColorGC(black), 3, 0, 3, 6);
/*
XDrawLine(dpy, pix, WMColorGC(black), 1, 0, 3, 3);
XDrawLine(dpy, pix, WMColorGC(black), 1, 6, 3, 3);
XDrawLine(dpy, pix, WMColorGC(black), 0, 0, 0, 6);
*/
pix = WMGetPixmapMaskXID(pixm);
gc = XCreateGC(dpy, pix, 0, NULL);
XSetForeground(dpy, gc, 0);
XFillRectangle(dpy, pix, gc, 0, 0, 7, 7);
XSetForeground(dpy, gc, 1);
XDrawLine(dpy, pix, gc, 0, 3, 6, 3);
XDrawLine(dpy, pix, gc, 3, 0, 3, 6);
pixm = WMCreatePixmapFromRImage(scr, img, 128);
RReleaseImage(img);
panel->markerPix[ExternalInfo] = pixm;
panel->markerPix[PipeInfo] = pixm;
@ -401,8 +383,6 @@ static void createPanel(_Panel * p)
panel->markerPix[DirectoryInfo] = pixm;
panel->markerPix[WSMenuInfo] = pixm;
panel->markerPix[WWindowListInfo] = pixm;
XFreeGC(dpy, gc);
}
panel->box = WMCreateBox(panel->parent);

View File

@ -22,9 +22,6 @@
#include "WPrefs.h"
#include <X11/Xutil.h>
#include <X11/XKBlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -121,7 +118,6 @@ typedef struct _Panel {
/* need access to the double click variables */
#include <WINGs/WINGsP.h>
#include <WINGs/WINGsX11.h>
static char *modifierNames[8];
@ -135,7 +131,7 @@ static void setMouseAccel(WMScreen * scr, float accel, int threshold)
d = 10;
n = accel * d;
XChangePointerControl(WMScreenDisplay(scr), True, True, n, d, threshold);
scr->eventBackend->set_pointer_control(scr->eventBackendCtx, n, d, threshold);
}
static void speedChange(WMWidget * w, void *data)
@ -253,11 +249,11 @@ static int getWheelAction(const char *str)
return -1;
}
static void getMouseParameters(Display * dpy, float *accel, int *thre)
static void getMouseParameters(WMScreen *scr, float *accel, int *thre)
{
int n, d;
XGetPointerControl(dpy, &n, &d, thre);
scr->eventBackend->get_pointer_control(scr->eventBackendCtx, &n, &d, thre);
*accel = (float)n / (float)d;
}
@ -269,7 +265,7 @@ static void showData(_Panel * panel)
int a = -1, b = -1;
float accel;
char buffer[32];
Display *dpy = WMScreenDisplay(WMWidgetScreen(panel->parent));
WMScreen *scr = WMWidgetScreen(panel->parent);
for (i = 0; i < wlengthof(button_list); i++) {
int action;
@ -291,8 +287,8 @@ static void showData(_Panel * panel)
WMSetButtonSelected(panel->disaB, GetBoolForKey("DisableWSMouseActions"));
toggle_disabling_of_mouse_actions(panel->disaB, panel);
/**/ getMouseParameters(dpy, &accel, &a);
panel->maxThreshold = WidthOfScreen(DefaultScreenOfDisplay(dpy));
/**/ getMouseParameters(scr, &accel, &a);
panel->maxThreshold = WMScreenWidth(scr);
if (a > panel->maxThreshold) {
panel->maxThreshold = a;
}
@ -348,15 +344,17 @@ static void showData(_Panel * panel)
static void fillModifierPopUp(WMPopUpButton * pop)
{
XModifierKeymap *mapping;
Display *dpy = WMScreenDisplay(WMWidgetScreen(pop));
int i, j;
WMScreen *scr = WMWidgetScreen(pop);
int j, i, k;
char *str;
char buffer[64];
#define MAX_KEYS_PER_MOD 8
WMNativeKeysym keysyms[8 * MAX_KEYS_PER_MOD];
int mkpm;
mapping = XGetModifierMapping(dpy);
if (!mapping || mapping->max_keypermod == 0) {
mkpm = scr->eventBackend->get_modifier_keysyms(scr->eventBackendCtx,
keysyms, MAX_KEYS_PER_MOD);
if (mkpm == 0) {
WMAddPopUpButtonItem(pop, "Mod1");
WMAddPopUpButtonItem(pop, "Mod2");
WMAddPopUpButtonItem(pop, "Mod3");
@ -367,33 +365,18 @@ static void fillModifierPopUp(WMPopUpButton * pop)
}
for (j = 0; j < 8; j++) {
int idx;
char *array[8];
int a;
WMNativeKeysym ksym;
int k;
char *ptr;
char *tmp;
int a = 0;
char *ptr, *tmp;
a = 0;
memset(array, 0, sizeof(char *) * 8);
for (i = 0; i < mapping->max_keypermod; i++) {
idx = i + j * mapping->max_keypermod;
if (mapping->modifiermap[idx] != 0) {
int l;
for (l = 0; l < 4; l++) {
ksym = W_KeycodeToKeysym(dpy, mapping->modifiermap[idx], l);
if (ksym != NoSymbol)
break;
}
if (ksym != NoSymbol)
str = XKeysymToString(ksym);
else
str = NULL;
if (str && !strstr(str, "_Lock") && !strstr(str, "Shift")
&& !strstr(str, "Control")) {
array[a++] = wstrdup(str);
}
memset(array, 0, sizeof(array));
for (i = 0; i < MAX_KEYS_PER_MOD; i++) {
WMNativeKeysym ksym = keysyms[j * MAX_KEYS_PER_MOD + i];
if (ksym == 0) continue;
str = (char *)scr->eventBackend->keysym_to_string(scr->eventBackendCtx, ksym);
if (str && !strstr(str, "_Lock") && !strstr(str, "Shift")
&& !strstr(str, "Control")) {
array[a++] = wstrdup(str);
}
}
@ -402,17 +385,13 @@ static void fillModifierPopUp(WMPopUpButton * pop)
continue;
tmp = wstrdup(array[k]);
ptr = strstr(tmp, "_L");
if (ptr)
*ptr = 0;
if (ptr) *ptr = 0;
ptr = strstr(tmp, "_R");
if (ptr)
*ptr = 0;
if (ptr) *ptr = 0;
sprintf(buffer, "%s (%s)", modifierNames[j], tmp);
/*sprintf(buffer, "%s", tmp); */
WMAddPopUpButtonItem(pop, buffer);
for (i = k + 1; i < a; i++) {
if (array[i] == NULL)
continue;
if (array[i] == NULL) continue;
if (strstr(array[i], tmp)) {
wfree(array[i]);
array[i] = NULL;
@ -427,9 +406,7 @@ static void fillModifierPopUp(WMPopUpButton * pop)
wfree(array[a]);
}
}
if (mapping)
XFreeModifiermap(mapping);
#undef MAX_KEYS_PER_MOD
}
static void createPanel(Panel * p)

View File

@ -24,11 +24,6 @@
#include "WPrefs.h"
#include <assert.h>
#ifdef USE_X11_BACKEND
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#endif
#ifdef HAVE_STDNORETURN
#include <stdnoreturn.h>
#endif
@ -132,39 +127,10 @@ static void save(WMWidget * w, void *data)
WMWritePropListToFile(WindowMakerDB, WindowMakerDBPath);
/* Tell the running wmaker to reconfigure. On X11 this sends a
* _WINDOWMAKER_COMMAND ClientMessage; on Wayland we use the
* WINGs screen flush (which triggers a wl_display_flush) and
* rely on wmaker's file-watch or SIGUSR1 mechanism. */
#ifdef USE_X11_BACKEND
{
Display *dpy = WMScreenDisplay(WMWidgetScreen(w));
XEvent ev;
memset(&ev, 0, sizeof(XEvent));
ev.xclient.type = ClientMessage;
ev.xclient.message_type = XInternAtom(dpy, "_WINDOWMAKER_COMMAND", False);
ev.xclient.window = DefaultRootWindow(dpy);
ev.xclient.format = 8;
strncpy(ev.xclient.data.b, "Reconfigure", sizeof(ev.xclient.data.b));
XSendEvent(dpy, DefaultRootWindow(dpy), False,
SubstructureRedirectMask, &ev);
XFlush(dpy);
WMScreen *scr = WMWidgetScreen(w);
scr->eventBackend->send_wm_command(scr->eventBackendCtx, "Reconfigure");
}
#else
/* Wayland: signal wmaker to re-read config. */
{
/* Find wmaker's PID from the lock file and send SIGUSR1. */
char pidfile[256];
snprintf(pidfile, sizeof(pidfile), "/tmp/wmaker-%d.pid", getuid());
FILE *f = fopen(pidfile, "r");
if (f) {
pid_t pid;
if (fscanf(f, "%d", &pid) == 1 && pid > 0)
kill(pid, SIGUSR1);
fclose(f);
}
}
#endif
}
static void undo(WMWidget * w, void *data)

View File

@ -36,6 +36,19 @@
/* Needed for HAVE_LIBINTL_H and EXTENDED_WINDOWSHORTCUT */
#include "../src/wconfig.h"
/* Backend-neutral keysym constants (values match X11/xkbcommon) */
#define WMK_Shift_L 0xffe1UL
#define WMK_Hyper_R 0xffeeUL
#define WMK_Mode_switch 0xff7eUL
#define WMK_Num_Lock 0xff7fUL
#define WMK_ISO_Lock 0xfe01UL
#define WMK_ISO_Level5_Lock 0xfe13UL
#define WM_IsModifierKey(ks) \
(((ks) >= WMK_Shift_L && (ks) <= WMK_Hyper_R) || \
((ks) >= WMK_ISO_Lock && (ks) <= WMK_ISO_Level5_Lock) || \
(ks) == WMK_Mode_switch || (ks) == WMK_Num_Lock)
/*
* The macro 'wlengthof' should be used as much as possible, this macro
* is reserved for the cases where wlengthof cannot be used because the

View File

@ -192,7 +192,7 @@ static void paintEditMenuItem(WEditMenuItem * iPtr)
color = scr->white;
}
XClearWindow(scr->display, win);
scr->renderBackend->fill_rect(scr->renderBackendCtx, win, scr->white, 0, 0, w, h);
W_DrawRelief(scr, win, 0, 0, w + 1, h, WRRaised);
@ -204,9 +204,9 @@ static void paintEditMenuItem(WEditMenuItem * iPtr)
WMDrawPixmap(iPtr->pixmap, win, w - size.width - 5, (h - size.height) / 2);
} else if (iPtr->submenu) {
/* draw the cascade indicator */
XDrawLine(scr->display, win, WMColorGC(scr->darkGray), w - 11, 6, w - 6, h / 2 - 1);
XDrawLine(scr->display, win, WMColorGC(scr->white), w - 11, h - 8, w - 6, h / 2 - 1);
XDrawLine(scr->display, win, WMColorGC(scr->black), w - 12, 6, w - 12, h - 8);
scr->renderBackend->draw_line(scr->renderBackendCtx, win, scr->darkGray, w - 11, 6, w - 6, h / 2 - 1);
scr->renderBackend->draw_line(scr->renderBackendCtx, win, scr->white, w - 11, h - 8, w - 6, h / 2 - 1);
scr->renderBackend->draw_line(scr->renderBackendCtx, win, scr->black, w - 12, 6, w - 12, h - 8);
}
}
@ -325,8 +325,8 @@ static void writeGNUstepWMAttr(WMScreen * scr, WNativeWindow window, GNUstepWMAt
data[6] = attr->miniaturize_mask;
data[7] = attr->close_mask;
data[8] = attr->extra_flags;
XChangeProperty(scr->display, window, scr->attribsAtom, scr->attribsAtom,
32, PropModeReplace, (unsigned char *)data, 9);
scr->eventBackend->set_window_property_data(scr->eventBackendCtx, window,
scr->attribsAtom, scr->attribsAtom, 32, (unsigned char *)data, 9);
}
static void realizeObserver(void *self, WMNotification * not)
@ -649,17 +649,12 @@ void WEditMenuUnhide(WEditMenu * mPtr)
void WEditMenuShowAt(WEditMenu * menu, int x, int y)
{
XSizeHints *hints;
hints = XAllocSizeHints();
hints->flags = USPosition;
hints->x = x;
hints->y = y;
WMScreen *scr = W_VIEW_SCREEN(menu->view);
WMMoveWidget(menu, x, y);
XSetWMNormalHints(W_VIEW_DISPLAY(menu->view), W_VIEW_DRAWABLE(menu->view), hints);
XFree(hints);
/* Set USPosition hint so the WM respects our placement */
scr->eventBackend->set_window_hints(scr->eventBackendCtx,
W_VIEW_DRAWABLE(menu->view), 0, 0, 0, 0, x, y);
WMMapWidget(menu);
}
@ -913,7 +908,7 @@ static void editItemLabel(WEditMenuItem * item)
/* -------------------------------------------------- */
static void slideWindow(Display * dpy, WNativeWindow win, int srcX, int srcY, int dstX, int dstY)
static void slideWindow(WMScreen *scr, WNativeWindow win, int srcX, int srcY, int dstX, int dstY)
{
double x, y, dx, dy;
int i;
@ -928,8 +923,8 @@ static void slideWindow(Display * dpy, WNativeWindow win, int srcX, int srcY, in
dy = (double)(dstY - srcY) / iterations;
for (i = 0; i <= iterations; i++) {
XMoveWindow(dpy, win, x, y);
XFlush(dpy);
scr->eventBackend->move_window(scr->eventBackendCtx, win, x, y);
scr->eventBackend->flush(scr->eventBackendCtx, False);
wusleep(800);
@ -938,27 +933,21 @@ static void slideWindow(Display * dpy, WNativeWindow win, int srcX, int srcY, in
}
}
static int errorHandler(Display * d, XErrorEvent * ev)
static int errorHandler(void)
{
/* Parameter not used, but tell the compiler that it is ok */
(void) d;
(void) ev;
/* just ignore */
return 0;
}
static WEditMenu *findMenuInWindow(Display * dpy, WNativeWindow toplevel, int x, int y)
static WEditMenu *findMenuInWindow(WMScreen *scr, WNativeWindow toplevel, int x, int y)
{
WNativeWindow foo, bar;
WNativeWindow *children;
unsigned nchildren;
int i;
WEditMenu *menu;
WMView *view;
int (*oldHandler) (Display *, XErrorEvent *);
view = W_GetViewForXWindow(dpy, toplevel);
view = W_GetViewForXWindow(scr->display, toplevel);
if (view && view->self && WMWidgetClass(view->self) == EditMenuClass) {
menu = (WEditMenu *) view->self;
if (menu->flags.acceptsDrop) {
@ -966,34 +955,34 @@ static WEditMenu *findMenuInWindow(Display * dpy, WNativeWindow toplevel, int x,
}
}
if (!XQueryTree(dpy, toplevel, &foo, &bar, &children, &nchildren) || children == NULL) {
scr->eventBackend->set_error_handler(scr->eventBackendCtx, NULL);
if (!scr->eventBackend->query_tree(scr->eventBackendCtx, toplevel, &children, &nchildren)
|| children == NULL) {
scr->eventBackend->restore_error_handler(scr->eventBackendCtx);
return NULL;
}
oldHandler = XSetErrorHandler(errorHandler);
/* first window that contains the point is the one */
for (i = nchildren - 1; i >= 0; i--) {
XWindowAttributes attr;
int cx, cy;
unsigned int cw, ch;
if (XGetWindowAttributes(dpy, children[i], &attr)
&& attr.map_state == IsViewable
&& x >= attr.x && y >= attr.y && x < attr.x + attr.width && y < attr.y + attr.height) {
WNativeWindow tmp;
if (scr->eventBackend->get_window_geometry(scr->eventBackendCtx, children[i],
&cx, &cy, &cw, &ch)
&& x >= cx && y >= cy && x < cx + (int)cw && y < cy + (int)ch) {
tmp = children[i];
menu = findMenuInWindow(dpy, tmp, x - attr.x, y - attr.y);
menu = findMenuInWindow(scr, children[i], x - cx, y - cy);
if (menu) {
XFree(children);
wfree(children);
scr->eventBackend->restore_error_handler(scr->eventBackendCtx);
return menu;
}
}
}
XSetErrorHandler(oldHandler);
XFree(children);
scr->eventBackend->restore_error_handler(scr->eventBackendCtx);
wfree(children);
return NULL;
}
@ -1004,7 +993,7 @@ static void handleDragOver(WEditMenu *menu, WMView *view, WEditMenuItem *item, i
int mx, my;
int offs;
XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my, &blaw);
scr->eventBackend->translate_coordinates(scr->eventBackendCtx, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my);
offs = menu->flags.standalone ? 0 : 1;
@ -1022,7 +1011,7 @@ static void handleItemDrop(WEditMenu *menu, WEditMenuItem *item, int y)
int mx, my;
int index;
XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my, &blaw);
scr->eventBackend->translate_coordinates(scr->eventBackendCtx, W_VIEW_DRAWABLE(menu->view), scr->rootWin, 0, 0, &mx, &my);
index = y - my;
if (menu->flags.isTitled) {
@ -1061,16 +1050,15 @@ static void dragMenu(WEditMenu * menu)
unsigned blau;
WNativeWindow blaw;
XGetGeometry(scr->display, W_VIEW_DRAWABLE(menu->view), &blaw, &dx, &dy, &blau, &blau, &blau, &blau);
scr->eventBackend->get_window_geometry(scr->eventBackendCtx,
W_VIEW_DRAWABLE(menu->view), &dx, &dy, &blau, &blau);
XTranslateCoordinates(scr->display, W_VIEW_DRAWABLE(menu->view), scr->rootWin, dx, dy, &dx, &dy, &blaw);
scr->eventBackend->translate_coordinates(scr->eventBackendCtx, W_VIEW_DRAWABLE(menu->view), scr->rootWin, dx, dy, &dx, &dy);
dx = menu->dragX - dx;
dy = menu->dragY - dy;
XGrabPointer(scr->display, scr->rootWin, False,
WM_EVMASK_BUTTON_RELEASE | WM_EVMASK_BUTTON_MOTION,
WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, WM_NATIVE_NONE, scr->defaultCursor, WM_CURRENT_TIME);
scr->eventBackend->grab_pointer(scr->eventBackendCtx, scr->rootWin, scr->defaultCursor);
if (menu->parent)
WTearOffEditMenu(menu->parent, menu);
@ -1104,7 +1092,7 @@ static void dragMenu(WEditMenu * menu)
}
}
XUngrabPointer(scr->display, WM_CURRENT_TIME);
scr->eventBackend->ungrab_pointer(scr->eventBackendCtx);
}
static WEditMenuItem *duplicateItem(WEditMenuItem * item)
@ -1154,10 +1142,10 @@ static WEditMenu *duplicateMenu(WEditMenu * menu)
static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
{
static XColor black = { 0, 0, 0, 0, DoRed | DoGreen | DoBlue, 0 };
static XColor green = { 0x0045b045, 0x4500, 0xb000, 0x4500, DoRed | DoGreen | DoBlue, 0 };
static XColor back = { 0, 0xffff, 0xffff, 0xffff, DoRed | DoGreen | DoBlue, 0 };
Display *dpy = W_VIEW_DISPLAY(menu->view);
static struct { unsigned short red, green, blue; } black = { 0, 0, 0 };
static struct { unsigned short red, green, blue; } green = { 0x4500, 0xb000, 0x4500 };
static struct { unsigned short red, green, blue; } back = { 0xffff, 0xffff, 0xffff };
WMScreen *scr = W_VIEW_SCREEN(menu->view);
int x = 0, y = 0;
int dx, dy;
@ -1185,7 +1173,7 @@ static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
win = scr->rootWin;
XTranslateCoordinates(dpy, W_VIEW_DRAWABLE(item->view), win, 0, 0, &orix, &oriy, &blaw);
scr->eventBackend->translate_coordinates(scr->eventBackendCtx, W_VIEW_DRAWABLE(item->view), win, 0, 0, &orix, &oriy);
dview = W_CreateUnmanagedTopView(scr);
W_SetViewBackgroundColor(dview, scr->black);
@ -1209,12 +1197,11 @@ static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
dx = menu->dragX - orix;
dy = menu->dragY - oriy;
XGrabPointer(dpy, scr->rootWin, False,
WM_EVMASK_BUTTON_PRESS | WM_EVMASK_BUTTON_RELEASE | WM_EVMASK_BUTTON_MOTION,
WM_GRAB_MODE_ASYNC, WM_GRAB_MODE_ASYNC, WM_NATIVE_NONE, scr->defaultCursor, WM_CURRENT_TIME);
scr->eventBackend->grab_pointer(scr->eventBackendCtx, scr->rootWin, scr->defaultCursor);
if (menu->flags.acceptsDrop)
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
scr->eventBackend->recolor_cursor(scr->eventBackendCtx, scr->defaultCursor,
green.red, green.green, green.blue, back.red, back.green, back.blue);
while (!done) {
WMEvent ev;
@ -1235,22 +1222,22 @@ static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
}
}
XQueryPointer(dpy, win, &blaw, &blaw, &blai, &blai, &x, &y, &blau);
scr->eventBackend->query_pointer(scr->eventBackendCtx, win, NULL, NULL, &x, &y, NULL);
dmenu = findMenuInWindow(dpy, win, x, y);
dmenu = findMenuInWindow(scr, win, x, y);
if (dmenu) {
handleDragOver(dmenu, dview, dritem, y - dy);
if (!enteredMenu) {
enteredMenu = True;
XRecolorCursor(dpy, scr->defaultCursor, &green, &back);
scr->eventBackend->recolor_cursor(scr->eventBackendCtx, scr->defaultCursor, green.red, green.green, green.blue, back.red, back.green, back.blue);
}
} else {
if (enteredMenu) {
W_ResizeView(dview, oldSize.width, oldSize.height);
W_ResizeView(dritem->view, oldSize.width, oldSize.height);
enteredMenu = False;
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
scr->eventBackend->recolor_cursor(scr->eventBackendCtx, scr->defaultCursor, black.red, black.green, black.blue, back.red, back.green, back.blue);
}
W_MoveView(dview, x - dx, y - dy);
}
@ -1266,9 +1253,9 @@ static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
break;
}
}
XRecolorCursor(dpy, scr->defaultCursor, &black, &back);
scr->eventBackend->recolor_cursor(scr->eventBackendCtx, scr->defaultCursor, black.red, black.green, black.blue, back.red, back.green, back.blue);
XUngrabPointer(dpy, WM_CURRENT_TIME);
scr->eventBackend->ungrab_pointer(scr->eventBackendCtx);
if (!enteredMenu) {
Bool rem = True;
@ -1282,7 +1269,7 @@ static void dragItem(WEditMenu * menu, WEditMenuItem * item, Bool copy)
}
if (!rem || menu->flags.isFactory || copy) {
slideWindow(dpy, W_VIEW_DRAWABLE(dview), x - dx, y - dy, orix, oriy);
slideWindow(scr, W_VIEW_DRAWABLE(dview), x - dx, y - dy, orix, oriy);
if (!menu->flags.isFactory && !copy) {
WRemoveEditMenuItem(menu, dritem);

View File

@ -26,10 +26,6 @@
#include <locale.h>
#ifdef USE_X11_BACKEND
#include <X11/Xlocale.h>
#endif
#include <sys/wait.h>
#include <unistd.h>
@ -137,19 +133,6 @@ int main(int argc, char **argv)
bindtextdomain("WPrefs", LOCALEDIR);
bind_textdomain_codeset("WPrefs", "UTF-8");
textdomain("WPrefs");
/* X11 locale checks only meaningful in X11 mode. In Wayland mode
* locale handling is delegated to xkbcommon / glib. */
#ifdef USE_X11_BACKEND
if (!getenv("WAYLAND_DISPLAY") || getenv("DISPLAY")) {
if (!XSupportsLocale()) {
wwarning(_("X server does not support locale"));
}
if (XSetLocaleModifiers("") == NULL) {
wwarning(_("cannot set locale modifiers"));
}
}
#endif
#endif
/* WMOpenScreen autodetects Wayland-client mode (WAYLAND_DISPLAY set

View File

@ -1,346 +1,18 @@
/* Grok X modifier mappings for shortcuts.
Most of this code was taken from src/event-Xt.c in XEmacs 20.3-b17.
The copyright(s) from the original XEmacs code are included below.
Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997. */
/*
* More changes for WPrefs by Alfredo Kojima, Aug 1998
/* Modifier mapping for WPrefs shortcut panels.
*
* Delegates to the event backend's modifier_from_key() vtable method,
* which probes the actual modifier mapping on X11 (via XGetModifierMapping)
* or returns sensible defaults on Wayland.
*
* Originally based on src/event-Xt.c in XEmacs 20.3-b17.
* Perpetrator: Sudish Joseph <sj@eng.mindspring.net>, Sept. 1997.
* More changes for WPrefs by Alfredo Kojima, Aug 1998.
* Refactored to backend-neutral vtable dispatch, 2026.
*/
/* The event_stream interface for X11 with Xt, and/or tty frames.
Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Copyright (C) 1995 Sun Microsystems, Inc.
Copyright (C) 1996 Ben Wing.
This file is part of XEmacs.
XEmacs is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
XEmacs is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with XEmacs; see the file COPYING. if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA. */
#include <string.h>
#include <strings.h>
#include "../src/wconfig.h"
#ifdef USE_X11_BACKEND
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/XKBlib.h>
#include <WINGs/WINGsX11.h>
#endif
#include <WINGs/WUtil.h>
#include "WPrefs.h"
/************************************************************************/
/* keymap handling */
/************************************************************************/
/* Modifier index results — populated by x_reset_modifier_mapping on X11,
* or left at defaults (Mod1=Alt=Meta, Mod4=Super) on Wayland. */
/* X11 modifier map indices — values match <X11/X.h>. */
#ifndef ShiftMapIndex
#define ShiftMapIndex 0
#define LockMapIndex 1
#define ControlMapIndex 2
#define Mod1MapIndex 3
#define Mod2MapIndex 4
#define Mod3MapIndex 5
#define Mod4MapIndex 6
#define Mod5MapIndex 7
#endif
static int MetaIndex = Mod1MapIndex;
static int HyperIndex = 0;
static int SuperIndex = Mod4MapIndex;
static int AltIndex = Mod1MapIndex;
static int ModeIndex = 0;
#ifdef USE_X11_BACKEND
/* X bogusly doesn't define the interpretations of any bits besides
ModControl, ModShift, and ModLock; so the Interclient Communication
Conventions Manual says that we have to bend over backwards to figure
out what the other modifier bits mean. According to ICCCM:
- Any keycode which is assigned ModControl is a "control" key.
- Any modifier bit which is assigned to a keycode which generates Meta_L
or Meta_R is the modifier bit meaning "meta". Likewise for Super, Hyper,
etc.
- Any keypress event which contains ModControl in its state should be
interpreted as a "control" character.
- Any keypress event which contains a modifier bit in its state which is
generated by a keycode whose corresponding keysym is Meta_L or Meta_R
should be interpreted as a "meta" character. Likewise for Super, Hyper,
etc.
- It is illegal for a keysym to be associated with more than one modifier
bit.
This means that the only thing that emacs can reasonably interpret as a
"meta" key is a key whose keysym is Meta_L or Meta_R, and which generates
one of the modifier bits Mod1-Mod5.
Unfortunately, many keyboards don't have Meta keys in their default
configuration. So, if there are no Meta keys, but there are "Alt" keys,
emacs will interpret Alt as Meta. If there are both Meta and Alt keys,
then the Meta keys mean "Meta", and the Alt keys mean "Alt" (it used to
mean "Symbol," but that just confused the hell out of way too many people).
This works with the default configurations of the 19 keyboard-types I've
checked.
Emacs detects keyboard configurations which violate the above rules, and
prints an error message on the standard-error-output. (Perhaps it should
use a pop-up-window instead.)
*/
static const char *index_to_name(int indice)
{
switch (indice) {
case ShiftMapIndex:
return "ModShift";
case LockMapIndex:
return "ModLock";
case ControlMapIndex:
return "ModControl";
case Mod1MapIndex:
return "Mod1";
case Mod2MapIndex:
return "Mod2";
case Mod3MapIndex:
return "Mod3";
case Mod4MapIndex:
return "Mod4";
case Mod5MapIndex:
return "Mod5";
default:
return "???";
}
}
static void x_reset_modifier_mapping(Display * display)
{
int modifier_index, modifier_key, column, mkpm;
int meta_bit = 0;
int hyper_bit = 0;
int super_bit = 0;
int alt_bit = 0;
int mode_bit = 0;
XModifierKeymap *x_modifier_keymap;
#define modwarn(name,old,other) \
wwarning(_("%s (0x%x) generates %s which is generated by %s"), \
name, code, index_to_name (old), other)
#define modbarf(name,other) \
wwarning(_("%s (0x%x) generates %s which is nonsensical"), \
name, code, other)
#define check_modifier(name,mask) \
if ((1<<modifier_index) != mask) \
wwarning(_("%s (0x%x) generates %s which is nonsensical"), \
name, code, index_to_name (modifier_index))
#define store_modifier(name,old) \
if (old && old != modifier_index) \
wwarning(_("%s (0x%x) generates both %s and %s which is nonsensical"), \
name, code, index_to_name (old), \
index_to_name (modifier_index)); \
if (modifier_index == ShiftMapIndex) modbarf (name,"ModShift"); \
else if (modifier_index == LockMapIndex) modbarf (name,"ModLock"); \
else if (modifier_index == ControlMapIndex) modbarf (name,"ModControl"); \
else if (sym == XK_Mode_switch) \
mode_bit = modifier_index; /* Mode_switch is special, see below... */ \
else if (modifier_index == meta_bit && old != meta_bit) \
modwarn (name, meta_bit, "Meta"); \
else if (modifier_index == super_bit && old != super_bit) \
modwarn (name, super_bit, "Super"); \
else if (modifier_index == hyper_bit && old != hyper_bit) \
modwarn (name, hyper_bit, "Hyper"); \
else if (modifier_index == alt_bit && old != alt_bit) \
modwarn (name, alt_bit, "Alt"); \
else \
old = modifier_index;
x_modifier_keymap = XGetModifierMapping(display);
if (x_modifier_keymap == NULL) {
wwarning(_("XGetModifierMapping returned NULL, there is no modifier or no memory"));
return;
}
mkpm = x_modifier_keymap->max_keypermod;
for (modifier_index = 0; modifier_index < 8; modifier_index++)
for (modifier_key = 0; modifier_key < mkpm; modifier_key++) {
WMNativeKeysym last_sym = 0;
for (column = 0; column < 4; column += 2) {
KeyCode code = x_modifier_keymap->modifiermap[modifier_index * mkpm
+ modifier_key];
WMNativeKeysym sym;
if (code) {
sym = W_KeycodeToKeysym(display, code, column);
} else {
sym = NoSymbol;
}
if (sym == last_sym)
continue;
last_sym = sym;
switch (sym) {
case XK_Mode_switch:
store_modifier("Mode_switch", mode_bit);
break;
case XK_Meta_L:
store_modifier("Meta_L", meta_bit);
break;
case XK_Meta_R:
store_modifier("Meta_R", meta_bit);
break;
case XK_Super_L:
store_modifier("Super_L", super_bit);
break;
case XK_Super_R:
store_modifier("Super_R", super_bit);
break;
case XK_Hyper_L:
store_modifier("Hyper_L", hyper_bit);
break;
case XK_Hyper_R:
store_modifier("Hyper_R", hyper_bit);
break;
case XK_Alt_L:
store_modifier("Alt_L", alt_bit);
break;
case XK_Alt_R:
store_modifier("Alt_R", alt_bit);
break;
case XK_Control_L:
check_modifier("Control_L", WM_MOD_CONTROL);
break;
case XK_Control_R:
check_modifier("Control_R", WM_MOD_CONTROL);
break;
case XK_Shift_L:
check_modifier("Shift_L", WM_MOD_SHIFT);
break;
case XK_Shift_R:
check_modifier("Shift_R", WM_MOD_SHIFT);
break;
case XK_Shift_Lock:
check_modifier("Shift_Lock", WM_MOD_LOCK);
break;
case XK_Caps_Lock:
check_modifier("Caps_Lock", WM_MOD_LOCK);
break;
/* It probably doesn't make any sense for a modifier bit to be
assigned to a key that is not one of the above, but OpenWindows
assigns modifier bits to a couple of random function keys for
no reason that I can discern, so printing a warning here would
be annoying. */
}
}
}
#undef store_modifier
#undef check_modifier
#undef modwarn
#undef modbarf
/* If there was no Meta key, then try using the Alt key instead.
If there is both a Meta key and an Alt key, then the Alt key
is not disturbed and remains an Alt key. */
if (!meta_bit && alt_bit)
meta_bit = alt_bit, alt_bit = 0;
/* mode_bit overrides everything, since it's processed down inside of
XLookupString() instead of by us. If Meta and Mode_switch both
generate the same modifier bit (which is an error), then we don't
interpret that bit as Meta, because we can't make XLookupString()
not interpret it as Mode_switch; and interpreting it as both would
be totally wrong. */
if (mode_bit) {
const char *warn = 0;
if (mode_bit == meta_bit)
warn = "Meta", meta_bit = 0;
else if (mode_bit == hyper_bit)
warn = "Hyper", hyper_bit = 0;
else if (mode_bit == super_bit)
warn = "Super", super_bit = 0;
else if (mode_bit == alt_bit)
warn = "Alt", alt_bit = 0;
if (warn) {
wwarning(_("%s is being used for both %s and %s"),
index_to_name(mode_bit), "Mode_switch", warn);
}
}
MetaIndex = meta_bit;
HyperIndex = hyper_bit;
SuperIndex = super_bit;
AltIndex = alt_bit;
ModeIndex = mode_bit;
XFreeModifiermap(x_modifier_keymap);
}
#endif /* USE_X11_BACKEND */
int ModifierFromKey(WMScreen *scr, const char *key)
{
#ifdef USE_X11_BACKEND
Display *dpy = WMScreenDisplay(scr);
static int eqw = 0;
if (!eqw)
x_reset_modifier_mapping(dpy);
eqw = 1;
#else
(void)scr;
#endif
if (strcasecmp(key, "SHIFT") == 0)
return ShiftMapIndex;
else if (strcasecmp(key, "CONTROL") == 0)
return ControlMapIndex;
else if (strcasecmp(key, "ALT") == 0)
return AltIndex;
else if (strcasecmp(key, "META") == 0)
return MetaIndex;
else if (strcasecmp(key, "SUPER") == 0)
return SuperIndex;
else if (strcasecmp(key, "HYPER") == 0)
return HyperIndex;
else if (strcasecmp(key, "MOD1") == 0)
return Mod1MapIndex;
else if (strcasecmp(key, "MOD2") == 0)
return Mod2MapIndex;
else if (strcasecmp(key, "MOD3") == 0)
return Mod3MapIndex;
else if (strcasecmp(key, "MOD4") == 0)
return Mod4MapIndex;
else if (strcasecmp(key, "MOD5") == 0)
return Mod5MapIndex;
else
return -1;
return scr->eventBackend->modifier_from_key(scr->eventBackendCtx, key);
}