little bit of an actions overhaul, added action_run* so that duplicated code can all be in the same place now woot.

allow actions to specify when they can be used (ShowMenu cant in the OB_USER_ACTION_MENU_SELECTION case)
remove KeyboardMove ad KeyboardResize. Instead, just use Move and Resize and determine if it should be a keyboard move/resize in the code
This commit is contained in:
Dana Jansens 2003-09-07 19:03:20 +00:00
parent b23594d88d
commit 78282959f9
15 changed files with 402 additions and 459 deletions

View file

@ -96,10 +96,10 @@
<action name="PreviousWindow"/>
</keybind>
<keybind key="A-F7">
<action name="KeyboardMove"/>
<action name="Move"/>
</keybind>
<keybind key="A-F8">
<action name="KeyboardResize"/>
<action name="Resize"/>
</keybind>
<keybind key="A-F9">
<action name="Iconify"/>

View file

@ -5,21 +5,22 @@
#include "menu.h"
#include "prop.h"
#include "stacking.h"
#include "frame.h"
#include "screen.h"
#include "action.h"
#include "openbox.h"
#include "grab.h"
#include "keyboard.h"
#include <glib.h>
typedef struct ActionString {
char *name;
void (*func)(union ActionData *);
void (*setup)(ObAction *);
void (*setup)(ObAction **, ObUserAction uact);
} ActionString;
ObAction *action_new(void (*func)(union ActionData *data))
static ObAction *action_new(void (*func)(union ActionData *data),
ObUserAction uact)
{
ObAction *a = g_new0(ObAction, 1);
a->func = func;
@ -40,262 +41,255 @@ void action_free(ObAction *a)
g_free(a);
}
void setup_action_directional_focus_north(ObAction *a)
void setup_action_directional_focus_north(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_NORTH;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_NORTH;
}
void setup_action_directional_focus_east(ObAction *a)
void setup_action_directional_focus_east(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_EAST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_EAST;
}
void setup_action_directional_focus_south(ObAction *a)
void setup_action_directional_focus_south(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_SOUTH;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_SOUTH;
}
void setup_action_directional_focus_west(ObAction *a)
void setup_action_directional_focus_west(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_WEST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_WEST;
}
void setup_action_directional_focus_northeast(ObAction *a)
void setup_action_directional_focus_northeast(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_NORTHEAST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_NORTHEAST;
}
void setup_action_directional_focus_southeast(ObAction *a)
void setup_action_directional_focus_southeast(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_SOUTHEAST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_SOUTHEAST;
}
void setup_action_directional_focus_southwest(ObAction *a)
void setup_action_directional_focus_southwest(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_SOUTHWEST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_SOUTHWEST;
}
void setup_action_directional_focus_northwest(ObAction *a)
void setup_action_directional_focus_northwest(ObAction **a, ObUserAction uact)
{
a->data.interdiraction.inter.any.interactive = TRUE;
a->data.interdiraction.direction = OB_DIRECTION_NORTHWEST;
(*a)->data.interdiraction.inter.any.interactive = TRUE;
(*a)->data.interdiraction.direction = OB_DIRECTION_NORTHWEST;
}
void setup_action_send_to_desktop(ObAction *a)
void setup_action_send_to_desktop(ObAction **a, ObUserAction uact)
{
a->data.sendto.follow = TRUE;
(*a)->data.sendto.follow = TRUE;
}
void setup_action_send_to_desktop_prev(ObAction *a)
void setup_action_send_to_desktop_prev(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_WEST;
a->data.sendtodir.linear = TRUE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_WEST;
(*a)->data.sendtodir.linear = TRUE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_send_to_desktop_next(ObAction *a)
void setup_action_send_to_desktop_next(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_EAST;
a->data.sendtodir.linear = TRUE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_EAST;
(*a)->data.sendtodir.linear = TRUE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_send_to_desktop_left(ObAction *a)
void setup_action_send_to_desktop_left(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_WEST;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_WEST;
(*a)->data.sendtodir.linear = FALSE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_send_to_desktop_right(ObAction *a)
void setup_action_send_to_desktop_right(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_EAST;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_EAST;
(*a)->data.sendtodir.linear = FALSE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_send_to_desktop_up(ObAction *a)
void setup_action_send_to_desktop_up(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_NORTH;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_NORTH;
(*a)->data.sendtodir.linear = FALSE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_send_to_desktop_down(ObAction *a)
void setup_action_send_to_desktop_down(ObAction **a, ObUserAction uact)
{
a->data.sendtodir.inter.any.interactive = TRUE;
a->data.sendtodir.dir = OB_DIRECTION_SOUTH;
a->data.sendtodir.linear = FALSE;
a->data.sendtodir.wrap = TRUE;
a->data.sendtodir.follow = TRUE;
(*a)->data.sendtodir.inter.any.interactive = TRUE;
(*a)->data.sendtodir.dir = OB_DIRECTION_SOUTH;
(*a)->data.sendtodir.linear = FALSE;
(*a)->data.sendtodir.wrap = TRUE;
(*a)->data.sendtodir.follow = TRUE;
}
void setup_action_desktop_prev(ObAction *a)
void setup_action_desktop_prev(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_WEST;
a->data.desktopdir.linear = TRUE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_WEST;
(*a)->data.desktopdir.linear = TRUE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_next(ObAction *a)
void setup_action_desktop_next(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_EAST;
a->data.desktopdir.linear = TRUE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_EAST;
(*a)->data.desktopdir.linear = TRUE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_left(ObAction *a)
void setup_action_desktop_left(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_WEST;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_WEST;
(*a)->data.desktopdir.linear = FALSE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_right(ObAction *a)
void setup_action_desktop_right(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_EAST;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_EAST;
(*a)->data.desktopdir.linear = FALSE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_up(ObAction *a)
void setup_action_desktop_up(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_NORTH;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_NORTH;
(*a)->data.desktopdir.linear = FALSE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_desktop_down(ObAction *a)
void setup_action_desktop_down(ObAction **a, ObUserAction uact)
{
a->data.desktopdir.inter.any.interactive = TRUE;
a->data.desktopdir.dir = OB_DIRECTION_SOUTH;
a->data.desktopdir.linear = FALSE;
a->data.desktopdir.wrap = TRUE;
(*a)->data.desktopdir.inter.any.interactive = TRUE;
(*a)->data.desktopdir.dir = OB_DIRECTION_SOUTH;
(*a)->data.desktopdir.linear = FALSE;
(*a)->data.desktopdir.wrap = TRUE;
}
void setup_action_move_keyboard(ObAction *a)
void setup_action_cycle_windows_next(ObAction **a, ObUserAction uact)
{
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move_keyboard;
(*a)->data.cycle.inter.any.interactive = TRUE;
(*a)->data.cycle.linear = FALSE;
(*a)->data.cycle.forward = TRUE;
}
void setup_action_move(ObAction *a)
void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
{
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_move;
(*a)->data.cycle.inter.any.interactive = TRUE;
(*a)->data.cycle.linear = FALSE;
(*a)->data.cycle.forward = FALSE;
}
void setup_action_resize(ObAction *a)
void setup_action_movetoedge_north(ObAction **a, ObUserAction uact)
{
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_topleft;
(*a)->data.diraction.direction = OB_DIRECTION_NORTH;
}
void setup_action_resize_keyboard(ObAction *a)
void setup_action_movetoedge_south(ObAction **a, ObUserAction uact)
{
a->data.moveresize.corner = prop_atoms.net_wm_moveresize_size_keyboard;
(*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
}
void setup_action_cycle_windows_linear_next(ObAction *a)
void setup_action_movetoedge_east(ObAction **a, ObUserAction uact)
{
a->data.cycle.inter.any.interactive = TRUE;
a->data.cycle.linear = TRUE;
a->data.cycle.forward = TRUE;
(*a)->data.diraction.direction = OB_DIRECTION_EAST;
}
void setup_action_cycle_windows_linear_previous(ObAction *a)
void setup_action_movetoedge_west(ObAction **a, ObUserAction uact)
{
a->data.cycle.inter.any.interactive = TRUE;
a->data.cycle.linear = TRUE;
a->data.cycle.forward = FALSE;
(*a)->data.diraction.direction = OB_DIRECTION_WEST;
}
void setup_action_cycle_windows_next(ObAction *a)
void setup_action_growtoedge_north(ObAction **a, ObUserAction uact)
{
a->data.cycle.inter.any.interactive = TRUE;
a->data.cycle.linear = FALSE;
a->data.cycle.forward = TRUE;
(*a)->data.diraction.direction = OB_DIRECTION_NORTH;
}
void setup_action_cycle_windows_previous(ObAction *a)
void setup_action_growtoedge_south(ObAction **a, ObUserAction uact)
{
a->data.cycle.inter.any.interactive = TRUE;
a->data.cycle.linear = FALSE;
a->data.cycle.forward = FALSE;
(*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
}
void setup_action_movetoedge_north(ObAction *a)
void setup_action_growtoedge_east(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_NORTH;
(*a)->data.diraction.direction = OB_DIRECTION_EAST;
}
void setup_action_movetoedge_south(ObAction *a)
void setup_action_growtoedge_west(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_SOUTH;
(*a)->data.diraction.direction = OB_DIRECTION_WEST;
}
void setup_action_movetoedge_east(ObAction *a)
void setup_action_top_layer(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_EAST;
(*a)->data.layer.layer = 1;
}
void setup_action_movetoedge_west(ObAction *a)
void setup_action_normal_layer(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_WEST;
(*a)->data.layer.layer = 0;
}
void setup_action_growtoedge_north(ObAction *a)
void setup_action_bottom_layer(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_NORTH;
(*a)->data.layer.layer = -1;
}
void setup_action_growtoedge_south(ObAction *a)
void setup_action_move(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_SOUTH;
(*a)->data.moveresize.move = TRUE;
(*a)->data.moveresize.keyboard =
(uact == OB_USER_ACTION_KEYBOARD_KEY ||
uact == OB_USER_ACTION_MENU_SELECTION);
}
void setup_action_growtoedge_east(ObAction *a)
void setup_action_resize(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_EAST;
(*a)->data.moveresize.move = FALSE;
(*a)->data.moveresize.keyboard =
(uact == OB_USER_ACTION_KEYBOARD_KEY ||
uact == OB_USER_ACTION_MENU_SELECTION);
}
void setup_action_growtoedge_west(ObAction *a)
void setup_action_showmenu(ObAction **a, ObUserAction uact)
{
a->data.diraction.direction = OB_DIRECTION_WEST;
}
void setup_action_top_layer(ObAction *a)
{
a->data.layer.layer = 1;
}
void setup_action_normal_layer(ObAction *a)
{
a->data.layer.layer = 0;
}
void setup_action_bottom_layer(ObAction *a)
{
a->data.layer.layer = -1;
/* you cannot call ShowMenu from inside a menu, cuz the menu code makes
assumptions that there is only one menu (and submenus) open at
a time! */
if (uact == OB_USER_ACTION_MENU_SELECTION) {
action_free(*a);
a = NULL;
}
}
ActionString actionstrings[] =
@ -348,12 +342,12 @@ ActionString actionstrings[] =
{
"activate",
action_activate,
NULL,
NULL
},
{
"focus",
action_focus,
NULL,
NULL
},
{
"unfocus",
@ -560,11 +554,6 @@ ActionString actionstrings[] =
action_toggle_decorations,
NULL
},
{
"keyboardmove",
action_moveresize,
setup_action_move_keyboard
},
{
"move",
action_moveresize,
@ -575,11 +564,6 @@ ActionString actionstrings[] =
action_moveresize,
setup_action_resize
},
{
"keyboardresize",
action_moveresize,
setup_action_resize_keyboard
},
{
"toggleshowdesktop",
action_toggle_show_desktop,
@ -618,7 +602,7 @@ ActionString actionstrings[] =
{
"showmenu",
action_showmenu,
NULL
setup_action_showmenu
},
{
"sendtotoplayer",
@ -645,16 +629,6 @@ ActionString actionstrings[] =
action_toggle_layer,
setup_action_bottom_layer
},
{
"nextwindowlinear",
action_cycle_windows,
setup_action_cycle_windows_linear_next
},
{
"previouswindowlinear",
action_cycle_windows,
setup_action_cycle_windows_linear_previous
},
{
"nextwindow",
action_cycle_windows,
@ -712,32 +686,37 @@ ActionString actionstrings[] =
}
};
ObAction *action_from_string(char *name)
ObAction *action_from_string(char *name, ObUserAction uact)
{
ObAction *a = NULL;
gboolean exist = FALSE;
int i;
for (i = 0; actionstrings[i].name; i++)
if (!g_ascii_strcasecmp(name, actionstrings[i].name)) {
a = action_new(actionstrings[i].func);
exist = TRUE;
a = action_new(actionstrings[i].func, uact);
if (actionstrings[i].setup)
actionstrings[i].setup(a);
actionstrings[i].setup(&a, uact);
break;
}
if (!a)
if (!exist)
g_warning("Invalid action '%s' requested. No such action exists.",
name);
if (!a)
g_warning("Invalid use of action '%s'. Action will be ignored.", name);
return a;
}
ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
ObUserAction uact)
{
char *actname;
ObAction *act = NULL;
xmlNodePtr n;
if (parse_attr_string("name", node, &actname)) {
if ((act = action_from_string(actname))) {
if ((act = action_from_string(actname, uact))) {
if (act->func == action_execute || act->func == action_restart) {
if ((n = parse_find_node("execute", node->xmlChildrenNode))) {
gchar *s = parse_string(doc, n);
@ -747,26 +726,25 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
} else if (act->func == action_showmenu) {
if ((n = parse_find_node("menu", node->xmlChildrenNode)))
act->data.showmenu.name = parse_string(doc, n);
} else if (act->func == action_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.desktop.desk = parse_int(doc, n);
if (act->data.desktop.desk > 0) act->data.desktop.desk--;
} else if (act->func == action_send_to_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.sendto.desk = parse_int(doc, n);
if (act->data.sendto.desk > 0) act->data.sendto.desk--;
} else if (act->func == action_move_relative_horz ||
act->func == action_move_relative_vert ||
act->func == action_resize_relative_horz ||
act->func == action_resize_relative_vert) {
if ((n = parse_find_node("delta", node->xmlChildrenNode)))
act->data.relative.delta = parse_int(doc, n);
} else if (act->func == action_desktop_dir) {
if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
act->data.desktopdir.wrap = parse_bool(doc, n);
} else if (act->func == action_send_to_desktop) {
} else if (act->func == action_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.desktop.desk = parse_int(doc, n);
if (act->data.desktop.desk > 0) act->data.desktop.desk--;
} else if (act->func == action_send_to_desktop) {
if ((n = parse_find_node("desktop", node->xmlChildrenNode)))
act->data.sendto.desk = parse_int(doc, n);
if (act->data.sendto.desk > 0) act->data.sendto.desk--;
if ((n = parse_find_node("follow", node->xmlChildrenNode)))
act->data.sendto.follow = parse_bool(doc, n);
} else if (act->func == action_desktop_dir) {
if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
act->data.desktopdir.wrap = parse_bool(doc, n);
} else if (act->func == action_send_to_desktop_dir) {
if ((n = parse_find_node("wrap", node->xmlChildrenNode)))
act->data.sendtodir.wrap = parse_bool(doc, n);
@ -775,6 +753,9 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
} else if (act->func == action_activate) {
if ((n = parse_find_node("here", node->xmlChildrenNode)))
act->data.activate.here = parse_bool(doc, n);
} else if (act->func == action_cycle_windows) {
if ((n = parse_find_node("linear", node->xmlChildrenNode)))
act->data.cycle.linear = parse_bool(doc, n);
}
}
g_free(actname);
@ -782,6 +763,30 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node)
return act;
}
void action_run_full(ObAction *a, struct _ObClient *c,
ObFrameContext context,
guint state, guint button, gint x, gint y,
gboolean cancel, gboolean done)
{
if (x < 0 && y < 0)
screen_pointer_pos(&x, &y);
a->data.any.c = c;
a->data.any.x = x;
a->data.any.y = y;
a->data.any.button = button;
if (a->data.any.interactive) {
a->data.inter.cancel = cancel;
a->data.inter.final = done;
if (!(cancel || done))
keyboard_interactive_grab(state, c, context, a);
}
a->func(&a->data);
}
void action_execute(union ActionData *data)
{
GError *e = NULL;
@ -1089,14 +1094,48 @@ void action_toggle_decorations(union ActionData *data)
client_setup_decor_and_functions(c);
}
static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
{
if (x - cx > cw / 2) {
if (y - cy > ch / 2)
return prop_atoms.net_wm_moveresize_size_bottomright;
else
return prop_atoms.net_wm_moveresize_size_topright;
} else {
if (y - cy > ch / 2)
return prop_atoms.net_wm_moveresize_size_bottomleft;
else
return prop_atoms.net_wm_moveresize_size_topleft;
}
}
void action_moveresize(union ActionData *data)
{
ObClient *c = data->moveresize.any.c;
guint32 corner;
if (!c || !client_normal(c)) return;
moveresize_start(c, data->moveresize.x, data->moveresize.y,
data->moveresize.button, data->moveresize.corner);
if (data->moveresize.keyboard) {
corner = (data->moveresize.move ?
prop_atoms.net_wm_moveresize_move_keyboard :
prop_atoms.net_wm_moveresize_size_keyboard);
} else {
corner = (data->moveresize.move ?
prop_atoms.net_wm_moveresize_move :
pick_corner(data->any.x, data->any.y,
c->frame->area.x, c->frame->area.y,
/* use the client size because the frame
can be differently sized (shaded
windows) and we want this based on the
clients size */
c->area.width + c->frame->size.left +
c->frame->size.right,
c->area.height + c->frame->size.top +
c->frame->size.bottom));
}
moveresize_start(c, data->any.x, data->any.y, data->any.button, corner);
}
void action_reconfigure(union ActionData *data)
@ -1117,7 +1156,7 @@ void action_exit(union ActionData *data)
void action_showmenu(union ActionData *data)
{
if (data->showmenu.name) {
menu_show(data->showmenu.name, data->showmenu.x, data->showmenu.y,
menu_show(data->showmenu.name, data->any.x, data->any.y,
data->showmenu.any.c);
}
}

View file

@ -2,8 +2,11 @@
#define __action_h
#include "misc.h"
#include "frame.h"
#include "parser/parse.h"
struct _ObClient;
typedef struct _ObAction ObAction;
/* These have to all have a Client* at the top even if they don't use it, so
@ -14,6 +17,9 @@ typedef struct _ObAction ObAction;
struct AnyAction {
struct _ObClient *c;
gboolean interactive;
gint x;
gint y;
gint button;
};
struct InteractiveAction {
@ -84,17 +90,13 @@ struct DesktopDirection {
struct MoveResize {
struct AnyAction any;
int x;
int y;
guint32 corner; /* prop_atoms.net_wm_moveresize_* */
guint button;
gboolean move;
gboolean keyboard;
};
struct ShowMenu {
struct AnyAction any;
char *name;
int x;
int y;
};
struct CycleWindows {
@ -123,6 +125,7 @@ union ActionData {
};
struct _ObAction {
ObUserAction act;
/* The func member acts like an enum to tell which one of the structs in
the data union are valid.
*/
@ -130,24 +133,53 @@ struct _ObAction {
union ActionData data;
};
ObAction *action_new(void (*func)(union ActionData *data));
/* Creates a new Action from the name of the action
A few action types need data set after making this call still. Check if
the returned action's "func" is one of these.
action_execute - the path needs to be set
action_restart - the path can optionally be set
action_desktop - the destination desktop needs to be set
action_send_to_desktop - the destination desktop needs to be set
action_move_relative_horz - the delta
action_move_relative_vert - the delta
action_resize_relative_horz - the delta
action_resize_relative_vert - the delta
*/
ObAction *action_from_string(char *name);
ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node);
ObAction *action_from_string(char *name, ObUserAction uact);
ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
ObUserAction uact);
void action_free(ObAction *a);
/*! Executes an action.
@param c The client associated with the action. Can be NULL.
@param context The context in which the user action occured.
@param state The keyboard modifiers state at the time the user action occured
@param button The mouse button used to execute the action.
@param x The x coord at which the user action occured.
@param y The y coord at which the user action occured.
@param cancel If the action is cancelling an interactive action. This only
affects interactive actions, but should generally always be FALSE.
@param done If the action is completing an interactive action. This only
affects interactive actions, but should generally always be FALSE.
*/
void action_run_full(ObAction *a, struct _ObClient *c,
ObFrameContext context,
guint state, guint button, gint x, gint y,
gboolean cancel, gboolean done);
#define action_run_mouse(a, c, t, s, b, x, y) \
action_run_full(a, c, t, s, b, x, y, FALSE, FALSE)
#define action_run_interactive(a, c, s, n, d) \
action_run_full(a, c, OB_FRAME_CONTEXT_NONE, s, 0, -1, -1, n, d)
#define action_run_key(a, c, s, x, y) \
action_run_full(a, c, OB_FRAME_CONTEXT_NONE, s, 0, x, y, FALSE,FALSE)
#define action_run(a, c, s) \
action_run_full(a, c, OB_FRAME_CONTEXT_NONE, s, 0, -1, -1, FALSE,FALSE)
/* Execute */
void action_execute(union ActionData *data);
/* ActivateAction */

View file

@ -40,7 +40,8 @@ static void desk_menu_update(ObMenuFrame *frame, gpointer data)
menu_add_separator(menu, -1);
}
act = action_from_string("activate");
act = action_from_string("Activate",
OB_USER_ACTION_MENU_SELECTION);
act->data.activate.any.c = c;
acts = g_slist_prepend(NULL, act);
e = menu_add_normal(menu, i,
@ -56,16 +57,16 @@ static void desk_menu_update(ObMenuFrame *frame, gpointer data)
}
/* executes it without changing the client in the actions, since we set that
/* executes it using the client in the actions, since we set that
when we make the actions! */
static void desk_menu_execute(ObMenuEntry *self, gpointer data)
static void desk_menu_execute(ObMenuEntry *self, guint state, gpointer data)
{
GSList *it;
for (it = self->data.normal.actions; it; it = g_slist_next(it))
{
ObAction *act = it->data;
act->func(&act->data);
action_run(it->data, act->data.any.c, state);
}
}

View file

@ -120,7 +120,8 @@ static void send_to_update(ObMenuFrame *frame, gpointer data)
name = screen_desktop_names[i];
}
act = action_from_string("SendToDesktop");
act = action_from_string("SendToDesktop",
OB_USER_ACTION_MENU_SELECTION);
act->data.sendto.desk = desk;
act->data.sendto.follow = FALSE;
acts = g_slist_prepend(NULL, act);
@ -143,13 +144,18 @@ void client_menu_startup()
menu = menu_new(LAYER_MENU_NAME, _("Layer"), NULL);
menu_set_update_func(menu, layer_update);
acts = g_slist_prepend(NULL, action_from_string("SendToTopLayer"));
acts = g_slist_prepend(NULL, action_from_string
("SendToTopLayer", OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, LAYER_TOP, _("Always on top"), acts);
acts = g_slist_prepend(NULL, action_from_string("SendToNormalLayer"));
acts = g_slist_prepend(NULL, action_from_string
("SendToNormalLayer",
OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, LAYER_NORMAL, _("Normal"), acts);
acts = g_slist_prepend(NULL, action_from_string("SendToBottomLayer"));
acts = g_slist_prepend(NULL, action_from_string
("SendToBottomLayer",
OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, LAYER_BOTTOM, _("Always on bottom"),acts);
@ -168,47 +174,58 @@ void client_menu_startup()
menu_add_submenu(menu, CLIENT_LAYER, LAYER_MENU_NAME);
acts = g_slist_prepend(NULL, action_from_string("Iconify"));
acts = g_slist_prepend(NULL, action_from_string
("Iconify", OB_USER_ACTION_MENU_SELECTION));
e = menu_add_normal(menu, CLIENT_ICONIFY, _("Iconify"), acts);
e->data.normal.mask = ob_rr_theme->iconify_mask;
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
e->data.normal.mask_disabled_color = ob_rr_theme->menu_disabled_color;
e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
acts = g_slist_prepend(NULL, action_from_string("ToggleMaximizeFull"));
acts = g_slist_prepend(NULL, action_from_string
("ToggleMaximizeFull",
OB_USER_ACTION_MENU_SELECTION));
e = menu_add_normal(menu, CLIENT_MAXIMIZE, _("Maximize"), acts);
e->data.normal.mask = ob_rr_theme->max_mask;
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
e->data.normal.mask_disabled_color = ob_rr_theme->menu_disabled_color;
e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
acts = g_slist_prepend(NULL, action_from_string("Raise"));
acts = g_slist_prepend(NULL, action_from_string
("Raise", OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, CLIENT_RAISE, _("Raise to top"), acts);
acts = g_slist_prepend(NULL, action_from_string("Lower"));
acts = g_slist_prepend(NULL, action_from_string
("Lower", OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, CLIENT_LOWER, _("Lower to bottom"),acts);
acts = g_slist_prepend(NULL, action_from_string("ToggleShade"));
acts = g_slist_prepend(NULL, action_from_string
("ToggleShade", OB_USER_ACTION_MENU_SELECTION));
e = menu_add_normal(menu, CLIENT_SHADE, _("Roll up/down"), acts);
e->data.normal.mask = ob_rr_theme->shade_mask;
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;
e->data.normal.mask_disabled_color = ob_rr_theme->menu_disabled_color;
e->data.normal.mask_selected_color = ob_rr_theme->menu_selected_color;
acts = g_slist_prepend(NULL, action_from_string("ToggleDecorations"));
acts = g_slist_prepend(NULL, action_from_string
("ToggleDecorations",
OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, CLIENT_DECORATE, _("Decorate"), acts);
menu_add_separator(menu, -1);
acts = g_slist_prepend(NULL, action_from_string("KeyboardMove"));
acts = g_slist_prepend(NULL, action_from_string
("Move", OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, CLIENT_MOVE, _("Move"), acts);
acts = g_slist_prepend(NULL, action_from_string("KeyboardResize"));
acts = g_slist_prepend(NULL, action_from_string
("Resize", OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(menu, CLIENT_RESIZE, _("Resize"), acts);
menu_add_separator(menu, -1);
acts = g_slist_prepend(NULL, action_from_string("Close"));
acts = g_slist_prepend(NULL, action_from_string
("Close", OB_USER_ACTION_MENU_SELECTION));
e = menu_add_normal(menu, CLIENT_CLOSE, _("Close"), acts);
e->data.normal.mask = ob_rr_theme->close_mask;
e->data.normal.mask_normal_color = ob_rr_theme->menu_color;

View file

@ -82,20 +82,9 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
if (keylist) {
nact = parse_find_node("action", node);
while (nact) {
if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a key binding */
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_move_keyboard &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
if (action)
keyboard_bind(keylist, action);
}
if ((action = action_parse(i, doc, nact,
OB_USER_ACTION_KEYBOARD_KEY)))
keyboard_bind(keylist, action);
nact = parse_find_node("action", nact->next);
}
}
@ -123,6 +112,7 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
xmlNodePtr n, nbut, nact;
char *buttonstr;
char *contextstr;
ObUserAction uact;
ObMouseAction mact;
ObAction *action;
@ -141,44 +131,27 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
while (nbut) {
if (!parse_attr_string("button", nbut, &buttonstr))
goto next_nbut;
if (parse_attr_contains("press", nbut, "action"))
if (parse_attr_contains("press", nbut, "action")) {
uact = OB_USER_ACTION_MOUSE_PRESS;
mact = OB_MOUSE_ACTION_PRESS;
else if (parse_attr_contains("release", nbut, "action"))
} else if (parse_attr_contains("release", nbut, "action")) {
uact = OB_USER_ACTION_MOUSE_RELEASE;
mact = OB_MOUSE_ACTION_RELEASE;
else if (parse_attr_contains("click", nbut, "action"))
} else if (parse_attr_contains("click", nbut, "action")) {
uact = OB_USER_ACTION_MOUSE_CLICK;
mact = OB_MOUSE_ACTION_CLICK;
else if (parse_attr_contains("doubleclick", nbut,"action"))
} else if (parse_attr_contains("doubleclick", nbut,"action")) {
uact = OB_USER_ACTION_MOUSE_DOUBLE_CLICK;
mact = OB_MOUSE_ACTION_DOUBLE_CLICK;
else if (parse_attr_contains("drag", nbut, "action"))
} else if (parse_attr_contains("drag", nbut, "action")) {
uact = OB_USER_ACTION_MOUSE_MOTION;
mact = OB_MOUSE_ACTION_MOTION;
else
} else
goto next_nbut;
nact = parse_find_node("action", nbut->xmlChildrenNode);
while (nact) {
if ((action = action_parse(i, doc, nact))) {
/* validate that its okay for a mouse binding*/
if (mact == OB_MOUSE_ACTION_MOTION) {
if (action->func != action_moveresize ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_move_keyboard ||
action->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
} else {
if (action->func == action_moveresize &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_move_keyboard &&
action->data.moveresize.corner !=
prop_atoms.net_wm_moveresize_size_keyboard) {
action_free(action);
action = NULL;
}
}
if (action)
mouse_bind(buttonstr, contextstr, mact, action);
}
if ((action = action_parse(i, doc, nact, uact)))
mouse_bind(buttonstr, contextstr, mact, action);
nact = parse_find_node("action", nact->next);
}
g_free(buttonstr);

View file

@ -1126,8 +1126,7 @@ static void event_handle_menu(XEvent *ev)
else {
if ((e = menu_entry_frame_under(ev->xbutton.x_root,
ev->xbutton.y_root)))
menu_entry_frame_execute(e,
!(ev->xbutton.state & ControlMask));
menu_entry_frame_execute(e, ev->xbutton.state);
}
break;
case MotionNotify:
@ -1145,8 +1144,7 @@ static void event_handle_menu(XEvent *ev)
else if (ev->xkey.keycode == ob_keycode(OB_KEY_RETURN)) {
ObMenuFrame *f;
if ((f = find_active_menu()))
menu_entry_frame_execute(f->selected,
!(ev->xkey.state & ControlMask));
menu_entry_frame_execute(f->selected, ev->xkey.state);
} else if (ev->xkey.keycode == ob_keycode(OB_KEY_LEFT)) {
ObMenuFrame *f;
if ((f = find_active_menu()) && f->parent)

View file

@ -133,6 +133,8 @@ void keyboard_interactive_grab(guint state, ObClient *client,
{
ObInteractiveState *s;
g_assert(action->data.any.interactive);
if (!interactive_states) {
if (!grab_keyboard(TRUE))
return;
@ -179,12 +181,8 @@ gboolean keyboard_process_interactive_grab(const XEvent *e,
cancel = done = TRUE;
}
if (done) {
g_assert(s->action->data.any.interactive);
s->action->data.inter.cancel = cancel;
s->action->data.inter.final = TRUE;
s->action->func(&s->action->data);
action_run_interactive(s->action, s->client,
e->xkey.state, cancel, TRUE);
g_free(s);
@ -221,7 +219,8 @@ void keyboard_event(ObClient *client, const XEvent *e)
p = curpos->first_child;
while (p) {
if (p->key == e->xkey.keycode &&
p->state == e->xkey.state) {
p->state == e->xkey.state)
{
if (p->first_child != NULL) { /* part of a chain */
ob_main_loop_timeout_remove(ob_main_loop, chain_timeout);
/* 5 second timeout for chains */
@ -232,32 +231,10 @@ void keyboard_event(ObClient *client, const XEvent *e)
grab_keys(TRUE);
} else {
GSList *it;
for (it = p->actions; it; it = it->next) {
ObAction *act = it->data;
if (act->func != NULL) {
act->data.any.c = client;
if (act->func == action_moveresize) {
screen_pointer_pos(&act->data.moveresize.x,
&act->data.moveresize.y);
}
if (act->data.any.interactive) {
act->data.inter.cancel = FALSE;
act->data.inter.final = FALSE;
keyboard_interactive_grab(e->xkey.state, client,
0, act);
}
if (act->func == action_showmenu) {
act->data.showmenu.x = e->xkey.x_root;
act->data.showmenu.y = e->xkey.y_root;
}
act->data.any.c = client;
act->func(&act->data);
}
}
for (it = p->actions; it; it = it->next)
action_run_key(it->data, client, e->xkey.state,
e->xkey.x_root, e->xkey.y_root);
keyboard_reset_chains();
}

View file

@ -180,7 +180,9 @@ static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
for (node = node->xmlChildrenNode; node; node = node->next)
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
acts = g_slist_append(acts, action_parse(i, doc, node));
acts = g_slist_append(acts, action_parse
(i, doc, node,
OB_USER_ACTION_MENU_SELECTION));
menu_add_normal(state->parent, -1, label, acts);
g_free(label);
}

View file

@ -20,7 +20,8 @@ typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry;
typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry;
typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data);
typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry, gpointer data);
typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntry *entry,
guint state, gpointer data);
typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data);
struct _ObMenu

View file

@ -711,7 +711,7 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self)
menu_frame_show(f, self->frame);
}
void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide)
void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state)
{
if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL &&
self->entry->data.normal.enabled)
@ -725,31 +725,16 @@ void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide)
ObClient *client = self->frame->client;
/* release grabs before executing the shit */
if (hide)
if (!(state & ControlMask))
menu_frame_hide_all();
if (func)
func(entry, data);
func(entry, state, data);
else {
GSList *it;
for (it = acts; it; it = g_slist_next(it))
{
ObAction *act = it->data;
act->data.any.c = client;
if (act->func == action_moveresize)
screen_pointer_pos(&act->data.moveresize.x,
&act->data.moveresize.y);
if (!(act->func == action_cycle_windows ||
act->func == action_desktop_dir ||
act->func == action_send_to_desktop_dir ||
act->func == action_showmenu))
{
act->func(&act->data);
}
}
action_run(it->data, client, state);
}
}
}

View file

@ -100,6 +100,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y);
void menu_entry_frame_show_submenu(ObMenuEntryFrame *self);
void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide);
void menu_entry_frame_execute(ObMenuEntryFrame *self, guint state);
#endif

View file

@ -62,4 +62,24 @@ typedef enum
OB_CORNER_BOTTOMRIGHT
} ObCorner;
typedef enum {
OB_MOUSE_ACTION_PRESS,
OB_MOUSE_ACTION_RELEASE,
OB_MOUSE_ACTION_CLICK,
OB_MOUSE_ACTION_DOUBLE_CLICK,
OB_MOUSE_ACTION_MOTION,
OB_NUM_MOUSE_ACTIONS
} ObMouseAction;
typedef enum {
OB_USER_ACTION_KEYBOARD_KEY,
OB_USER_ACTION_MOUSE_PRESS,
OB_USER_ACTION_MOUSE_RELEASE,
OB_USER_ACTION_MOUSE_CLICK,
OB_USER_ACTION_MOUSE_DOUBLE_CLICK,
OB_USER_ACTION_MOUSE_MOTION,
OB_USER_ACTION_MENU_SELECTION,
OB_NUM_USER_ACTIONS
} ObUserAction;
#endif

View file

@ -9,13 +9,12 @@
#include "frame.h"
#include "translate.h"
#include "mouse.h"
#include "keyboard.h"
#include <glib.h>
typedef struct {
guint state;
guint button;
GSList *actions[OB_MOUSE_NUM_ACTIONS]; /* lists of Action pointers */
GSList *actions[OB_NUM_MOUSE_ACTIONS]; /* lists of Action pointers */
} ObMouseBinding;
#define FRAME_CONTEXT(co, cl) ((cl && cl->type != OB_CLIENT_TYPE_DESKTOP) ? \
@ -33,7 +32,7 @@ void mouse_grab_for_client(ObClient *client, gboolean grab)
GSList *it;
for (i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i)
for (it = bound_contexts[i]; it != NULL; it = it->next) {
for (it = bound_contexts[i]; it != NULL; it = g_slist_next(it)) {
/* grab/ungrab the button */
ObMouseBinding *b = it->data;
Window win;
@ -75,14 +74,14 @@ static void clearall()
for(i = 0; i < OB_FRAME_NUM_CONTEXTS; ++i) {
for (it = bound_contexts[i]; it != NULL; it = it->next) {
ObMouseBinding *b = it->data;
int j;
ObMouseBinding *b = it->data;
for (j = 0; j < OB_MOUSE_NUM_ACTIONS; ++j) {
for (j = 0; j < OB_NUM_MOUSE_ACTIONS; ++j) {
GSList *it;
for (it = b->actions[j]; it; it = it->next) {
for (it = b->actions[j]; it; it = it->next)
action_free(it->data);
}
g_slist_free(b->actions[j]);
}
g_free(b);
@ -92,9 +91,9 @@ static void clearall()
}
}
static gboolean fire_button(ObMouseAction a, ObFrameContext context,
ObClient *c, guint state,
guint button, int x, int y)
static gboolean fire_binding(ObMouseAction a, ObFrameContext context,
ObClient *c, guint state,
guint button, int x, int y)
{
GSList *it;
ObMouseBinding *b;
@ -107,85 +106,11 @@ static gboolean fire_button(ObMouseAction a, ObFrameContext context,
/* if not bound, then nothing to do! */
if (it == NULL) return FALSE;
for (it = b->actions[a]; it; it = it->next) {
ObAction *act = it->data;
if (act->func != NULL) {
act->data.any.c = c;
g_assert(act->func != action_moveresize);
if (act->func == action_showmenu) {
act->data.showmenu.x = x;
act->data.showmenu.y = y;
}
if (act->data.any.interactive) {
act->data.inter.cancel = FALSE;
act->data.inter.final = FALSE;
keyboard_interactive_grab(state, c, context, act);
}
act->func(&act->data);
}
}
for (it = b->actions[a]; it; it = it->next)
action_run_mouse(it->data, c, context, state, button, x, y);
return TRUE;
}
static gboolean fire_motion(ObMouseAction a, ObFrameContext context,
ObClient *c, guint state, guint button,
int x_root, int y_root, guint32 corner)
{
GSList *it;
ObMouseBinding *b;
for (it = bound_contexts[context]; it != NULL; it = it->next) {
b = it->data;
if (b->state == state && b->button == button)
break;
}
/* if not bound, then nothing to do! */
if (it == NULL) return FALSE;
for (it = b->actions[a]; it; it = it->next) {
ObAction *act = it->data;
if (act->func != NULL) {
act->data.any.c = c;
if (act->func == action_moveresize) {
act->data.moveresize.x = x_root;
act->data.moveresize.y = y_root;
act->data.moveresize.button = button;
if (!(act->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_move ||
act->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_move_keyboard ||
act->data.moveresize.corner ==
prop_atoms.net_wm_moveresize_size_keyboard))
act->data.moveresize.corner = corner;
} else
g_assert_not_reached();
act->func(&act->data);
}
}
return TRUE;
}
static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
{
if (x - cx < cw / 2) {
if (y - cy < ch / 2)
return prop_atoms.net_wm_moveresize_size_topleft;
else
return prop_atoms.net_wm_moveresize_size_bottomleft;
} else {
if (y - cy < ch / 2)
return prop_atoms.net_wm_moveresize_size_topright;
else
return prop_atoms.net_wm_moveresize_size_bottomright;
}
}
void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
{
static Time ltime;
@ -203,10 +128,10 @@ void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
button = e->xbutton.button;
state = e->xbutton.state;
fire_button(OB_MOUSE_ACTION_PRESS, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root, e->xbutton.y_root);
fire_binding(OB_MOUSE_ACTION_PRESS, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root, e->xbutton.y_root);
if (CLIENT_CONTEXT(context, client)) {
/* Replay the event, so it goes to the client*/
@ -252,22 +177,22 @@ void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
state = 0;
ltime = e->xbutton.time;
}
fire_button(OB_MOUSE_ACTION_RELEASE, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root, e->xbutton.y_root);
fire_binding(OB_MOUSE_ACTION_RELEASE, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root, e->xbutton.y_root);
if (click)
fire_button(OB_MOUSE_ACTION_CLICK, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root,
e->xbutton.y_root);
fire_binding(OB_MOUSE_ACTION_CLICK, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root,
e->xbutton.y_root);
if (dclick)
fire_button(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root,
e->xbutton.y_root);
fire_binding(OB_MOUSE_ACTION_DOUBLE_CLICK, context,
client, e->xbutton.state,
e->xbutton.button,
e->xbutton.x_root,
e->xbutton.y_root);
break;
case MotionNotify:
@ -276,7 +201,6 @@ void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
config_mouse_threshold ||
ABS(e->xmotion.y_root - py) >=
config_mouse_threshold) {
guint32 corner;
/* You can't drag on buttons */
if (context == OB_FRAME_CONTEXT_MAXIMIZE ||
@ -287,26 +211,8 @@ void mouse_event(ObClient *client, ObFrameContext context, XEvent *e)
context == OB_FRAME_CONTEXT_CLOSE)
break;
if (!client)
corner = prop_atoms.net_wm_moveresize_size_bottomright;
else
corner =
pick_corner(e->xmotion.x_root,
e->xmotion.y_root,
client->frame->area.x,
client->frame->area.y,
/* use the client size because the frame
can be differently sized (shaded
windows) and we want this based on the
clients size */
client->area.width +
client->frame->size.left +
client->frame->size.right,
client->area.height +
client->frame->size.top +
client->frame->size.bottom);
fire_motion(OB_MOUSE_ACTION_MOTION, context,
client, state, button, px, py, corner);
fire_binding(OB_MOUSE_ACTION_MOTION, context,
client, state, button, px, py);
button = 0;
state = 0;
}

View file

@ -3,18 +3,10 @@
#include "action.h"
#include "frame.h"
#include "misc.h"
#include <X11/Xlib.h>
typedef enum {
OB_MOUSE_ACTION_PRESS,
OB_MOUSE_ACTION_RELEASE,
OB_MOUSE_ACTION_CLICK,
OB_MOUSE_ACTION_DOUBLE_CLICK,
OB_MOUSE_ACTION_MOTION,
OB_MOUSE_NUM_ACTIONS
} ObMouseAction;
void mouse_startup(gboolean reconfig);
void mouse_shutdown(gboolean reconfig);