/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
action.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
Copyright (c) 2003 Ben Jansens
This program is free software; you can redistribute it and/or modify
#include "dock.h"
#include "config.h"
#include "mainloop.h"
+#include "startupnotify.h"
#include <glib.h>
(*a)->data.cycle.dialog = TRUE;
}
+void setup_action_movefromedge_north(ObAction **a, ObUserAction uact)
+{
+ (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
+ (*a)->data.diraction.direction = OB_DIRECTION_NORTH;
+ (*a)->data.diraction.hang = TRUE;
+}
+
+void setup_action_movefromedge_south(ObAction **a, ObUserAction uact)
+{
+ (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
+ (*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
+ (*a)->data.diraction.hang = TRUE;
+}
+
+void setup_action_movefromedge_east(ObAction **a, ObUserAction uact)
+{
+ (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
+ (*a)->data.diraction.direction = OB_DIRECTION_EAST;
+ (*a)->data.diraction.hang = TRUE;
+}
+
+void setup_action_movefromedge_west(ObAction **a, ObUserAction uact)
+{
+ (*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
+ (*a)->data.diraction.direction = OB_DIRECTION_WEST;
+ (*a)->data.diraction.hang = TRUE;
+}
+
void setup_action_movetoedge_north(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_NORTH;
+ (*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_south(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_SOUTH;
+ (*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_east(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_EAST;
+ (*a)->data.diraction.hang = FALSE;
}
void setup_action_movetoedge_west(ObAction **a, ObUserAction uact)
{
(*a)->data.diraction.any.client_action = OB_CLIENT_ACTION_ALWAYS;
(*a)->data.diraction.direction = OB_DIRECTION_WEST;
+ (*a)->data.diraction.hang = FALSE;
}
void setup_action_growtoedge_north(ObAction **a, ObUserAction uact)
action_cycle_windows,
setup_action_cycle_windows_previous
},
+ {
+ "movefromedgenorth",
+ action_movetoedge,
+ setup_action_movefromedge_north
+ },
+ {
+ "movefromedgesouth",
+ action_movetoedge,
+ setup_action_movefromedge_south
+ },
+ {
+ "movefromedgewest",
+ action_movetoedge,
+ setup_action_movefromedge_west
+ },
+ {
+ "movefromedgeeast",
+ action_movetoedge,
+ setup_action_movefromedge_east
+ },
{
"movetoedgenorth",
action_movetoedge,
act->data.execute.path = parse_expand_tilde(s);
g_free(s);
}
+ if ((n = parse_find_node("startupnotify", node->xmlChildrenNode))) {
+ xmlNodePtr m;
+ if ((m = parse_find_node("enabled", n->xmlChildrenNode)))
+ act->data.execute.startupnotify = parse_bool(doc, m);
+ if ((m = parse_find_node("name", n->xmlChildrenNode)))
+ act->data.execute.name = parse_string(doc, m);
+ if ((m = parse_find_node("icon", n->xmlChildrenNode)))
+ act->data.execute.icon_name = parse_string(doc, m);
+ }
} else if (act->func == action_showmenu) {
if ((n = parse_find_node("menu", node->xmlChildrenNode)))
act->data.showmenu.name = parse_string(doc, n);
act->func == action_raiselower ||
act->func == action_shadelower ||
act->func == action_unshaderaise) {
- if ((n = parse_find_node("group", node->xmlChildrenNode)))
- act->data.stacking.group = parse_bool(doc, n);
}
INTERACTIVE_LIMIT(act, uact);
}
}
void action_run_list(GSList *acts, ObClient *c, ObFrameContext context,
- guint state, guint button, gint x, gint y,
+ guint state, guint button, gint x, gint y, Time time,
gboolean cancel, gboolean done)
{
GSList *it;
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);
+ XUngrabKeyboard(ob_display, event_curtime);
}
for (it = acts; it; it = g_slist_next(it)) {
a->data.any.button = button;
+ a->data.any.time = time;
+
if (a->data.any.interactive) {
a->data.inter.cancel = cancel;
a->data.inter.final = done;
}
}
-void action_run_string(const gchar *name, struct _ObClient *c)
+void action_run_string(const gchar *name, struct _ObClient *c, Time time)
{
ObAction *a;
GSList *l;
l = g_slist_append(NULL, a);
- action_run(l, c, 0);
+ action_run(l, c, 0, time);
}
void action_execute(union ActionData *data)
g_warning("failed to execute '%s': %s",
cmd, e->message);
g_error_free(e);
+ } else if (data->execute.startupnotify) {
+ gchar **env, *program;
+
+ program = g_path_get_basename(argv[0]);
+ env = sn_get_spawn_environment(program,
+ data->execute.name,
+ data->execute.icon_name,
+ data->execute.any.time);
+ if (!g_spawn_async(NULL, argv, env, G_SPAWN_SEARCH_PATH |
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, NULL, &e)) {
+ g_warning("failed to execute '%s': %s",
+ cmd, e->message);
+ g_error_free(e);
+ sn_spawn_cancel();
+ }
+ g_strfreev(env);
+ g_free(program);
+ g_strfreev(argv);
} else {
if (!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH |
G_SPAWN_DO_NOT_REAP_CHILD,
- NULL, NULL, NULL, &e)) {
+ NULL, NULL, NULL, &e))
+ {
g_warning("failed to execute '%s': %s",
cmd, e->message);
g_error_free(e);
void action_activate(union ActionData *data)
{
- client_activate(data->activate.any.c, data->activate.here);
+ /* 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();
+
+ client_activate(data->activate.any.c, data->activate.here, TRUE,
+ data->activate.any.time);
+ }
}
void action_focus(union ActionData *data)
{
- /* if using focus_delay, stop the timer now so that focus doesn't go moving
- on us */
- event_halt_focus_delay();
+ /* 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();
- client_focus(data->client.any.c);
+ if (client_validate(data->client.any.c))
+ client_focus(data->client.any.c);
+ }
}
void action_unfocus (union ActionData *data)
{
- if (data->client.any.c == focus_client);
+ if (data->client.any.c == focus_client)
focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING);
}
void action_raise(union ActionData *data)
{
client_action_start(data);
- stacking_raise(CLIENT_AS_WINDOW(data->client.any.c), data->stacking.group);
+ stacking_raise(CLIENT_AS_WINDOW(data->client.any.c));
client_action_end(data);
}
void action_lower(union ActionData *data)
{
client_action_start(data);
- stacking_lower(CLIENT_AS_WINDOW(data->client.any.c), data->stacking.group);
+ stacking_lower(CLIENT_AS_WINDOW(data->client.any.c));
client_action_end(data);
}
focus_cycle(data->cycle.forward, data->cycle.linear, data->any.interactive,
data->cycle.dialog,
- data->cycle.inter.final, data->cycle.inter.cancel);
+ data->cycle.inter.final, data->cycle.inter.cancel,
+ data->cycle.inter.any.time);
}
void action_directional_focus(union ActionData *data)
data->any.interactive,
data->interdiraction.dialog,
data->interdiraction.inter.final,
- data->interdiraction.inter.cancel);
+ data->interdiraction.inter.cancel,
+ data->interdiraction.inter.any.time);
}
void action_movetoedge(union ActionData *data)
switch(data->diraction.direction) {
case OB_DIRECTION_NORTH:
- y = client_directional_edge_search(c, OB_DIRECTION_NORTH);
+ y = client_directional_edge_search(c, OB_DIRECTION_NORTH,
+ data->diraction.hang)
+ - (data->diraction.hang ? c->frame->area.height : 0);
break;
case OB_DIRECTION_WEST:
- x = client_directional_edge_search(c, OB_DIRECTION_WEST);
+ x = client_directional_edge_search(c, OB_DIRECTION_WEST,
+ data->diraction.hang)
+ - (data->diraction.hang ? c->frame->area.width : 0);
break;
case OB_DIRECTION_SOUTH:
- y = client_directional_edge_search(c, OB_DIRECTION_SOUTH) -
- c->frame->area.height;
+ y = client_directional_edge_search(c, OB_DIRECTION_SOUTH,
+ data->diraction.hang)
+ - (data->diraction.hang ? 0 : c->frame->area.height);
break;
case OB_DIRECTION_EAST:
- x = client_directional_edge_search(c, OB_DIRECTION_EAST) -
- c->frame->area.width;
+ x = client_directional_edge_search(c, OB_DIRECTION_EAST,
+ data->diraction.hang)
+ - (data->diraction.hang ? 0 : c->frame->area.width);
break;
default:
g_assert_not_reached();
switch(data->diraction.direction) {
case OB_DIRECTION_NORTH:
- dest = client_directional_edge_search(c, OB_DIRECTION_NORTH);
+ dest = client_directional_edge_search(c, OB_DIRECTION_NORTH, FALSE);
if (a->y == y)
height = c->frame->area.height / 2;
else {
}
break;
case OB_DIRECTION_WEST:
- dest = client_directional_edge_search(c, OB_DIRECTION_WEST);
+ dest = client_directional_edge_search(c, OB_DIRECTION_WEST, FALSE);
if (a->x == x)
width = c->frame->area.width / 2;
else {
}
break;
case OB_DIRECTION_SOUTH:
- dest = client_directional_edge_search(c, OB_DIRECTION_SOUTH);
+ 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;
y = a->y + a->height - height;
height -= (height - c->frame->area.height) % c->size_inc.height;
break;
case OB_DIRECTION_EAST:
- dest = client_directional_edge_search(c, OB_DIRECTION_EAST);
+ dest = client_directional_edge_search(c, OB_DIRECTION_EAST, FALSE);
if (a->x + a->width == x + c->frame->area.width) {
width = c->frame->area.width / 2;
x = a->x + a->width - width;