inline void client_action_end(union ActionData *data)
{
if (config_focus_follow)
- if (data->any.context != OB_FRAME_CONTEXT_CLIENT) {
- if (!data->any.button) {
- grab_pointer(FALSE, FALSE, OB_CURSOR_NONE);
- } else {
- ObClient *c;
-
- /* usually this is sorta redundant, but with a press action
- the enter event will come as a GrabNotify which is
- ignored, so this will handle that case */
- if ((c = client_under_pointer()))
- event_enter_client(c);
- }
- }
+ if (data->any.context != OB_FRAME_CONTEXT_CLIENT && !data->any.button)
+ grab_pointer(FALSE, FALSE, OB_CURSOR_NONE);
}
typedef struct
(*a)->data.cycle.forward = TRUE;
(*a)->data.cycle.dialog = TRUE;
(*a)->data.cycle.dock_windows = FALSE;
+ (*a)->data.cycle.all_desktops = FALSE;
}
void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
(*a)->data.cycle.forward = FALSE;
(*a)->data.cycle.dialog = TRUE;
(*a)->data.cycle.dock_windows = FALSE;
+ (*a)->data.cycle.all_desktops = FALSE;
}
void setup_action_movefromedge_north(ObAction **a, ObUserAction uact)
{
"activate",
action_activate,
- setup_client_action
+ setup_action_focus
},
{
"focus",
act->data.cycle.dialog = parse_bool(doc, n);
if ((n = parse_find_node("panels", node->xmlChildrenNode)))
act->data.cycle.dock_windows = parse_bool(doc, n);
+ if ((n = parse_find_node("allDesktops",
+ node->xmlChildrenNode)))
+ act->data.cycle.all_desktops = parse_bool(doc, n);
} else if (act->func == action_directional_focus) {
if ((n = parse_find_node("dialog", node->xmlChildrenNode)))
act->data.interdiraction.dialog = parse_bool(doc, n);
if (a->data.any.interactive || a->func == action_moveresize) {
/* interactive actions are not queued */
a->func(&a->data);
+ } else if ((context == OB_FRAME_CONTEXT_CLIENT ||
+ (c && c->type == OB_CLIENT_TYPE_DESKTOP &&
+ context == OB_FRAME_CONTEXT_DESKTOP)) &&
+ (a->func == action_focus ||
+ a->func == action_activate ||
+ a->func == action_showmenu))
+ {
+ /* XXX MORE UGLY HACK
+ actions from clicks on client windows are NOT queued.
+ this solves the mysterious click-and-drag-doesnt-work
+ problem. it was because the window gets focused and stuff
+ after the button event has already been passed through. i
+ dont really know why it should care but it does and it makes
+ a difference.
+
+ however this very bogus ! !
+ we want to send the button press to the window BEFORE
+ we do the action because the action might move the windows
+ (eg change desktops) and then the button press ends up on
+ the completely wrong window !
+ so, this is just for that bug, and it will only NOT queue it
+ if it is a focusing action that can be used with the mouse
+ pointer. ugh.
+
+ also with the menus, there is a race going on. if the
+ desktop wants to pop up a menu, and we do to, we send them
+ the button before we pop up the menu, so they pop up their
+ menu first. but not always. if we pop up our menu before
+ sending them the button press, then the result is
+ deterministic. yay.
+ */
+ a->func(&a->data);
} else
ob_main_loop_queue_action(ob_main_loop, a);
}
void action_activate(union ActionData *data)
{
- /* similar to the openbox dock for dockapps, don't let user actions give
- focus to 3rd-party docks (panels) either (unless they ask for it
- themselves). */
- if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) {
- /* if using focus_delay, stop the timer now so that focus doesn't go
- moving on us */
- event_halt_focus_delay();
+ if (data->client.any.c) {
+ if (!data->any.button || client_mouse_focusable(data->client.any.c) ||
+ data->any.context != OB_FRAME_CONTEXT_CLIENT)
+ {
+ /* if using focus_delay, stop the timer now so that focus doesn't
+ go moving on us */
+ event_halt_focus_delay();
- client_activate(data->activate.any.c, data->activate.here, TRUE);
+ client_activate(data->activate.any.c, data->activate.here, TRUE);
+ }
+ } else {
+ /* focus action on something other than a client, make keybindings
+ work for this openbox instance, but don't focus any specific client
+ */
+ focus_nothing();
}
}
void action_focus(union ActionData *data)
{
if (data->client.any.c) {
- /* similar to the openbox dock for dockapps, don't let user actions
- give focus to 3rd-party docks (panels) either (unless they ask for
- it themselves). */
- if (data->client.any.c->type != OB_CLIENT_TYPE_DOCK) {
+ if (!data->any.button || client_mouse_focusable(data->client.any.c) ||
+ data->any.context != OB_FRAME_CONTEXT_CLIENT)
+ {
/* if using focus_delay, stop the timer now so that focus doesn't
go moving on us */
event_halt_focus_delay();
if (cit == c) break;
if (client_normal(cit) == client_normal(c) &&
- cit->layer == c->layer &&
- cit->frame->visible &&
- !client_search_transient(c, cit))
+ cit->layer == c->layer &&
+ cit->frame->visible &&
+ !client_search_transient(c, cit))
{
if (RECT_INTERSECTS_RECT(cit->frame->area, c->frame->area)) {
raise = TRUE;
h = oh + data->relative.deltay * c->size_inc.height
+ data->relative.deltayu * c->size_inc.height;
- client_try_configure(c, OB_CORNER_TOPLEFT, &x, &y, &w, &h, &lw, &lh, TRUE);
+ client_try_configure(c, &x, &y, &w, &h, &lw, &lh, TRUE);
client_move_resize(c, x + (ow - w), y + (oh - h), w, h);
client_action_end(data);
}
data->sendto.desk == DESKTOP_ALL) {
client_set_desktop(c, data->sendto.desk, data->sendto.follow);
if (data->sendto.follow)
- screen_set_desktop(data->sendto.desk);
+ screen_set_desktop(data->sendto.desk, TRUE);
}
}
void action_desktop(union ActionData *data)
{
- static guint first = (unsigned) -1;
-
- if (data->inter.any.interactive && first == (unsigned) -1)
- first = screen_desktop;
-
if (!data->inter.any.interactive ||
(!data->inter.cancel && !data->inter.final))
{
if (data->desktop.desk < screen_num_desktops ||
data->desktop.desk == DESKTOP_ALL)
{
- screen_set_desktop(data->desktop.desk);
+ screen_set_desktop(data->desktop.desk, TRUE);
if (data->inter.any.interactive)
screen_desktop_popup(data->desktop.desk, TRUE);
}
- } else if (data->inter.cancel) {
- screen_set_desktop(first);
- }
-
- if (!data->inter.any.interactive || data->inter.final) {
+ } else
screen_desktop_popup(0, FALSE);
- first = (unsigned) -1;
- }
}
void action_desktop_dir(union ActionData *data)
data->desktopdir.inter.final,
data->desktopdir.inter.cancel);
if (!data->sendtodir.inter.any.interactive ||
- !data->sendtodir.inter.final ||
- data->sendtodir.inter.cancel)
+ (data->sendtodir.inter.final && !data->sendtodir.inter.cancel))
{
- screen_set_desktop(d);
+ if (d != screen_desktop) screen_set_desktop(d, TRUE);
}
}
data->sendtodir.inter.final,
data->sendtodir.inter.cancel);
if (!data->sendtodir.inter.any.interactive ||
- !data->sendtodir.inter.final ||
- data->sendtodir.inter.cancel)
+ (data->sendtodir.inter.final && !data->sendtodir.inter.cancel))
{
client_set_desktop(c, d, data->sendtodir.follow);
- if (data->sendtodir.follow)
- screen_set_desktop(d);
+ if (data->sendtodir.follow && d != screen_desktop)
+ screen_set_desktop(d, TRUE);
}
}
void action_desktop_last(union ActionData *data)
{
- screen_set_desktop(screen_last_desktop);
+ screen_set_desktop(screen_last_desktop, TRUE);
}
void action_toggle_decorations(union ActionData *data)
client_action_end(data);
}
-static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch)
+static guint32 pick_corner(gint x, gint y, gint cx, gint cy, gint cw, gint ch,
+ gboolean shaded)
{
/* let's make x and y client relative instead of screen relative */
x = x - cx;
|CCCCCCC | A B | DDDDDDD|
| CCCCCCCC | A | | B | DDDDDDDD |
| CCCCCCC A B DDDDDDD |
- - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - -
- | | b c | |
- | west | b move c | east |
- | | b c | |
- - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - -
+ - - - - - - - - - - - +CCCCCCC+aaaaaaa+DDDDDDD+ - - - - - - - - - - - -
+ | | b c | | sh
+ | west | b move c | east | ad
+ | | b c | | ed
+ - - - - - - - - - - - +EEEEEEE+ddddddd+FFFFFFF+- - - - - - - - - - - -
| EEEEEEE G H FFFFFFF |
| EEEEEEEE | G | | H | FFFFFFFF |
|EEEEEEE | G H | FFFFFFF|
+---------------------G-------|-------|-------H---------------------+
*/
+ if (shaded) {
+ /* for shaded windows, you can only resize west/east and move */
+ if (b)
+ return prop_atoms.net_wm_moveresize_size_left;
+ if (c)
+ return prop_atoms.net_wm_moveresize_size_right;
+ return prop_atoms.net_wm_moveresize_move;
+ }
+
if (y < A && y >= C)
return prop_atoms.net_wm_moveresize_size_topleft;
else if (y >= A && y >= B && a)
ObClient *c = data->moveresize.any.c;
guint32 corner;
- if (!client_normal(c)) return;
-
if (data->moveresize.keyboard) {
corner = (data->moveresize.move ?
prop_atoms.net_wm_moveresize_move_keyboard :
c->area.width + c->frame->size.left +
c->frame->size.right,
c->area.height + c->frame->size.top +
- c->frame->size.bottom));
- const gchar *c;
- if (corner == prop_atoms.net_wm_moveresize_size_topright)
- c = "topright";
- else if (corner == prop_atoms.net_wm_moveresize_size_top)
- c = "top";
- else if (corner == prop_atoms.net_wm_moveresize_size_topleft)
- c = "topleft";
- else if (corner == prop_atoms.net_wm_moveresize_size_right)
- c = "right";
- else if (corner == prop_atoms.net_wm_moveresize_move)
- c = "middle";
- else if (corner == prop_atoms.net_wm_moveresize_size_left)
- c = "left";
- else if (corner == prop_atoms.net_wm_moveresize_size_bottomright)
- c = "bottomright";
- else if (corner == prop_atoms.net_wm_moveresize_size_bottom)
- c = "bottom";
- else if (corner == prop_atoms.net_wm_moveresize_size_bottomleft)
- c = "bottomleft";
- ob_debug("corner: %s\n", c);
+ c->frame->size.bottom, c->shaded));
}
moveresize_start(c, data->any.x, data->any.y, data->any.button, corner);
{
if (data->showmenu.name) {
menu_show(data->showmenu.name, data->any.x, data->any.y,
- data->showmenu.any.c);
+ data->any.button, data->showmenu.any.c);
}
}
event_halt_focus_delay();
focus_cycle(data->cycle.forward,
+ data->cycle.all_desktops,
data->cycle.dock_windows,
data->cycle.linear, data->any.interactive,
data->cycle.dialog,
default:
g_assert_not_reached();
}
- frame_frame_gravity(c->frame, &x, &y);
+ frame_frame_gravity(c->frame, &x, &y, c->area.width, c->area.height);
client_action_start(data);
client_move(c, x, y);
client_action_end(data);
ObClient *c = data->diraction.any.c;
Rect *a;
- //FIXME growtoedge resizes shaded windows to 0 height
- if (c->shaded)
- return;
-
a = screen_area(c->desktop);
x = c->frame->area.x;
y = c->frame->area.y;
- width = c->frame->area.width;
- height = c->frame->area.height;
+ /* get the unshaded frame's dimensions..if it is shaded */
+ width = c->area.width + c->frame->size.left + c->frame->size.right;
+ height = c->area.height + c->frame->size.top + c->frame->size.bottom;
switch(data->diraction.direction) {
case OB_DIRECTION_NORTH:
+ if (c->shaded) break; /* don't allow vertical resize if shaded */
+
dest = client_directional_edge_search(c, OB_DIRECTION_NORTH, FALSE);
if (a->y == y)
- height = c->frame->area.height / 2;
+ height = height / 2;
else {
- height = c->frame->area.y + c->frame->area.height - dest;
+ height = c->frame->area.y + height - dest;
y = dest;
}
break;
case OB_DIRECTION_WEST:
dest = client_directional_edge_search(c, OB_DIRECTION_WEST, FALSE);
if (a->x == x)
- width = c->frame->area.width / 2;
+ width = width / 2;
else {
- width = c->frame->area.x + c->frame->area.width - dest;
+ width = c->frame->area.x + width - dest;
x = dest;
}
break;
case OB_DIRECTION_SOUTH:
+ if (c->shaded) break; /* don't allow vertical resize if shaded */
+
dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH, FALSE);
if (a->y + a->height == y + c->frame->area.height) {
height = c->frame->area.height / 2;
default:
g_assert_not_reached();
}
- frame_frame_gravity(c->frame, &x, &y);
width -= c->frame->size.left + c->frame->size.right;
height -= c->frame->size.top + c->frame->size.bottom;
+ frame_frame_gravity(c->frame, &x, &y, width, height);
client_action_start(data);
client_move_resize(c, x, y, width, height);
client_action_end(data);
void action_toggle_show_desktop(union ActionData *data)
{
- screen_show_desktop(!screen_showing_desktop);
+ screen_show_desktop(!screen_showing_desktop, TRUE);
}
void action_show_desktop(union ActionData *data)
{
- screen_show_desktop(TRUE);
+ screen_show_desktop(TRUE, TRUE);
}
void action_unshow_desktop(union ActionData *data)
{
- screen_show_desktop(FALSE);
+ screen_show_desktop(FALSE, TRUE);
}
void action_break_chroot(union ActionData *data)