From d8591dfb7045017f73945af3813a14397f95af3c Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Tue, 5 Feb 2008 11:19:10 +0100 Subject: [PATCH] New SendKeyEvent and SetKeyTarget actions. These let you define SendKeyEvent actions that send a specified key to a target window. The target window can be changed at runtime with the SetKeyTarget action. --- Makefile.am | 1 + obt/prop.c | 1 + obt/prop.h | 1 + openbox/actions/all.c | 1 + openbox/actions/all.h | 1 + openbox/actions/sendkeyevent.c | 92 ++++++++++++++++++++++++++++++++++ openbox/screen.c | 1 + po/POTFILES.in | 1 + 8 files changed, 99 insertions(+) create mode 100644 openbox/actions/sendkeyevent.c diff --git a/Makefile.am b/Makefile.am index e7ef29fc..d14042e8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -231,6 +231,7 @@ openbox_openbox_SOURCES = \ openbox/actions/resize.c \ openbox/actions/resizerelative.c \ openbox/actions/restart.c \ + openbox/actions/sendkeyevent.c \ openbox/actions/shade.c \ openbox/actions/shadelowerraise.c \ openbox/actions/showdesktop.c \ diff --git a/obt/prop.c b/obt/prop.c index 0cecccf4..ad40b2b9 100644 --- a/obt/prop.c +++ b/obt/prop.c @@ -200,6 +200,7 @@ void obt_prop_startup(void) CREATE_(OB_APP_GROUP_NAME); CREATE_(OB_APP_GROUP_CLASS); CREATE_(OB_APP_TYPE); + CREATE_(OB_TARGET_WINDOW); } Atom obt_prop_atom(ObtPropAtom a) diff --git a/obt/prop.h b/obt/prop.h index acb5c956..804ac409 100644 --- a/obt/prop.h +++ b/obt/prop.h @@ -222,6 +222,7 @@ typedef enum { OBT_PROP_OB_APP_GROUP_NAME, OBT_PROP_OB_APP_GROUP_CLASS, OBT_PROP_OB_APP_TYPE, + OBT_PROP_OB_TARGET_WINDOW, OBT_PROP_NUM_ATOMS } ObtPropAtom; diff --git a/openbox/actions/all.c b/openbox/actions/all.c index 7b226b1f..1c0e21a9 100644 --- a/openbox/actions/all.c +++ b/openbox/actions/all.c @@ -40,6 +40,7 @@ void action_all_startup(void) action_growtoedge_startup(); action_if_startup(); action_focustobottom_startup(); + action_sendkeyevent_startup(); /* 3.4-compatibility */ action_shadelowerraise_startup(); } diff --git a/openbox/actions/all.h b/openbox/actions/all.h index ec576844..cc3f580d 100644 --- a/openbox/actions/all.h +++ b/openbox/actions/all.h @@ -41,6 +41,7 @@ void action_movetoedge_startup(void); void action_growtoedge_startup(void); void action_if_startup(void); void action_focustobottom_startup(void); +void action_sendkeyevent_startup(void); /* 3.4-compatibility */ void action_shadelowerraise_startup(void); diff --git a/openbox/actions/sendkeyevent.c b/openbox/actions/sendkeyevent.c new file mode 100644 index 00000000..72be282d --- /dev/null +++ b/openbox/actions/sendkeyevent.c @@ -0,0 +1,92 @@ +#include "openbox/actions.h" +#include "openbox/client.h" +#include "openbox/window.h" +#include "openbox/translate.h" +#include "obt/display.h" +#include "obt/prop.h" +#include "openbox/openbox.h" +#include "gettext.h" + +typedef struct { + guint key; + guint state; + gboolean target; +} Options; + +static gpointer setup_sendkey_func(xmlNodePtr node); +static gboolean sendkey(ObActionsData *data, gpointer options); +static gboolean settarget(ObActionsData *data, gpointer options); + +static Window target; + +void action_sendkeyevent_startup(void) +{ + actions_register("SendKeyEvent", + setup_sendkey_func, g_free, + sendkey); + actions_register("SetKeyTarget", + NULL, NULL, + settarget); + OBT_PROP_GET32(obt_root(ob_screen), OB_TARGET_WINDOW, WINDOW, (guint32 *)&target); +} + +static gpointer setup_sendkey_func(xmlNodePtr node) +{ + xmlNodePtr n; + Options *o; + + o = g_new0(Options, 1); + o->target = TRUE; + + if ((n = obt_xml_find_node(node, "key"))) { + gchar *s = obt_xml_node_string(n); + translate_key(s, &o->state, &o->key); + g_free(s); + } else + translate_key("space", &o->state, &o->key); + if ((n = obt_xml_find_node(node, "usetarget"))) + o->target = obt_xml_node_bool(n); + + return o; +} + +/* Always return FALSE because its not interactive */ +static gboolean sendkey(ObActionsData *data, gpointer options) +{ + Options *o = options; + XEvent ev; + Window win; + + if (!o->key) /* the key couldn't be parsed */ + return FALSE; + + if (o->target) + win = target; + else if (data->client) + win = data->client->window; + else + return FALSE; + + ev.xkey.window = win; + ev.xkey.state = o->state; + ev.xkey.keycode = o->key; + obt_display_ignore_errors(TRUE); + ev.type = KeyPress; + XSendEvent(obt_display, win, False, 0, &ev); + ev.type = KeyRelease; + XSendEvent(obt_display, win, False, 0, &ev); + obt_display_ignore_errors(FALSE); + + return FALSE; +} + +/* Always return FALSE because its not interactive */ +static gboolean settarget(ObActionsData *data, gpointer options) +{ + if (data->client) { + target = data->client->window; + OBT_PROP_SET32(obt_root(ob_screen), OB_TARGET_WINDOW, WINDOW, target); + } + + return FALSE; +} diff --git a/openbox/screen.c b/openbox/screen.c index e758ada1..d254c528 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -308,6 +308,7 @@ gboolean screen_annex(void) supported[i++] = OBT_PROP_ATOM(OB_APP_GROUP_NAME); supported[i++] = OBT_PROP_ATOM(OB_APP_GROUP_CLASS); supported[i++] = OBT_PROP_ATOM(OB_APP_TYPE); + supported[i++] = OBT_PROP_ATOM(OB_TARGET_WINDOW); g_assert(i == num_support); OBT_PROP_SETA32(obt_root(ob_screen), diff --git a/po/POTFILES.in b/po/POTFILES.in index 45097149..326a5e72 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -2,6 +2,7 @@ openbox/actions.c openbox/actions/execute.c openbox/actions/exit.c +openbox/actions/sendkeyevent.c openbox/client.c openbox/client_list_combined_menu.c openbox/client_list_menu.c -- 2.34.1