-/* -*- indent-tabs-mode: t; tab-width: 4; c-basic-offset: 4; -*-
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
action.c for the Openbox window manager
Copyright (c) 2003 Ben Jansens
#include "openbox.h"
#include "grab.h"
#include "keyboard.h"
+#include "event.h"
+#include "config.h"
#include <glib.h>
-typedef struct ActionString {
- char *name;
+inline void client_action_start(union ActionData *data)
+{
+ if (config_focus_follow)
+ if (data->any.context != OB_FRAME_CONTEXT_CLIENT && !data->any.button)
+ grab_pointer(TRUE, OB_CURSOR_NONE);
+}
+
+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, 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);
+ }
+ }
+}
+
+typedef struct
+{
+ const gchar *name;
void (*func)(union ActionData *);
void (*setup)(ObAction **, ObUserAction uact);
} ActionString;
}
};
-ObAction *action_from_string(char *name, ObUserAction uact)
+ObAction *action_from_string(const gchar *name, ObUserAction uact)
{
ObAction *a = NULL;
gboolean exist = FALSE;
return act;
}
-void action_run_full(ObAction *a, struct _ObClient *c,
+void action_run_list(GSList *acts, ObClient *c, ObFrameContext context,
guint state, guint button, gint x, gint y,
gboolean cancel, gboolean done)
{
+ GSList *it;
+ ObAction *a;
+ gboolean inter = FALSE;
+
+ if (!acts)
+ return;
+
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 (grab_on_keyboard())
+ inter = TRUE;
+ else
+ for (it = acts; it; it = g_slist_next(it)) {
+ a = it->data;
+ if (a->data.any.interactive) {
+ inter = TRUE;
+ break;
+ }
+ }
- if (a->data.any.interactive) {
- a->data.inter.cancel = cancel;
- a->data.inter.final = done;
- if (!(cancel || done))
- keyboard_interactive_grab(state, c, a);
+ if (!inter) {
+ /* sometimes when we execute another app as an action,
+ it won't work right unless we XUngrabKeyboard first,
+ even though we grabbed the key/button Asychronously.
+ e.g. "gnome-panel-control --main-menu" */
+ XUngrabKeyboard(ob_display, event_lasttime);
}
- a->func(&a->data);
+ for (it = acts; it; it = g_slist_next(it)) {
+ a = it->data;
+
+ a->data.any.c = c;
+ a->data.any.context = context;
+ 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, a);
+ }
+
+ a->func(&a->data);
+ }
}
void action_execute(union ActionData *data)
}
}
- if (raise)
+ if (raise) {
+ client_action_start(data);
stacking_raise(CLIENT_AS_WINDOW(c));
- else
+ client_action_end(data);
+ } else {
+ client_action_start(data);
stacking_lower(CLIENT_AS_WINDOW(c));
+ client_action_end(data);
+ }
}
void action_raise(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
stacking_raise(CLIENT_AS_WINDOW(data->client.any.c));
+ client_action_end(data);
+ }
}
void action_unshaderaise(union ActionData *data)
{
if (data->client.any.c) {
if (data->client.any.c->shaded) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_shade(data->client.any.c, FALSE);
- grab_pointer(FALSE, OB_CURSOR_NONE);
- } else
+ client_action_end(data);
+ } else {
+ client_action_start(data);
stacking_raise(CLIENT_AS_WINDOW(data->client.any.c));
+ client_action_end(data);
+ }
}
}
if (data->client.any.c->shaded)
stacking_lower(CLIENT_AS_WINDOW(data->client.any.c));
else {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_shade(data->client.any.c, TRUE);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
}
void action_lower(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
stacking_lower(CLIENT_AS_WINDOW(data->client.any.c));
+ client_action_end(data);
+ }
}
void action_close(union ActionData *data)
void action_shade(union ActionData *data)
{
if (data->client.any.c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_shade(data->client.any.c, TRUE);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
void action_unshade(union ActionData *data)
{
if (data->client.any.c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_shade(data->client.any.c, FALSE);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
void action_toggle_shade(union ActionData *data)
{
if (data->client.any.c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_shade(data->client.any.c, !data->client.any.c->shaded);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
{
ObClient *c = data->relative.any.c;
if (c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_move(c, c->area.x + data->relative.delta, c->area.y);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
{
ObClient *c = data->relative.any.c;
if (c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_move(c, c->area.x, c->area.y + data->relative.delta);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
{
ObClient *c = data->relative.any.c;
if (c) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_resize(c,
c->area.width + data->relative.delta * c->size_inc.width,
c->area.height);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
{
ObClient *c = data->relative.any.c;
if (c && !c->shaded) {
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_resize(c, c->area.width, c->area.height +
data->relative.delta * c->size_inc.height);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
}
void action_maximize_full(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, TRUE, 0, TRUE);
+ client_action_end(data);
+ }
}
void action_unmaximize_full(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, FALSE, 0, TRUE);
+ client_action_end(data);
+ }
}
void action_toggle_maximize_full(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c,
!(data->client.any.c->max_horz ||
data->client.any.c->max_vert),
0, TRUE);
+ client_action_end(data);
+ }
}
void action_maximize_horz(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, TRUE, 1, TRUE);
+ client_action_end(data);
+ }
}
void action_unmaximize_horz(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, FALSE, 1, TRUE);
+ client_action_end(data);
+ }
}
void action_toggle_maximize_horz(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c,
!data->client.any.c->max_horz, 1, TRUE);
+ client_action_end(data);
+ }
}
void action_maximize_vert(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, TRUE, 2, TRUE);
+ client_action_end(data);
+ }
}
void action_unmaximize_vert(union ActionData *data)
{
- if (data->client.any.c)
+ if (data->client.any.c) {
+ client_action_start(data);
client_maximize(data->client.any.c, FALSE, 2, TRUE);
+ client_action_end(data);
+ }
}
void action_toggle_maximize_vert(union ActionData *data)
{
- if (data->client.any.c)
- client_maximize(data->client.any.c, !data->client.any.c->max_vert, 2, TRUE);
+ if (data->client.any.c) {
+ client_action_start(data);
+ client_maximize(data->client.any.c,
+ !data->client.any.c->max_vert, 2, TRUE);
+ client_action_end(data);
+ }
}
void action_send_to_desktop(union ActionData *data)
data->desktopdir.inter.any.interactive,
data->desktopdir.inter.final,
data->desktopdir.inter.cancel);
- screen_set_desktop(d);
+ if (!data->sendtodir.inter.any.interactive ||
+ !data->sendtodir.inter.final)
+ {
+ screen_set_desktop(d);
+ }
}
void action_send_to_desktop_dir(union ActionData *data)
data->sendtodir.inter.any.interactive,
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.inter.any.interactive ||
+ !data->sendtodir.inter.final)
+ {
+ client_set_desktop(c, d, data->sendtodir.follow);
+ if (data->sendtodir.follow)
+ screen_set_desktop(d);
+ }
}
void action_desktop_last(union ActionData *data)
{
ObClient *c = data->client.any.c;
- if (!c) return;
-
- c->decorate = !c->decorate;
- client_setup_decor_and_functions(c);
+ if (c) {
+ client_action_start(data);
+ c->decorate = !c->decorate;
+ client_setup_decor_and_functions(c);
+ client_action_end(data);
+ }
}
static guint32 pick_corner(int x, int y, int cx, int cy, int cw, int ch)
g_assert_not_reached();
}
frame_frame_gravity(c->frame, &x, &y);
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_move(c, x, y);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
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;
- grab_pointer(TRUE, OB_CURSOR_NONE);
+ client_action_start(data);
client_move_resize(c, x, y, width, height);
- grab_pointer(FALSE, OB_CURSOR_NONE);
+ client_action_end(data);
}
void action_send_to_layer(union ActionData *data)
ObClient *c = data->layer.any.c;
if (c) {
+ client_action_start(data);
if (data->layer.layer < 0)
client_set_layer(c, c->below ? 0 : -1);
else if (data->layer.layer > 0)
client_set_layer(c, c->above ? 0 : 1);
+ client_action_end(data);
}
}