#include "actions.h"
#include "gettext.h"
+#include "grab.h"
-static void actions_definition_ref(ObActionsDefinition *def);
-static void actions_definition_unref(ObActionsDefinition *def);
+static void actions_definition_ref(ObActionsDefinition *def);
+static void actions_definition_unref(ObActionsDefinition *def);
+static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state);
+static void actions_interactive_end_act();
+
+static ObActionsAct *interactive_act = NULL;
+static guint interactive_initial_state = 0;
struct _ObActionsDefinition {
guint ref;
ObActionsDataSetupFunc setup;
ObActionsDataFreeFunc free;
ObActionsRunFunc run;
+ ObActionsInteractiveInputFunc i_input;
+ ObActionsInteractiveCancelFunc i_cancel;
};
struct _ObActionsAct {
ObActionsType type,
ObActionsDataSetupFunc setup,
ObActionsDataFreeFunc free,
- ObActionsRunFunc run)
+ ObActionsRunFunc run,
+ ObActionsInteractiveInputFunc i_input,
+ ObActionsInteractiveCancelFunc i_cancel)
{
GSList *it;
ObActionsDefinition *def;
return FALSE;
}
+ g_assert((i_input == NULL) == (i_cancel == NULL));
+
def = g_new(ObActionsDefinition, 1);
def->ref = 1;
def->name = g_strdup(name);
def->setup = setup;
def->free = free;
def->run = run;
+ def->i_input = i_input;
+ def->i_cancel = i_cancel;
return TRUE;
}
return act;
}
+gboolean actions_act_is_interactive(ObActionsAct *act)
+{
+ return act->def->i_cancel != NULL;
+}
+
void actions_act_ref(ObActionsAct *act)
{
++act->ref;
ObUserAction uact,
Time time,
guint state,
- guint button,
gint x,
gint y)
{
data->any.uact = uact;
data->any.time = time;
data->any.state = state;
- data->any.button = button;
data->any.x = x;
data->any.y = y;
}
ObUserAction uact,
Time time,
guint state,
- guint button,
gint x,
gint y,
ObFrameContext con,
- struct _ObClient *client,
- ObActionsInteractiveState interactive)
+ struct _ObClient *client)
{
GSList *it;
for (it = acts; it; it = g_slist_next(it)) {
ObActionsData data;
ObActionsAct *act = it->data;
+ gboolean ok = TRUE;
data.type = act->def->type;
- actions_setup_data(&data, uact, time, state, button, x, y);
+ actions_setup_data(&data, uact, time, state, x, y);
switch (data.type) {
case OB_ACTION_TYPE_GLOBAL:
break;
data.client.context = con;
data.client.c = client;
break;
- case OB_ACTION_TYPE_SELECTOR:
- data.selector.interactive = interactive;
- break;
default:
g_assert_not_reached();
}
+ if (actions_act_is_interactive(act) &&
+ (!interactive_act || interactive_act->def != act->def))
+ {
+ ok = actions_interactive_begin_act(act, state);
+ }
+
/* fire the action's run function with this data */
- act->def->run(&data, act->options);
+ if (ok) {
+ if (!act->def->run(&data, act->options))
+ actions_interactive_end_act();
+ else
+ break; /* no actions are run after the interactive one */
+ }
+ }
+}
+
+gboolean actions_interactive_act_running()
+{
+ return interactive_act != NULL;
+}
+
+void actions_interactive_cancel_act()
+{
+ if (interactive_act) {
+ interactive_act->def->i_cancel(interactive_act->options);
+ actions_interactive_end_act();
+ }
+}
+
+static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state)
+{
+ /* cancel the old one */
+ if (interactive_act)
+ actions_interactive_cancel_act();
+
+ if (grab_keyboard()) {
+ interactive_act = act;
+ actions_act_ref(interactive_act);
+
+ interactive_initial_state = state;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static void actions_interactive_end_act()
+{
+ if (interactive_act) {
+ ungrab_keyboard();
+
+ actions_act_unref(interactive_act);
+ interactive_act = NULL;
+ }
+}
+
+gboolean actions_interactive_input_event(XEvent *e)
+{
+ gboolean used = FALSE;
+ if (interactive_act) {
+ if (!interactive_act->def->i_input(interactive_initial_state, e,
+ interactive_act->options, &used))
+ {
+ used = TRUE; /* if it cancelled the action then it has to of
+ been used */
+ actions_interactive_end_act();
+ }
}
+ return used;
}