Make the relative desktop switching actions interactive

The desktop popup can now be shown "permanently" in which case it stays until
you tell it to hide.
This commit is contained in:
Dana Jansens 2009-12-16 15:17:08 -05:00
parent 1b392b5fbe
commit 1a34857640
6 changed files with 311 additions and 81 deletions

View file

@ -304,9 +304,12 @@ void actions_run_acts(GSList *acts,
if (interactive_act)
actions_interactive_cancel_act();
if (act->i_pre)
act->i_pre(act->options);
ok = actions_interactive_begin_act(act, state);
if (!act->i_pre(state, act->options))
act->i_input = NULL; /* remove the interactivity */
}
/* check again cuz it might have been cancelled */
if (actions_act_is_interactive(act))
ok = actions_interactive_begin_act(act, state);
}
/* fire the action's run function with this data */

View file

@ -37,7 +37,9 @@ typedef gboolean (*ObActionsRunFunc)(ObActionsData *data,
typedef gpointer (*ObActionsDataSetupFunc)(xmlNodePtr node);
/* functions for interactive actions */
typedef void (*ObActionsIPreFunc)(gpointer options);
/* return TRUE if the action is going to be interactive, or false to change
your mind and make it not */
typedef gboolean (*ObActionsIPreFunc)(guint initial_state, gpointer options);
typedef void (*ObActionsIPostFunc)(gpointer options);
typedef gboolean (*ObActionsIInputFunc)(guint initial_state,
XEvent *e,

View file

@ -27,17 +27,17 @@ static gpointer setup_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *in,
ObActionsICancelFunc *c,
ObActionsIPreFunc *post);
ObActionsIPostFunc *post);
static gpointer setup_forward_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *in,
ObActionsICancelFunc *c,
ObActionsIPreFunc *post);
ObActionsIPostFunc *post);
static gpointer setup_backward_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *in,
ObActionsICancelFunc *c,
ObActionsIPreFunc *post);
ObActionsIPostFunc *post);
static void free_func(gpointer options);
static gboolean run_func(ObActionsData *data, gpointer options);
static gboolean i_input_func(guint initial_state,
@ -58,7 +58,7 @@ static gpointer setup_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPreFunc *post)
ObActionsIPostFunc *post)
{
xmlNodePtr n;
Options *o;
@ -115,7 +115,7 @@ static gpointer setup_forward_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPreFunc *post)
ObActionsIPostFunc *post)
{
Options *o = setup_func(node, pre, input, cancel, post);
o->forward = TRUE;
@ -126,7 +126,7 @@ static gpointer setup_backward_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPreFunc *post)
ObActionsIPostFunc *post)
{
Options *o = setup_func(node, pre, input, cancel, post);
o->forward = FALSE;

View file

@ -1,6 +1,7 @@
#include "openbox/actions.h"
#include "openbox/screen.h"
#include "openbox/client.h"
#include "openbox/openbox.h"
#include <glib.h>
typedef enum {
@ -24,59 +25,130 @@ typedef struct {
} u;
gboolean send;
gboolean follow;
gboolean interactive;
} Options;
static gpointer setup_go_func(xmlNodePtr node);
static gpointer setup_send_func(xmlNodePtr node);
static gpointer setup_go_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gboolean run_func(ObActionsData *data, gpointer options);
static gboolean i_pre_func(guint state, gpointer options);
static gboolean i_input_func(guint initial_state,
XEvent *e,
gpointer options,
gboolean *used);
static void i_post_func(gpointer options);
/* 3.4-compatibility */
static gpointer setup_go_last_func(xmlNodePtr node);
static gpointer setup_send_last_func(xmlNodePtr node);
static gpointer setup_go_abs_func(xmlNodePtr node);
static gpointer setup_send_abs_func(xmlNodePtr node);
static gpointer setup_go_next_func(xmlNodePtr node);
static gpointer setup_send_next_func(xmlNodePtr node);
static gpointer setup_go_prev_func(xmlNodePtr node);
static gpointer setup_send_prev_func(xmlNodePtr node);
static gpointer setup_go_left_func(xmlNodePtr node);
static gpointer setup_send_left_func(xmlNodePtr node);
static gpointer setup_go_right_func(xmlNodePtr node);
static gpointer setup_send_right_func(xmlNodePtr node);
static gpointer setup_go_up_func(xmlNodePtr node);
static gpointer setup_send_up_func(xmlNodePtr node);
static gpointer setup_go_down_func(xmlNodePtr node);
static gpointer setup_send_down_func(xmlNodePtr node);
static gpointer setup_go_next_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_next_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_go_prev_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_prev_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_go_left_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_left_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_go_right_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_right_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_go_up_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_up_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_go_down_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
static gpointer setup_send_down_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post);
void action_desktop_startup(void)
{
actions_register("GoToDesktop", setup_go_func, g_free, run_func);
actions_register("SendToDesktop", setup_send_func, g_free, run_func);
actions_register_i("GoToDesktop", setup_go_func, g_free, run_func);
actions_register_i("SendToDesktop", setup_send_func, g_free, run_func);
/* 3.4-compatibility */
actions_register("DesktopLast", setup_go_last_func, g_free, run_func);
actions_register("SendToDesktopLast", setup_send_last_func,
g_free, run_func);
actions_register("Desktop", setup_go_abs_func, g_free, run_func);
actions_register("SendToDesktop", setup_send_abs_func, g_free, run_func);
actions_register("DesktopNext", setup_go_next_func, g_free, run_func);
actions_register("SendToDesktopNext", setup_send_next_func,
g_free, run_func);
actions_register("DesktopPrevious", setup_go_prev_func, g_free, run_func);
actions_register("SendToDesktopPrevious", setup_send_prev_func,
g_free, run_func);
actions_register("DesktopLeft", setup_go_left_func, g_free, run_func);
actions_register("SendToDesktopLeft", setup_send_left_func,
g_free, run_func);
actions_register("DesktopRight", setup_go_right_func, g_free, run_func);
actions_register("SendToDesktopRight", setup_send_right_func,
g_free, run_func);
actions_register("DesktopUp", setup_go_up_func, g_free, run_func);
actions_register("SendToDesktopUp", setup_send_up_func, g_free, run_func);
actions_register("DesktopDown", setup_go_down_func, g_free, run_func);
actions_register("SendToDesktopDown", setup_send_down_func,
g_free, run_func);
actions_register_i("DesktopNext", setup_go_next_func, g_free, run_func);
actions_register_i("SendToDesktopNext", setup_send_next_func,
g_free, run_func);
actions_register_i("DesktopPrevious", setup_go_prev_func,
g_free, run_func);
actions_register_i("SendToDesktopPrevious", setup_send_prev_func,
g_free, run_func);
actions_register_i("DesktopLeft", setup_go_left_func, g_free, run_func);
actions_register_i("SendToDesktopLeft", setup_send_left_func,
g_free, run_func);
actions_register_i("DesktopRight", setup_go_right_func, g_free, run_func);
actions_register_i("SendToDesktopRight", setup_send_right_func,
g_free, run_func);
actions_register_i("DesktopUp", setup_go_up_func, g_free, run_func);
actions_register_i("SendToDesktopUp", setup_send_up_func,
g_free, run_func);
actions_register_i("DesktopDown", setup_go_down_func, g_free, run_func);
actions_register_i("SendToDesktopDown", setup_send_down_func,
g_free, run_func);
}
static gpointer setup_go_func(xmlNodePtr node)
static gpointer setup_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
xmlNodePtr n;
Options *o;
@ -135,18 +207,49 @@ static gpointer setup_go_func(xmlNodePtr node)
return o;
}
static gpointer setup_send_func(xmlNodePtr node)
static gpointer setup_go_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o;
o = setup_func(node, pre, input, cancel, post);
if (o->type == RELATIVE) {
o->interactive = TRUE;
*pre = i_pre_func;
*input = i_input_func;
*post = i_post_func;
}
return o;
}
static gpointer setup_send_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
xmlNodePtr n;
Options *o;
o = setup_go_func(node);
o = setup_func(node, pre, input, cancel, post);
o->send = TRUE;
o->follow = TRUE;
if ((n = obt_parse_find_node(node, "follow")))
o->follow = obt_parse_node_bool(n);
if (o->type == RELATIVE && o->follow) {
o->interactive = TRUE;
*pre = i_pre_func;
*input = i_input_func;
*post = i_post_func;
}
return o;
}
@ -188,7 +291,54 @@ static gboolean run_func(ObActionsData *data, gpointer options)
actions_client_move(data, FALSE);
}
return FALSE;
return o->interactive;
}
static gboolean i_input_func(guint initial_state,
XEvent *e,
gpointer options,
gboolean *used)
{
if (e->type == KeyPress) {
/* Escape cancels no matter what */
if (ob_keycode_match(e->xkey.keycode, OB_KEY_ESCAPE)) {
return FALSE;
}
/* There were no modifiers and they pressed enter */
else if (ob_keycode_match(e->xkey.keycode, OB_KEY_RETURN) &&
!initial_state)
{
return FALSE;
}
}
/* They released the modifiers */
else if (e->type == KeyRelease && initial_state &&
(e->xkey.state & initial_state) == 0)
{
return FALSE;
}
return TRUE;
}
static gboolean i_pre_func(guint initial_state, gpointer options)
{
if (!initial_state) {
Options *o = options;
o->interactive = FALSE;
return FALSE;
}
else {
screen_show_desktop_popup(screen_desktop, TRUE);
return TRUE;
}
}
static void i_post_func(gpointer options)
{
screen_hide_desktop_popup();
}
/* 3.4-compatilibity */
@ -241,7 +391,11 @@ static gpointer setup_send_abs_func(xmlNodePtr node)
return o;
}
static void setup_rel(Options *o, xmlNodePtr node, gboolean lin, ObDirection dir)
static void setup_rel(Options *o, xmlNodePtr node, gboolean lin,
ObDirection dir,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsIPostFunc *post)
{
xmlNodePtr n;
@ -252,88 +406,149 @@ static void setup_rel(Options *o, xmlNodePtr node, gboolean lin, ObDirection dir
if ((n = obt_parse_find_node(node, "wrap")))
o->u.rel.wrap = obt_parse_node_bool(n);
if (input) {
o->interactive = TRUE;
*pre = i_pre_func;
*input = i_input_func;
*post = i_post_func;
}
}
static gpointer setup_go_next_func(xmlNodePtr node)
static gpointer setup_go_next_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
setup_rel(o, node, TRUE, OB_DIRECTION_EAST, pre, input, post);
return o;
}
static gpointer setup_send_next_func(xmlNodePtr node)
static gpointer setup_send_next_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, TRUE, OB_DIRECTION_EAST);
setup_rel(o, node, TRUE, OB_DIRECTION_EAST,
pre, (o->follow ? input : NULL), post);
return o;
}
static gpointer setup_go_prev_func(xmlNodePtr node)
static gpointer setup_go_prev_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
setup_rel(o, node, TRUE, OB_DIRECTION_WEST, pre, input, post);
return o;
}
static gpointer setup_send_prev_func(xmlNodePtr node)
static gpointer setup_send_prev_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, TRUE, OB_DIRECTION_WEST);
setup_rel(o, node, TRUE, OB_DIRECTION_WEST,
pre, (o->follow ? input : NULL), post);
return o;
}
static gpointer setup_go_left_func(xmlNodePtr node)
static gpointer setup_go_left_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
setup_rel(o, node, FALSE, OB_DIRECTION_WEST, pre, input, post);
return o;
}
static gpointer setup_send_left_func(xmlNodePtr node)
static gpointer setup_send_left_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, FALSE, OB_DIRECTION_WEST);
setup_rel(o, node, FALSE, OB_DIRECTION_WEST,
pre, (o->follow ? input : NULL), post);
return o;
}
static gpointer setup_go_right_func(xmlNodePtr node)
static gpointer setup_go_right_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
setup_rel(o, node, FALSE, OB_DIRECTION_EAST, pre, input, post);
return o;
}
static gpointer setup_send_right_func(xmlNodePtr node)
static gpointer setup_send_right_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, FALSE, OB_DIRECTION_EAST);
setup_rel(o, node, FALSE, OB_DIRECTION_EAST,
pre, (o->follow ? input : NULL), post);
return o;
}
static gpointer setup_go_up_func(xmlNodePtr node)
static gpointer setup_go_up_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
setup_rel(o, node, FALSE, OB_DIRECTION_NORTH, pre, input, post);
return o;
}
static gpointer setup_send_up_func(xmlNodePtr node)
static gpointer setup_send_up_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, FALSE, OB_DIRECTION_NORTH);
setup_rel(o, node, FALSE, OB_DIRECTION_NORTH,
pre, (o->follow ? input : NULL), post);
return o;
}
static gpointer setup_go_down_func(xmlNodePtr node)
static gpointer setup_go_down_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = g_new0(Options, 1);
setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH, pre, input, post);
return o;
}
static gpointer setup_send_down_func(xmlNodePtr node)
static gpointer setup_send_down_func(xmlNodePtr node,
ObActionsIPreFunc *pre,
ObActionsIInputFunc *input,
ObActionsICancelFunc *cancel,
ObActionsIPostFunc *post)
{
Options *o = setup_follow(node);
setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH);
setup_rel(o, node, FALSE, OB_DIRECTION_SOUTH,
pre, (o->follow ? input : NULL), post);
return o;
}

View file

@ -77,6 +77,7 @@ static GSList *struts_right = NULL;
static GSList *struts_bottom = NULL;
static ObPagerPopup *desktop_popup;
static gboolean desktop_popup_perm;
/*! The number of microseconds that you need to be on a desktop before it will
replace the remembered "last desktop" */
@ -347,6 +348,7 @@ void screen_startup(gboolean reconfig)
gboolean namesexist = FALSE;
desktop_popup = pager_popup_new();
desktop_popup_perm = FALSE;
pager_popup_height(desktop_popup, POPUP_HEIGHT);
if (reconfig) {
@ -677,7 +679,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
ob_debug("Moving to desktop %d", num+1);
if (ob_state() == OB_STATE_RUNNING)
screen_show_desktop_popup(screen_desktop);
screen_show_desktop_popup(screen_desktop, FALSE);
/* ignore enter events caused by the move */
ignore_start = event_start_ignore_all_enters();
@ -701,8 +703,7 @@ void screen_set_desktop(guint num, gboolean dofocus)
for (it = g_list_last(stacking_list); it; it = g_list_previous(it)) {
if (WINDOW_IS_CLIENT(it->data)) {
ObClient *c = it->data;
client_hide(c);
if (c == focus_client) {
if (client_hide(c) && c == focus_client) {
/* c was focused and we didn't do fallback clearly so make sure
openbox doesnt still consider the window focused.
this happens when using NextWindow with allDesktops, since
@ -922,7 +923,7 @@ static gboolean hide_desktop_popup_func(gpointer data)
return FALSE; /* don't repeat */
}
void screen_show_desktop_popup(guint d)
void screen_show_desktop_popup(guint d, gboolean perm)
{
Rect *a;
@ -942,9 +943,13 @@ void screen_show_desktop_popup(guint d)
pager_popup_show(desktop_popup, screen_desktop_names[d], d);
obt_main_loop_timeout_remove(ob_main_loop, hide_desktop_popup_func);
obt_main_loop_timeout_add(ob_main_loop, config_desktop_popup_time * 1000,
hide_desktop_popup_func, desktop_popup,
g_direct_equal, NULL);
if (!perm && !desktop_popup_perm)
/* only hide if its not already being show permanently */
obt_main_loop_timeout_add(ob_main_loop,
config_desktop_popup_time * 1000,
hide_desktop_popup_func, desktop_popup,
g_direct_equal, NULL);
g_free(a);
}
@ -953,6 +958,7 @@ void screen_hide_desktop_popup(void)
obt_main_loop_timeout_remove_data(ob_main_loop, hide_desktop_popup_func,
desktop_popup, FALSE);
pager_popup_hide(desktop_popup);
desktop_popup_perm = FALSE;
}
guint screen_find_desktop(guint from, ObDirection dir,

View file

@ -75,8 +75,12 @@ void screen_remove_desktop(gboolean current);
guint screen_find_desktop(guint from, ObDirection dir,
gboolean wrap, gboolean linear);
/*! Show the desktop popup/notification */
void screen_show_desktop_popup(guint d);
/*! Show the desktop popup/notification
@permanent If TRUE, the popup will stay on the screen until you call
screen_hide_desktop_popup(). Otherwise it will hide after a
delay.
*/
void screen_show_desktop_popup(guint d, gboolean permanent);
/*! Hide it */
void screen_hide_desktop_popup(void);