a variable sized alt-tab box. is this nice or slower to read? we'll see.
This commit is contained in:
parent
0f018ecea0
commit
5e0fa1b5c1
1 changed files with 100 additions and 43 deletions
143
openbox/focus.c
143
openbox/focus.c
|
@ -55,14 +55,10 @@ RrColor *color_white;
|
|||
|
||||
static ObIconPopup *focus_cycle_popup;
|
||||
|
||||
static void focus_cycle_destructor(ObClient *client, gpointer data)
|
||||
{
|
||||
/* end cycling if the target disappears. CurrentTime is fine, time won't
|
||||
be used
|
||||
*/
|
||||
if (focus_cycle_target == client)
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
}
|
||||
static gboolean valid_focus_target(ObClient *ft,
|
||||
gboolean all_desktops,
|
||||
gboolean dock_windows);
|
||||
static void focus_cycle_destructor(ObClient *client, gpointer data);
|
||||
|
||||
static Window createWindow(Window parent, gulong mask,
|
||||
XSetWindowAttributes *attrib)
|
||||
|
@ -289,49 +285,108 @@ void focus_nothing()
|
|||
event_curtime);
|
||||
}
|
||||
|
||||
static void popup_cycle(ObClient *c, gboolean show)
|
||||
static gchar *popup_get_name(ObClient *c, ObClient **nametarget)
|
||||
{
|
||||
ObClient *p;
|
||||
gchar *title = NULL;
|
||||
const gchar *desk = NULL;
|
||||
gchar *ret;
|
||||
|
||||
/* find our highest direct parent, including non-normal windows */
|
||||
for (p = c; p->transient_for && p->transient_for != OB_TRAN_GROUP;
|
||||
p = p->transient_for);
|
||||
if (nametarget) *nametarget = p;
|
||||
|
||||
if (c->desktop != DESKTOP_ALL && c->desktop != screen_desktop)
|
||||
desk = screen_desktop_names[c->desktop];
|
||||
|
||||
/* use the transient's parent's title/icon if we don't have one */
|
||||
if (p != c && !strcmp("", (c->iconic ? c->icon_title : c->title)))
|
||||
title = g_strdup(p->iconic ? p->icon_title : p->title);
|
||||
|
||||
if (title == NULL)
|
||||
title = g_strdup(c->iconic ? c->icon_title : c->title);
|
||||
|
||||
if (desk)
|
||||
ret = g_strdup_printf("%s [%s]", title, desk);
|
||||
else {
|
||||
ret = title;
|
||||
title = NULL;
|
||||
}
|
||||
g_free(title);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void popup_cycle(ObClient *c, gboolean show,
|
||||
gboolean all_desktops, gboolean dock_windows)
|
||||
{
|
||||
gchar *showtext = NULL;
|
||||
ObClient *showtarget;
|
||||
|
||||
if (!show) {
|
||||
icon_popup_hide(focus_cycle_popup);
|
||||
} else {
|
||||
Rect *a;
|
||||
ObClient *p;
|
||||
gchar *text;
|
||||
gchar *title = NULL;
|
||||
const gchar *desk = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* do this stuff only when the dialog is first showing */
|
||||
if (!focus_cycle_popup->popup->mapped &&
|
||||
!focus_cycle_popup->popup->delay_mapped)
|
||||
{
|
||||
Rect *a;
|
||||
gchar **names;
|
||||
GList *targets = NULL, *it;
|
||||
gint n = 0, i;
|
||||
|
||||
/* position the popup */
|
||||
a = screen_physical_area_monitor(0);
|
||||
icon_popup_position(focus_cycle_popup, CenterGravity,
|
||||
a->x + a->width / 2, a->y + a->height / 2);
|
||||
icon_popup_width(focus_cycle_popup, MAX(a->width/3, POPUP_WIDTH));
|
||||
icon_popup_height(focus_cycle_popup, POPUP_HEIGHT);
|
||||
|
||||
/* find our highest direct parent, including non-normal windows */
|
||||
for (p = c; p->transient_for && p->transient_for != OB_TRAN_GROUP;
|
||||
p = p->transient_for);
|
||||
/* make its width to be the width of all the possible titles */
|
||||
|
||||
if (c->desktop != DESKTOP_ALL && c->desktop != screen_desktop)
|
||||
desk = screen_desktop_names[c->desktop];
|
||||
/* build a list of all the valid focus targets */
|
||||
for (it = focus_order; it; it = g_list_next(it)) {
|
||||
ObClient *ft = it->data;
|
||||
if (valid_focus_target(ft, all_desktops, dock_windows)) {
|
||||
targets = g_list_prepend(targets, ft);
|
||||
++n;
|
||||
}
|
||||
}
|
||||
/* make it null terminated so we can use g_strfreev */
|
||||
names = g_new(char*, n+1);
|
||||
for (it = targets, i = 0; it; it = g_list_next(it), ++i) {
|
||||
ObClient *ft = it->data;
|
||||
names[i] = popup_get_name(ft, &showtarget);
|
||||
|
||||
/* use the transient's parent's title/icon if we don't have one */
|
||||
if (p != c && !strcmp("", (c->iconic ? c->icon_title : c->title)))
|
||||
title = g_strdup(p->iconic ? p->icon_title : p->title);
|
||||
/*ptitle = g_strconcat((c->iconic ? c->icon_title : c->title),
|
||||
" - ",
|
||||
(p->iconic ? p->icon_title : p->title),
|
||||
NULL);
|
||||
*/
|
||||
if (title == NULL)
|
||||
title = g_strdup(c->iconic ? c->icon_title : c->title);
|
||||
if (desk)
|
||||
text = g_strdup_printf("%s [%s]", title, desk);
|
||||
else
|
||||
text = g_strdup(title);
|
||||
/* little optimization.. save this text so we dont have to get it
|
||||
again */
|
||||
if (ft == c)
|
||||
showtext = g_strdup(names[i]);
|
||||
}
|
||||
names[n] = NULL;
|
||||
|
||||
icon_popup_show(focus_cycle_popup, text, client_icon(p, 48, 48));
|
||||
g_free(text);
|
||||
g_free(title);
|
||||
icon_popup_width_to_strings(focus_cycle_popup,
|
||||
names, n,
|
||||
MAX(a->width/3, POPUP_WIDTH));
|
||||
g_strfreev(names);
|
||||
}
|
||||
|
||||
|
||||
if (!showtext) showtext = popup_get_name(c, &showtarget);
|
||||
icon_popup_show(focus_cycle_popup, showtext,
|
||||
client_icon(showtarget, 48, 48));
|
||||
g_free(showtext);
|
||||
}
|
||||
|
||||
static void focus_cycle_destructor(ObClient *client, gpointer data)
|
||||
{
|
||||
/* end cycling if the target disappears. CurrentTime is fine, time won't
|
||||
be used
|
||||
*/
|
||||
if (focus_cycle_target == client)
|
||||
focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
|
||||
}
|
||||
|
||||
void focus_cycle_draw_indicator()
|
||||
|
@ -568,7 +623,8 @@ void focus_cycle(gboolean forward, gboolean all_desktops,
|
|||
focus_cycle_target = ft;
|
||||
focus_cycle_draw_indicator();
|
||||
}
|
||||
popup_cycle(ft, dialog);
|
||||
/* same arguments as valid_focus_target */
|
||||
popup_cycle(ft, dialog, all_desktops, dock_windows);
|
||||
return;
|
||||
} else if (ft != focus_cycle_target) {
|
||||
focus_cycle_target = ft;
|
||||
|
@ -590,14 +646,14 @@ done_cycle:
|
|||
|
||||
if (interactive) {
|
||||
focus_cycle_draw_indicator();
|
||||
popup_cycle(ft, FALSE);
|
||||
popup_cycle(ft, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* this be mostly ripped from fvwm */
|
||||
ObClient *focus_find_directional(ObClient *c, ObDirection dir,
|
||||
static ObClient *focus_find_directional(ObClient *c, ObDirection dir,
|
||||
gboolean dock_windows)
|
||||
{
|
||||
gint my_cx, my_cy, his_cx, his_cy;
|
||||
|
@ -739,7 +795,8 @@ void focus_directional_cycle(ObDirection dir, gboolean dock_windows,
|
|||
}
|
||||
}
|
||||
if (focus_cycle_target) {
|
||||
popup_cycle(focus_cycle_target, dialog);
|
||||
/* same arguments as valid_focus_target */
|
||||
popup_cycle(focus_cycle_target, dialog, FALSE, dock_windows);
|
||||
if (dialog)
|
||||
return;
|
||||
}
|
||||
|
@ -753,7 +810,7 @@ done_cycle:
|
|||
focus_cycle_target = NULL;
|
||||
|
||||
focus_cycle_draw_indicator();
|
||||
popup_cycle(ft, FALSE);
|
||||
popup_cycle(ft, FALSE, FALSE, FALSE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue