diff --git a/WINGs/WINGs/WINGsP.h.in b/WINGs/WINGs/WINGsP.h.in index 2b26ae5..9d77a35 100644 --- a/WINGs/WINGs/WINGsP.h.in +++ b/WINGs/WINGs/WINGsP.h.in @@ -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)); diff --git a/WINGs/wevent_wl.c b/WINGs/wevent_wl.c index f45ad05..297f93f 100644 --- a/WINGs/wevent_wl.c +++ b/WINGs/wevent_wl.c @@ -16,6 +16,7 @@ #include "WINGsP.h" #include +#include /* ------------------------------------------------------------------ */ @@ -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, }; /* ------------------------------------------------------------------ */ diff --git a/WINGs/wevent_x11.c b/WINGs/wevent_x11.c index 11354a2..cf310ea 100644 --- a/WINGs/wevent_x11.c +++ b/WINGs/wevent_x11.c @@ -10,7 +10,10 @@ #include "WINGs/WINGsX11.h" #include +#include #include +#include +#include /* ------------------------------------------------------------------ */ /* 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 +#include + +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, }; diff --git a/WPrefs.app/KeyboardShortcuts.c b/WPrefs.app/KeyboardShortcuts.c index f018ab8..64858a6 100644 --- a/WPrefs.app/KeyboardShortcuts.c +++ b/WPrefs.app/KeyboardShortcuts.c @@ -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 #include -#include -#include - 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); diff --git a/WPrefs.app/Menu.c b/WPrefs.app/Menu.c index 0317cf0..0b2d40e 100644 --- a/WPrefs.app/Menu.c +++ b/WPrefs.app/Menu.c @@ -24,9 +24,6 @@ #include #include -#include -#include - #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); diff --git a/WPrefs.app/MouseSettings.c b/WPrefs.app/MouseSettings.c index 092d6d4..51602c5 100644 --- a/WPrefs.app/MouseSettings.c +++ b/WPrefs.app/MouseSettings.c @@ -22,9 +22,6 @@ #include "WPrefs.h" -#include -#include - #include #include #include @@ -121,7 +118,6 @@ typedef struct _Panel { /* need access to the double click variables */ #include -#include 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) diff --git a/WPrefs.app/WPrefs.c b/WPrefs.app/WPrefs.c index 75eca95..7592098 100644 --- a/WPrefs.app/WPrefs.c +++ b/WPrefs.app/WPrefs.c @@ -24,11 +24,6 @@ #include "WPrefs.h" #include -#ifdef USE_X11_BACKEND -#include -#include -#endif - #ifdef HAVE_STDNORETURN #include #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) diff --git a/WPrefs.app/WPrefs.h b/WPrefs.app/WPrefs.h index 3c8873b..a07b54f 100644 --- a/WPrefs.app/WPrefs.h +++ b/WPrefs.app/WPrefs.h @@ -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 diff --git a/WPrefs.app/editmenu.c b/WPrefs.app/editmenu.c index 772dce6..38b9114 100644 --- a/WPrefs.app/editmenu.c +++ b/WPrefs.app/editmenu.c @@ -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); diff --git a/WPrefs.app/main.c b/WPrefs.app/main.c index b9acd05..9793e7b 100644 --- a/WPrefs.app/main.c +++ b/WPrefs.app/main.c @@ -26,10 +26,6 @@ #include -#ifdef USE_X11_BACKEND -#include -#endif - #include #include @@ -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 diff --git a/WPrefs.app/xmodifier.c b/WPrefs.app/xmodifier.c index 12aa47f..a58d93a 100644 --- a/WPrefs.app/xmodifier.c +++ b/WPrefs.app/xmodifier.c @@ -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 , 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 , 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 -#include - -#include "../src/wconfig.h" - -#ifdef USE_X11_BACKEND -#include -#include -#include -#include -#endif - -#include - #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 . */ -#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<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); }