]> icculus.org git repositories - mikachu/openbox.git/blob - openbox/actions/sendkeyevent.c
Merge branch 'work' into wip/mikabox
[mikachu/openbox.git] / openbox / actions / sendkeyevent.c
1 #include "openbox/actions.h"
2 #include "openbox/client.h"
3 #include "openbox/window.h"
4 #include "obt/display.h"
5 #include "obt/prop.h"
6 #include "openbox/openbox.h"
7 #include "gettext.h"
8
9 typedef struct {
10     KeyCode key;
11     gboolean target;
12 } Options;
13
14 static gpointer setup_sendkey_func(xmlNodePtr node);
15 static void free_sendkey_func(gpointer options);
16 static gboolean sendkey(ObActionsData *data, gpointer options);
17 static gboolean settarget(ObActionsData *data, gpointer options);
18
19 static Window target;
20
21 void action_sendkeyevent_startup(void)
22 {
23     actions_register("SendKeyEvent",
24                      setup_sendkey_func, g_free,
25                      sendkey,
26                      NULL, NULL);
27     actions_register("SetKeyTarget",
28                      NULL, NULL,
29                      settarget,
30                      NULL, NULL);
31     OBT_PROP_GET32(obt_root(ob_screen), OB_TARGET_WINDOW, WINDOW, (guint32 *)&target);
32 }
33
34 static KeyCode parse_key(gchar *s)
35 {
36     KeySym sym;
37
38     sym = XStringToKeysym(s);
39     if (sym == NoSymbol) {
40         g_warning(_("Invalid key name '%s' in SendKeyEvent action."), s);
41         return 0;
42     }
43
44     return XKeysymToKeycode(obt_display, sym);
45 }
46
47 static gpointer setup_sendkey_func(xmlNodePtr node)
48 {
49     xmlNodePtr n;
50     Options *o;
51
52     o = g_new0(Options, 1);
53     o->target = TRUE;
54
55     if ((n = obt_parse_find_node(node, "key"))) {
56         gchar *s = obt_parse_node_string(n);
57         o->key = parse_key(s);
58         g_free(s);
59     } else
60         o->key = parse_key("space");
61     if ((n = obt_parse_find_node(node, "usetarget")))
62         o->target = obt_parse_node_bool(n);
63
64     return o;
65 }
66
67 /* Always return FALSE because its not interactive */
68 static gboolean sendkey(ObActionsData *data, gpointer options)
69 {
70     Options *o = options;
71     XEvent ev;
72     Window win;
73
74     if (!o->key) /* the key couldn't be parsed */
75         return FALSE;
76
77     if (o->target)
78         win = target;
79     else if (data->client)
80         win = data->client->window;
81     else
82         return FALSE;
83
84     ev.xkey.window = win;
85     ev.xkey.state = 0;
86     ev.xkey.keycode = o->key;
87     obt_display_ignore_errors(TRUE);
88     ev.type = KeyPress;
89     XSendEvent(obt_display, win, False, 0, &ev);
90     ev.type = KeyRelease;
91     XSendEvent(obt_display, win, False, 0, &ev);
92     obt_display_ignore_errors(FALSE);
93
94     return FALSE;
95 }
96
97 /* Always return FALSE because its not interactive */
98 static gboolean settarget(ObActionsData *data, gpointer options)
99 {
100     if (data->client) {
101       target = data->client->window;
102       OBT_PROP_SET32(obt_root(ob_screen), OB_TARGET_WINDOW, WINDOW, target);
103     }
104
105     return FALSE;
106 }