Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5cf6063
Showing
5 changed files
with
353 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
sendkeys | ||
======= | ||
Couple of bash scripts for sending key presses to and open window in X. Uses Alan Donovan's xsendkey.c (http://people.csail.mit.edu/adonovan/hacks/xsendkey.html). | ||
|
||
Usage | ||
----- | ||
* sendkey.sh 'Google Chrome' F5 | ||
* sendkeys.sh 'Terminal' "start-server.sh" | ||
|
||
vim/sendkeys.vim contains some examples of using these scripts to do common tasks from Vim. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#!/bin/bash | ||
#Send a single key press to an open window with a given window title | ||
#Usage: sendkey.sh WINDOW-TITLE KEY | ||
# WINDOW-TITLE can be a regex | ||
# e.g. sendkey.sh 'Google Chrome' F5 | ||
title=$1 | ||
key=$2 | ||
|
||
windowId=`wmctrl -l | awk "/$title/ {print "'$1}'` | ||
xsendkey -window "$windowId" "$key" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
#!/bin/bash | ||
#Send a series of key presses to an open window with a given window title | ||
#Usage: sendkeys.sh WINDOW-TITLE KEY | ||
# WINDOW-TITLE can be a regex | ||
# e.g. sendkeys.sh 'Terminal' "start-server.sh" | ||
title=$1 | ||
keys=$2 | ||
|
||
for i in $(seq 0 $((${#keys} - 1))); do | ||
key=${keys:$i:1} | ||
windowId=`wmctrl -l | awk "/$title/ {print "'$1}'` | ||
|
||
#Handle special chars | ||
#TODO: What other chars should be handled here? What's a more generic way of doing this? | ||
if [ "$key" == "." ]; then | ||
key="period" | ||
elif [ "$key" == "," ]; then | ||
key="comma" | ||
elif [ "$key" == "'" ]; then | ||
key="apostrophe" | ||
elif [ "$key" == "/" ]; then | ||
key="slash" | ||
elif [ "$key" == " " ]; then | ||
key="space" | ||
fi | ||
xsendkey -window "$windowId" "$key" | ||
done | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
"Some examples of using sendkeys to do common tasks from Vim | ||
|
||
"Save current buffer and send F5 (refresh) to Chrome | ||
map <Leader>ss :w<CR>:silent !sendkey.sh ' Chrom' F5<CR> | ||
"Save current buffer and run the last command in the terminal (don't switch focus away from Vim) | ||
map <Leader>stl :w<CR>:silent !sendkey.sh Terminal Up && sendkey.sh Terminal Return<CR> | ||
"Save current buffer and prompt for a command to run in the terminal (don't switch focus away from Vim) | ||
map <Leader>ste :w<CR>:silent !sendkeys.sh Terminal "" && sendkey.sh Terminal Return<C-Left><C-Left><C-Left><C-Left><Left><Left> | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,294 @@ | ||
/* | ||
* (C) 2000-2004 Alan Donovan | ||
* | ||
* Author: Alan Donovan <adonovan@lcs.mit.edu> | ||
* | ||
* With thanks to: T.Sato <VEF00200@nifty.ne.jp>. | ||
* http://member.nifty.ne.jp/tsato/tools/xvkbd-e.html | ||
* and: Derek Martin (derek_martin at agilent dot com) | ||
* (for -count and XGetInputFocus) | ||
* and: Hanno Hecker <h.hecker@bee.de> | ||
* (for symbolic keysym and modifier lookup.) | ||
* | ||
* xsendkey.cxx -- General purpose keypress generator | ||
* | ||
* This program 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 | ||
* of the License, or any later version. | ||
* | ||
* This program 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. | ||
* <http://www.gnu.org/copyleft/gpl.html>. | ||
* | ||
* $Id: xsendkey.c,v 1.3 2004/11/11 16:10:01 adonovan Exp $ | ||
* | ||
*/ | ||
|
||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#ifdef WIN32 | ||
# include "windows_x11.h" | ||
#else | ||
# define NeedFunctionPrototypes 1 | ||
# include <X11/Xlib.h> | ||
# include <X11/keysym.h> | ||
# if XlibSpecificationRelease != 6 | ||
# error Requires X11R6 | ||
# endif | ||
#endif | ||
|
||
static char *progname = NULL; | ||
static char *displayname = NULL; | ||
static Window window = 0; | ||
static Display *display = NULL; | ||
static char keyname[1024]; | ||
static int shift = 0; | ||
static int keysym = 0; | ||
|
||
int MyErrorHandler(Display *my_display, XErrorEvent *event) | ||
{ | ||
fprintf(stderr, "%s: XSendEvent(0x%lx) failed.\n", progname, window); | ||
return 1; | ||
} | ||
|
||
void SendEvent(XKeyEvent *event) | ||
{ | ||
XSync(display, False); | ||
XSetErrorHandler(MyErrorHandler); | ||
XSendEvent(display, window, True, KeyPressMask, (XEvent*)event); | ||
XSync(display, False); | ||
XSetErrorHandler(NULL); | ||
} | ||
|
||
void SendKeyPressedEvent(KeySym keysym, unsigned int shift) | ||
{ | ||
XKeyEvent event; | ||
|
||
// Meta not yet implemented (Alt used instead ;->) | ||
int meta_mask=0; | ||
|
||
event.display = display; | ||
event.window = window; | ||
event.root = RootWindow(display, 0); // XXX nonzero screens? | ||
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.type = KeyPress; | ||
event.state = 0; | ||
|
||
// | ||
// press down shift keys one at a time... | ||
// | ||
|
||
if (shift & ShiftMask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Shift_L); | ||
SendEvent(&event); | ||
event.state |= ShiftMask; | ||
} | ||
if (shift & ControlMask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Control_L); | ||
SendEvent(&event); | ||
event.state |= ControlMask; | ||
} | ||
|
||
if (shift & Mod1Mask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Alt_L); | ||
SendEvent(&event); | ||
event.state |= Mod1Mask; | ||
} | ||
if (shift & meta_mask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Meta_L); | ||
SendEvent(&event); | ||
event.state |= meta_mask; | ||
} | ||
|
||
// | ||
// Now with shift keys held down, send event for the key itself... | ||
// | ||
|
||
|
||
// fprintf(stderr, "sym: 0x%x, name: %s\n", keysym, keyname); | ||
if (keysym != NoSymbol) { | ||
event.keycode = XKeysymToKeycode(display, keysym); | ||
// fprintf(stderr, "code: 0x%x, %d\n", event.keycode, event.keycode ); | ||
SendEvent(&event); | ||
|
||
event.type = KeyRelease; | ||
SendEvent(&event); | ||
} | ||
|
||
// | ||
// Now release all the shift keys... | ||
// | ||
|
||
if (shift & ShiftMask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Shift_L); | ||
SendEvent(&event); | ||
event.state &= ~ShiftMask; | ||
} | ||
if (shift & ControlMask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Control_L); | ||
SendEvent(&event); | ||
event.state &= ~ControlMask; | ||
} | ||
if (shift & Mod1Mask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Alt_L); | ||
SendEvent(&event); | ||
event.state &= ~Mod1Mask; | ||
} | ||
if (shift & meta_mask) { | ||
event.keycode = XKeysymToKeycode(display, XK_Meta_L); | ||
SendEvent(&event); | ||
event.state &= ~meta_mask; | ||
} | ||
} | ||
|
||
void usage() | ||
{ | ||
fprintf(stderr, | ||
"usage: %s [-window <id>|root]\n" | ||
" [-count <count>]\n" | ||
" [-display <name>] [Modifier+[Modifier+]]Key\n" | ||
"(looks up keysyms in <X11/keysymdef.h>)\n" | ||
"'Alt', 'Control', 'Shift' are replaced by\n" | ||
"'Alt_L', 'Control_L', 'Shift_L'...\n" | ||
" example:\n" | ||
" %s Control+Alt+Right\n", progname, progname); | ||
exit(1); | ||
} | ||
|
||
int main(int argc, char **argv) | ||
{ | ||
int ii, Junk; | ||
int c; | ||
char *temp; | ||
unsigned long count = 1; | ||
progname = argv[0]; | ||
|
||
for(ii=1; ii<argc; ii++) { | ||
if(strcmp(argv[ii], "-display") == 0) { | ||
if(++ii == argc) | ||
usage(); | ||
|
||
displayname = argv[ii]; | ||
} | ||
else if(strcmp(argv[ii], "-count") == 0) { | ||
if(++ii == argc) | ||
usage(); | ||
|
||
count = strtoul(argv[ii],NULL,0); | ||
} | ||
else if(strcmp(argv[ii], "-window") == 0) { | ||
if(++ii == argc) | ||
usage(); | ||
|
||
if(strcmp(argv[ii], "root") == 0) | ||
window = (Window)-1; | ||
else | ||
window = (Window)strtoul(argv[ii], NULL, 0); | ||
} | ||
else if(argv[ii][0] == '-') { | ||
fprintf(stderr, "%s: bad option `%s'.\n", | ||
progname, argv[ii]); | ||
usage(); | ||
} | ||
else { | ||
strncpy(keyname, argv[ii], 1023); | ||
keysym = 0; | ||
shift = 0; | ||
// fprintf(stderr, "keyname: %s\n", keyname); | ||
temp = strtok((char *)keyname, "+"); | ||
while (temp != NULL) { | ||
// fprintf(stderr, "temp: %s\n", temp); | ||
if (strcmp(temp, "Alt") == 0) | ||
c = XK_Alt_L; | ||
else if (strcmp(temp, "Control") == 0) | ||
c = XK_Control_L; | ||
else if (strcmp(temp, "Shift") == 0) | ||
c = XK_Shift_L; | ||
else | ||
c = XStringToKeysym(temp); | ||
|
||
if (c == 0) { | ||
fprintf(stderr, "unknown: %s\n", temp); | ||
usage(); | ||
} | ||
|
||
switch (c) { | ||
case XK_Shift_L: | ||
case XK_Shift_R: | ||
shift |= ShiftMask; | ||
break; | ||
case XK_Control_L: | ||
case XK_Control_R: | ||
shift |= ControlMask; | ||
break; | ||
case XK_Caps_Lock: | ||
case XK_Shift_Lock: | ||
shift |= LockMask; | ||
break; | ||
case XK_Meta_L: | ||
case XK_Meta_R: | ||
case XK_Alt_L: | ||
case XK_Alt_R: | ||
shift |= Mod1Mask; | ||
break; | ||
case XK_Super_L: | ||
case XK_Super_R: | ||
case XK_Hyper_L: | ||
case XK_Hyper_R: | ||
break; | ||
default: | ||
keysym = c; | ||
} | ||
// fprintf(stderr, "keysym: 0x%x, shift: %d\n", keysym, shift); | ||
temp = strtok(NULL, "+"); | ||
} | ||
/* keysym = strtoul(argv[ii], NULL, 0); */ | ||
} | ||
} | ||
if (keyname[0] == 0) { | ||
fprintf(stderr, "%s: you must specify a keyname.\n", progname); | ||
exit(1); | ||
} | ||
|
||
if(displayname == NULL) | ||
displayname = getenv("DISPLAY"); | ||
|
||
if(displayname == NULL) | ||
displayname = ":0.0"; | ||
|
||
display = XOpenDisplay(displayname); | ||
|
||
if(display == NULL) | ||
{ | ||
fprintf(stderr, "%s: can't open display `%s'.\n", | ||
progname, displayname); | ||
exit(1); | ||
} | ||
|
||
if(window == 0) | ||
XGetInputFocus(display, &window, &Junk); | ||
|
||
if(window == (Window)-1) | ||
{ | ||
window = RootWindow(display, 0); // XXX nonzero screens? | ||
} | ||
|
||
// now do the work: | ||
for (ii=0;ii<(int)count;ii++) | ||
SendKeyPressedEvent(keysym, shift); | ||
|
||
XCloseDisplay(display); | ||
|
||
return 0; | ||
} |