icewm/src/icesh.cc | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 101 insertions(+), 3 deletions(-) diff --git a/icewm/src/icesh.cc b/icewm/src/icesh.cc index 2c52cb9..3958640 100644 --- a/icewm/src/icesh.cc +++ b/icewm/src/icesh.cc @@ -459,6 +459,91 @@ Status setTrayHint(Window window, long trayopt) { return XSendEvent(display, root, False, SubstructureNotifyMask, (XEvent *) &xev); } +bool parseKey(const char *arg, KeySym *key, unsigned int *mod) { + const char *orig_arg = arg; + + *mod = 0; + for (;;) { + if (strncmp("Alt+", arg, 4) == 0) { + *mod |= Mod1Mask; + arg += 4; + } else if (strncmp("Ctrl+", arg, 5) == 0) { + *mod |= ControlMask; + arg += 5; + } else if (strncmp("Shift+", arg, 6) == 0) { + *mod |= ShiftMask; + arg += 6; + } else if (strncmp("Meta+", arg, 5) == 0) { + *mod |= Mod2Mask; + arg += 5; + } else if (strncmp("Super+", arg, 6) == 0) { + *mod |= Mod3Mask; + arg += 6; + } else if (strncmp("Hyper+", arg, 6) == 0) { + *mod |= Mod4Mask; + arg += 6; + } else + break; + } + if (strcmp(arg, "") == 0) { + *key = NoSymbol; + return true; + } else if (strcmp(arg, "Esc") == 0) + *key = XK_Escape; + else if (strcmp(arg, "Enter") == 0) + *key = XK_Return; + else if (strcmp(arg, "Space") == 0) + *key = ' '; + else if (strcmp(arg, "BackSp") == 0) + *key = XK_BackSpace; + else if (strcmp(arg, "Del") == 0) + *key = XK_Delete; + else if (strlen(arg) == 1 && arg[0] >= 'A' && arg[0] <= 'Z') { + char s[2]; + s[0] = arg[0] - 'A' + 'a'; + s[1] = 0; + *key = XStringToKeysym(s); + } else { + *key = XStringToKeysym(arg); + } + + if (*key == NoSymbol) { + msg(_("Unknown key name %s in %s"), arg, orig_arg); + return false; + } + return true; +} + +Status sendKeyEvent(Window window, const char *key) { + XKeyEvent event; + KeySym sym = NoSymbol; + unsigned int mod = 0; + KeyCode code; + + if (!parseKey(key, &sym, &mod)) + MSG(("parseKey error")); + + code = XKeysymToKeycode(display, sym); + + event.display = display; + event.window = window; + event.root = root; + event.subwindow = None; + event.time = CurrentTime; + event.x = 1; + event.y = 1; + event.x_root = 1; + event.y_root = 1; + event.same_screen = True; + event.send_event = True; + + event.type = KeyPress; + event.keycode = code; + event.state = mod; + + return XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event); +} + /******************************************************************************/ Window getClientWindow(Window window) @@ -573,6 +658,7 @@ Actions:\n\ the root window to change the current workspace.\n\ listWorkspaces Lists the names of all workspaces.\n\ setTrayOption TRAYOPTION Set the IceWM tray option hint.\n\ + sendKeyEvent KEYCOMBINATION Send KEYCOMBINATION to window.\n\ \n\ Expressions:\n\ Expressions are list of symbols of one domain concatenated by `+' or `|':\n\ @@ -747,10 +833,13 @@ int main(int argc, char **argv) { if (windowList[i] != None && XGetClassHint(display, windowList[i], &classhint)) { if (wmclass) { - if (strcmp(classhint.res_name, wmname) || - strcmp(classhint.res_class, wmclass)) + if ((strcmp(classhint.res_name, wmname) || + strcmp(classhint.res_class, wmclass)) || + (strcmp(classhint.res_name, wmclass) || + strcmp(classhint.res_class, wmname))) windowList[i] = None; - } else { + } + else { if (strcmp(classhint.res_name, wmname) && strcmp(classhint.res_class, wmname)) windowList[i] = None; @@ -770,6 +859,9 @@ int main(int argc, char **argv) { MSG(("windowCount: %d", windowCount)); +if (windowCount == 0) +return 1; + /******************************************************************************/ while (argp < argv + argc) { @@ -885,6 +977,12 @@ int main(int argc, char **argv) { MSG(("setTrayOption: %d", trayopt)); FOREACH_WINDOW(window) setTrayHint(*window, trayopt); + } else if (!strcmp(action, "sendKeyEvent")) { + CHECK_ARGUMENT_COUNT (1) + + MSG(("sendKeyEvent: `%s'", *argp)); + FOREACH_WINDOW(window) sendKeyEvent(*window, *argp); + argp++; } else { msg(_("Unknown action: `%s'"), action); THROW(1);