cycling between dock windows now possible with the <panels>yes</panels> option
This commit is contained in:
parent
33e017838f
commit
9f11e2af6b
6 changed files with 154 additions and 129 deletions
|
@ -119,6 +119,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_east(ObAction **a, ObUserAction uact)
|
||||
|
@ -126,6 +127,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_south(ObAction **a, ObUserAction uact)
|
||||
|
@ -133,6 +135,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_west(ObAction **a, ObUserAction uact)
|
||||
|
@ -140,6 +143,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_northeast(ObAction **a, ObUserAction uact)
|
||||
|
@ -147,6 +151,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_southeast(ObAction **a, ObUserAction uact)
|
||||
|
@ -154,6 +159,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_southwest(ObAction **a, ObUserAction uact)
|
||||
|
@ -161,6 +167,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_directional_focus_northwest(ObAction **a, ObUserAction uact)
|
||||
|
@ -168,6 +175,7 @@ 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.dialog = TRUE;
|
||||
(*a)->data.interdiraction.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_send_to_desktop(ObAction **a, ObUserAction uact)
|
||||
|
@ -295,6 +303,7 @@ void setup_action_cycle_windows_next(ObAction **a, ObUserAction uact)
|
|||
(*a)->data.cycle.linear = FALSE;
|
||||
(*a)->data.cycle.forward = TRUE;
|
||||
(*a)->data.cycle.dialog = TRUE;
|
||||
(*a)->data.cycle.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
|
||||
|
@ -303,6 +312,7 @@ void setup_action_cycle_windows_previous(ObAction **a, ObUserAction uact)
|
|||
(*a)->data.cycle.linear = FALSE;
|
||||
(*a)->data.cycle.forward = FALSE;
|
||||
(*a)->data.cycle.dialog = TRUE;
|
||||
(*a)->data.cycle.dock_windows = FALSE;
|
||||
}
|
||||
|
||||
void setup_action_movefromedge_north(ObAction **a, ObUserAction uact)
|
||||
|
@ -1003,9 +1013,13 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
|
|||
act->data.cycle.linear = parse_bool(doc, n);
|
||||
if ((n = parse_find_node("dialog", node->xmlChildrenNode)))
|
||||
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);
|
||||
} else if (act->func == action_directional_focus) {
|
||||
if ((n = parse_find_node("dialog", node->xmlChildrenNode)))
|
||||
act->data.cycle.dialog = parse_bool(doc, n);
|
||||
act->data.interdiraction.dialog = parse_bool(doc, n);
|
||||
if ((n = parse_find_node("panels", node->xmlChildrenNode)))
|
||||
act->data.interdiraction.dock_windows = parse_bool(doc, n);
|
||||
} else if (act->func == action_raise ||
|
||||
act->func == action_lower ||
|
||||
act->func == action_raiselower ||
|
||||
|
@ -1647,7 +1661,9 @@ void action_cycle_windows(union ActionData *data)
|
|||
on us */
|
||||
event_halt_focus_delay();
|
||||
|
||||
focus_cycle(data->cycle.forward, data->cycle.linear, data->any.interactive,
|
||||
focus_cycle(data->cycle.forward,
|
||||
data->cycle.dock_windows,
|
||||
data->cycle.linear, data->any.interactive,
|
||||
data->cycle.dialog,
|
||||
data->cycle.inter.final, data->cycle.inter.cancel);
|
||||
}
|
||||
|
@ -1659,6 +1675,7 @@ void action_directional_focus(union ActionData *data)
|
|||
event_halt_focus_delay();
|
||||
|
||||
focus_directional_cycle(data->interdiraction.direction,
|
||||
data->interdiraction.dock_windows,
|
||||
data->any.interactive,
|
||||
data->interdiraction.dialog,
|
||||
data->interdiraction.inter.final,
|
||||
|
|
|
@ -61,6 +61,7 @@ struct InterDirectionalAction{
|
|||
struct InteractiveAction inter;
|
||||
ObDirection direction;
|
||||
gboolean dialog;
|
||||
gboolean dock_windows;
|
||||
};
|
||||
|
||||
struct DirectionalAction{
|
||||
|
@ -141,6 +142,7 @@ struct CycleWindows {
|
|||
gboolean linear;
|
||||
gboolean forward;
|
||||
gboolean dialog;
|
||||
gboolean dock_windows;
|
||||
};
|
||||
|
||||
struct Stacking {
|
||||
|
|
101
openbox/client.c
101
openbox/client.c
|
@ -3188,107 +3188,6 @@ const ObClientIcon* client_icon(ObClient *self, gint w, gint h)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* this be mostly ripped from fvwm */
|
||||
ObClient *client_find_directional(ObClient *c, ObDirection dir)
|
||||
{
|
||||
gint my_cx, my_cy, his_cx, his_cy;
|
||||
gint offset = 0;
|
||||
gint distance = 0;
|
||||
gint score, best_score;
|
||||
ObClient *best_client, *cur;
|
||||
GList *it;
|
||||
|
||||
if(!client_list)
|
||||
return NULL;
|
||||
|
||||
/* first, find the centre coords of the currently focused window */
|
||||
my_cx = c->frame->area.x + c->frame->area.width / 2;
|
||||
my_cy = c->frame->area.y + c->frame->area.height / 2;
|
||||
|
||||
best_score = -1;
|
||||
best_client = NULL;
|
||||
|
||||
for(it = g_list_first(client_list); it; it = g_list_next(it)) {
|
||||
cur = it->data;
|
||||
|
||||
/* the currently selected window isn't interesting */
|
||||
if(cur == c)
|
||||
continue;
|
||||
if (!client_normal(cur))
|
||||
continue;
|
||||
/* using c->desktop instead of screen_desktop doesn't work if the
|
||||
* current window was omnipresent, hope this doesn't have any other
|
||||
* side effects */
|
||||
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
|
||||
continue;
|
||||
if(cur->iconic)
|
||||
continue;
|
||||
if(!(client_focus_target(cur) == cur &&
|
||||
client_can_focus(cur)))
|
||||
continue;
|
||||
|
||||
/* find the centre coords of this window, from the
|
||||
* currently focused window's point of view */
|
||||
his_cx = (cur->frame->area.x - my_cx)
|
||||
+ cur->frame->area.width / 2;
|
||||
his_cy = (cur->frame->area.y - my_cy)
|
||||
+ cur->frame->area.height / 2;
|
||||
|
||||
if(dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST ||
|
||||
dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST) {
|
||||
gint tx;
|
||||
/* Rotate the diagonals 45 degrees counterclockwise.
|
||||
* To do this, multiply the matrix /+h +h\ with the
|
||||
* vector (x y). \-h +h/
|
||||
* h = sqrt(0.5). We can set h := 1 since absolute
|
||||
* distance doesn't matter here. */
|
||||
tx = his_cx + his_cy;
|
||||
his_cy = -his_cx + his_cy;
|
||||
his_cx = tx;
|
||||
}
|
||||
|
||||
switch(dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_SOUTH:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
offset = (his_cx < 0) ? -his_cx : his_cx;
|
||||
distance = ((dir == OB_DIRECTION_NORTH ||
|
||||
dir == OB_DIRECTION_NORTHEAST) ?
|
||||
-his_cy : his_cy);
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_WEST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
offset = (his_cy < 0) ? -his_cy : his_cy;
|
||||
distance = ((dir == OB_DIRECTION_WEST ||
|
||||
dir == OB_DIRECTION_NORTHWEST) ?
|
||||
-his_cx : his_cx);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the target must be in the requested direction */
|
||||
if(distance <= 0)
|
||||
continue;
|
||||
|
||||
/* Calculate score for this window. The smaller the better. */
|
||||
score = distance + offset;
|
||||
|
||||
/* windows more than 45 degrees off the direction are
|
||||
* heavily penalized and will only be chosen if nothing
|
||||
* else within a million pixels */
|
||||
if(offset > distance)
|
||||
score += 1000000;
|
||||
|
||||
if(best_score == -1 || score < best_score)
|
||||
best_client = cur,
|
||||
best_score = score;
|
||||
}
|
||||
|
||||
return best_client;
|
||||
}
|
||||
|
||||
void client_set_layer(ObClient *self, gint layer)
|
||||
{
|
||||
if (layer < 0) {
|
||||
|
|
|
@ -620,9 +620,6 @@ ObClient *client_search_parent(ObClient *self, ObClient *search);
|
|||
NULL is returned if the given search is not a transient of the client. */
|
||||
ObClient *client_search_transient(ObClient *self, ObClient *search);
|
||||
|
||||
/*! Return the "closest" client in the given direction */
|
||||
ObClient *client_find_directional(ObClient *c, ObDirection dir);
|
||||
|
||||
/*! Return the closest edge in the given direction */
|
||||
gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang);
|
||||
|
||||
|
|
150
openbox/focus.c
150
openbox/focus.c
|
@ -59,7 +59,7 @@ static void focus_cycle_destructor(ObClient *client, gpointer data)
|
|||
be used
|
||||
*/
|
||||
if (focus_cycle_target == client)
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
static Window createWindow(Window parent, gulong mask,
|
||||
|
@ -168,7 +168,7 @@ void focus_set_client(ObClient *client)
|
|||
be used.
|
||||
*/
|
||||
if (focus_cycle_target)
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
|
||||
focus_client = client;
|
||||
|
||||
|
@ -468,23 +468,27 @@ void focus_cycle_draw_indicator()
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean valid_focus_target(ObClient *ft)
|
||||
static gboolean valid_focus_target(ObClient *ft, gboolean dock_windows)
|
||||
{
|
||||
gboolean ok = FALSE;
|
||||
/* we don't use client_can_focus here, because that doesn't let you
|
||||
focus an iconic window, but we want to be able to, so we just check
|
||||
if the focus flags on the window allow it, and its on the current
|
||||
desktop */
|
||||
if ((ft->type == OB_CLIENT_TYPE_NORMAL ||
|
||||
ft->type == OB_CLIENT_TYPE_DIALOG ||
|
||||
(!client_has_group_siblings(ft) &&
|
||||
(ft->type == OB_CLIENT_TYPE_TOOLBAR ||
|
||||
ft->type == OB_CLIENT_TYPE_MENU ||
|
||||
ft->type == OB_CLIENT_TYPE_UTILITY))) &&
|
||||
((ft->can_focus || ft->focus_notify) &&
|
||||
!ft->skip_pager &&
|
||||
(ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) &&
|
||||
ft == client_focus_target(ft))
|
||||
return TRUE;
|
||||
if (dock_windows)
|
||||
ok = ft->type == OB_CLIENT_TYPE_DOCK;
|
||||
else
|
||||
ok = (ft->type == OB_CLIENT_TYPE_NORMAL ||
|
||||
ft->type == OB_CLIENT_TYPE_DIALOG ||
|
||||
(!client_has_group_siblings(ft) &&
|
||||
(ft->type == OB_CLIENT_TYPE_TOOLBAR ||
|
||||
ft->type == OB_CLIENT_TYPE_MENU ||
|
||||
ft->type == OB_CLIENT_TYPE_UTILITY)));
|
||||
ok = ok && (ft->can_focus || ft->focus_notify);
|
||||
ok = ok && !ft->skip_pager;
|
||||
ok = ok && (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL);
|
||||
ok = ok && ft == client_focus_target(ft);
|
||||
return ok;
|
||||
/*
|
||||
{
|
||||
GSList *it;
|
||||
|
@ -498,11 +502,10 @@ static gboolean valid_focus_target(ObClient *ft)
|
|||
return TRUE;
|
||||
}
|
||||
*/
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
|
||||
void focus_cycle(gboolean forward, gboolean dock_windows,
|
||||
gboolean linear, gboolean interactive,
|
||||
gboolean dialog, gboolean done, gboolean cancel)
|
||||
{
|
||||
static ObClient *first = NULL;
|
||||
|
@ -546,7 +549,7 @@ void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
|
|||
if (it == NULL) it = g_list_last(list);
|
||||
}
|
||||
ft = it->data;
|
||||
if (valid_focus_target(ft)) {
|
||||
if (valid_focus_target(ft, dock_windows)) {
|
||||
if (interactive) {
|
||||
if (ft != focus_cycle_target) { /* prevents flicker */
|
||||
focus_cycle_target = ft;
|
||||
|
@ -580,7 +583,112 @@ done_cycle:
|
|||
return;
|
||||
}
|
||||
|
||||
void focus_directional_cycle(ObDirection dir, gboolean interactive,
|
||||
/* this be mostly ripped from fvwm */
|
||||
ObClient *focus_find_directional(ObClient *c, ObDirection dir,
|
||||
gboolean dock_windows)
|
||||
{
|
||||
gint my_cx, my_cy, his_cx, his_cy;
|
||||
gint offset = 0;
|
||||
gint distance = 0;
|
||||
gint score, best_score;
|
||||
ObClient *best_client, *cur;
|
||||
GList *it;
|
||||
|
||||
if(!client_list)
|
||||
return NULL;
|
||||
|
||||
/* first, find the centre coords of the currently focused window */
|
||||
my_cx = c->frame->area.x + c->frame->area.width / 2;
|
||||
my_cy = c->frame->area.y + c->frame->area.height / 2;
|
||||
|
||||
best_score = -1;
|
||||
best_client = NULL;
|
||||
|
||||
for(it = g_list_first(client_list); it; it = g_list_next(it)) {
|
||||
cur = it->data;
|
||||
|
||||
/* the currently selected window isn't interesting */
|
||||
if(cur == c)
|
||||
continue;
|
||||
if (!dock_windows && !client_normal(cur))
|
||||
continue;
|
||||
if (dock_windows && cur->type != OB_CLIENT_TYPE_DOCK)
|
||||
continue;
|
||||
/* using c->desktop instead of screen_desktop doesn't work if the
|
||||
* current window was omnipresent, hope this doesn't have any other
|
||||
* side effects */
|
||||
if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
|
||||
continue;
|
||||
if(cur->iconic)
|
||||
continue;
|
||||
if(!(client_focus_target(cur) == cur &&
|
||||
client_can_focus(cur)))
|
||||
continue;
|
||||
|
||||
/* find the centre coords of this window, from the
|
||||
* currently focused window's point of view */
|
||||
his_cx = (cur->frame->area.x - my_cx)
|
||||
+ cur->frame->area.width / 2;
|
||||
his_cy = (cur->frame->area.y - my_cy)
|
||||
+ cur->frame->area.height / 2;
|
||||
|
||||
if(dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST ||
|
||||
dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST) {
|
||||
gint tx;
|
||||
/* Rotate the diagonals 45 degrees counterclockwise.
|
||||
* To do this, multiply the matrix /+h +h\ with the
|
||||
* vector (x y). \-h +h/
|
||||
* h = sqrt(0.5). We can set h := 1 since absolute
|
||||
* distance doesn't matter here. */
|
||||
tx = his_cx + his_cy;
|
||||
his_cy = -his_cx + his_cy;
|
||||
his_cx = tx;
|
||||
}
|
||||
|
||||
switch(dir) {
|
||||
case OB_DIRECTION_NORTH:
|
||||
case OB_DIRECTION_SOUTH:
|
||||
case OB_DIRECTION_NORTHEAST:
|
||||
case OB_DIRECTION_SOUTHWEST:
|
||||
offset = (his_cx < 0) ? -his_cx : his_cx;
|
||||
distance = ((dir == OB_DIRECTION_NORTH ||
|
||||
dir == OB_DIRECTION_NORTHEAST) ?
|
||||
-his_cy : his_cy);
|
||||
break;
|
||||
case OB_DIRECTION_EAST:
|
||||
case OB_DIRECTION_WEST:
|
||||
case OB_DIRECTION_SOUTHEAST:
|
||||
case OB_DIRECTION_NORTHWEST:
|
||||
offset = (his_cy < 0) ? -his_cy : his_cy;
|
||||
distance = ((dir == OB_DIRECTION_WEST ||
|
||||
dir == OB_DIRECTION_NORTHWEST) ?
|
||||
-his_cx : his_cx);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the target must be in the requested direction */
|
||||
if(distance <= 0)
|
||||
continue;
|
||||
|
||||
/* Calculate score for this window. The smaller the better. */
|
||||
score = distance + offset;
|
||||
|
||||
/* windows more than 45 degrees off the direction are
|
||||
* heavily penalized and will only be chosen if nothing
|
||||
* else within a million pixels */
|
||||
if(offset > distance)
|
||||
score += 1000000;
|
||||
|
||||
if(best_score == -1 || score < best_score)
|
||||
best_client = cur,
|
||||
best_score = score;
|
||||
}
|
||||
|
||||
return best_client;
|
||||
}
|
||||
|
||||
void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
|
||||
gboolean interactive,
|
||||
gboolean dialog, gboolean done, gboolean cancel)
|
||||
{
|
||||
static ObClient *first = NULL;
|
||||
|
@ -602,12 +710,12 @@ void focus_directional_cycle(ObDirection dir, gboolean interactive,
|
|||
if (!focus_cycle_target) focus_cycle_target = focus_client;
|
||||
|
||||
if (focus_cycle_target)
|
||||
ft = client_find_directional(focus_cycle_target, dir);
|
||||
ft = focus_find_directional(focus_cycle_target, dir, dock_windows);
|
||||
else {
|
||||
GList *it;
|
||||
|
||||
for (it = focus_order; it; it = g_list_next(it))
|
||||
if (valid_focus_target(it->data))
|
||||
if (valid_focus_target(it->data, dock_windows))
|
||||
ft = it->data;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,9 +52,11 @@ struct _ObClient* focus_fallback_target(gboolean allow_refocus,
|
|||
void focus_fallback(gboolean allow_refocus);
|
||||
|
||||
/*! Cycle focus amongst windows. */
|
||||
void focus_cycle(gboolean forward, gboolean linear, gboolean interactive,
|
||||
void focus_cycle(gboolean forward, gboolean dock_windows,
|
||||
gboolean linear, gboolean interactive,
|
||||
gboolean dialog, gboolean done, gboolean cancel);
|
||||
void focus_directional_cycle(ObDirection dir, gboolean interactive,
|
||||
void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
|
||||
gboolean interactive,
|
||||
gboolean dialog, gboolean done, gboolean cancel);
|
||||
void focus_cycle_draw_indicator();
|
||||
|
||||
|
|
Loading…
Reference in a new issue