X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Ffocus.c;h=63d2c97194b2f36fdc0f048f51c34ae538bf67e2;hb=b2b8ad92bfbc60392737fe9945e719b238d34933;hp=cac6fc7959101e8adcadd1e801dc56a96c231129;hpb=6611c30854e96f73feaafcef7ee3d4e38a799bfc;p=chaz%2Fopenbox diff --git a/openbox/focus.c b/openbox/focus.c index cac6fc79..63d2c971 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -1,6 +1,7 @@ /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- focus.c for the Openbox window manager + Copyright (c) 2004 Mikael Magnusson Copyright (c) 2003 Ben Jansens This program is free software; you can redistribute it and/or modify @@ -30,16 +31,27 @@ #include "focus.h" #include "stacking.h" #include "popup.h" +#include "render/render.h" #include #include #include -ObClient *focus_client; +ObClient *focus_client, *focus_hilite; GList **focus_order; /* these lists are created when screen_startup sets the number of desktops */ ObClient *focus_cycle_target; +struct { + InternalWindow top; + InternalWindow left; + InternalWindow right; + InternalWindow bottom; +} focus_indicator; + +RrAppearance *a_focus_indicator; +RrColor *color_white; + static ObIconPopup *focus_cycle_popup; static void focus_cycle_destructor(ObClient *client, gpointer data) @@ -49,15 +61,72 @@ static void focus_cycle_destructor(ObClient *client, gpointer data) focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE); } +static Window createWindow(Window parent, gulong mask, + XSetWindowAttributes *attrib) +{ + return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0, + RrDepth(ob_rr_inst), InputOutput, + RrVisual(ob_rr_inst), mask, attrib); + +} + void focus_startup(gboolean reconfig) { focus_cycle_popup = icon_popup_new(TRUE); if (!reconfig) { + XSetWindowAttributes attr; + client_add_destructor(focus_cycle_destructor, NULL); /* start with nothing focused */ focus_set_client(NULL); + + focus_indicator.top.obwin.type = Window_Internal; + focus_indicator.left.obwin.type = Window_Internal; + focus_indicator.right.obwin.type = Window_Internal; + focus_indicator.bottom.obwin.type = Window_Internal; + + attr.save_under = True; + attr.override_redirect = True; + attr.background_pixel = BlackPixel(ob_display, ob_screen); + focus_indicator.top.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel | CWSaveUnder, + &attr); + focus_indicator.left.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel | CWSaveUnder, + &attr); + focus_indicator.right.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel | CWSaveUnder, + &attr); + focus_indicator.bottom.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel | CWSaveUnder, + &attr); + + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.top)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.left)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.right)); + stacking_add(INTERNAL_AS_WINDOW(&focus_indicator.bottom)); + + color_white = RrColorNew(ob_rr_inst, 0xff, 0xff, 0xff); + + a_focus_indicator = RrAppearanceNew(ob_rr_inst, 4); + a_focus_indicator->surface.grad = RR_SURFACE_SOLID; + a_focus_indicator->surface.relief = RR_RELIEF_FLAT; + a_focus_indicator->surface.primary = RrColorNew(ob_rr_inst, + 0, 0, 0); + a_focus_indicator->texture[0].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[0].data.lineart.color = color_white; + a_focus_indicator->texture[1].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[1].data.lineart.color = color_white; + a_focus_indicator->texture[2].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[2].data.lineart.color = color_white; + a_focus_indicator->texture[3].type = RR_TEXTURE_LINE_ART; + a_focus_indicator->texture[3].data.lineart.color = color_white; } } @@ -76,6 +145,15 @@ void focus_shutdown(gboolean reconfig) /* reset focus to root */ XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime); + + RrColorFree(color_white); + + RrAppearanceFree(a_focus_indicator); + + XDestroyWindow(ob_display, focus_indicator.top.win); + XDestroyWindow(ob_display, focus_indicator.left.win); + XDestroyWindow(ob_display, focus_indicator.right.win); + XDestroyWindow(ob_display, focus_indicator.bottom.win); } } @@ -133,12 +211,13 @@ void focus_set_client(ObClient *client) /* finds the first transient that isn't 'skip' and ensure's that client_normal is true for it */ -static ObClient *find_transient_recursive(ObClient *c, ObClient *top, ObClient *skip) +static ObClient *find_transient_recursive(ObClient *c, ObClient *top, + ObClient *skip) { GSList *it; ObClient *ret; - for (it = c->transients; it; it = it->next) { + for (it = c->transients; it; it = g_slist_next(it)) { if (it->data == top) return NULL; ret = find_transient_recursive(it->data, top, skip); if (ret && ret != skip && client_normal(ret)) return ret; @@ -174,7 +253,7 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) if (old->transient_for) { gboolean trans = FALSE; - if (!config_focus_follow) + if (!config_focus_follow || config_focus_last) trans = TRUE; else { if ((target = client_under_pointer()) && @@ -188,14 +267,19 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) /* try for transient relations */ if (trans) { if (old->transient_for == OB_TRAN_GROUP) { - for (it = focus_order[screen_desktop]; it; it = it->next) { + for (it = focus_order[screen_desktop]; it; + it = g_list_next(it)) + { GSList *sit; - for (sit = old->group->members; sit; sit = sit->next) + for (sit = old->group->members; sit; + sit = g_slist_next(sit)) + { if (sit->data == it->data) if ((target = focus_fallback_transient(sit->data, old))) return target; + } } } else { if ((target = @@ -206,7 +290,7 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) } } - if (config_focus_follow) { + if (config_focus_follow && !config_focus_last) { if ((target = client_under_pointer())) if (client_normal(target) && client_can_focus(target)) return target; @@ -217,8 +301,8 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) if (old->group) { GSList *sit; - for (it = focus_order[screen_desktop]; it != NULL; it = it->next) - for (sit = old->group->members; sit; sit = sit->next) + for (it = focus_order[screen_desktop]; it; it = g_list_next(it)) + for (sit = old->group->members; sit; sit = g_slist_next(sit)) if (sit->data == it->data) if (sit->data != old && client_normal(sit->data)) if (client_can_focus(sit->data)) @@ -226,7 +310,7 @@ ObClient* focus_fallback_target(ObFocusFallbackType type) } #endif - for (it = focus_order[screen_desktop]; it != NULL; it = it->next) + for (it = focus_order[screen_desktop]; it; it = g_list_next(it)) if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old) if (client_normal(it->data) && client_can_focus(it->data)) return it->data; @@ -255,7 +339,7 @@ static void popup_cycle(ObClient *c, gboolean show) } else { Rect *a; ObClient *p = c; - char *title; + gchar *title = NULL; a = screen_physical_area_monitor(0); icon_popup_position(focus_cycle_popup, CenterGravity, @@ -272,13 +356,13 @@ static void popup_cycle(ObClient *c, gboolean show) while (p->transient_for && p->transient_for != OB_TRAN_GROUP) p = p->transient_for; - if (p == c) - title = NULL; - else +/* + if (p != c) title = g_strconcat((c->iconic ? c->icon_title : c->title), " - ", (p->iconic ? p->icon_title : p->title), NULL); +*/ icon_popup_show(focus_cycle_popup, (title ? title : @@ -288,16 +372,171 @@ static void popup_cycle(ObClient *c, gboolean show) } } +void focus_cycle_draw_indicator() +{ + if (!focus_cycle_target) { + XUnmapWindow(ob_display, focus_indicator.top.win); + XUnmapWindow(ob_display, focus_indicator.left.win); + XUnmapWindow(ob_display, focus_indicator.right.win); + XUnmapWindow(ob_display, focus_indicator.bottom.win); + } else { + /* + if (focus_cycle_target) + frame_adjust_focus(focus_cycle_target->frame, FALSE); + frame_adjust_focus(focus_cycle_target->frame, TRUE); + */ + gint x, y, w, h; + gint wt, wl, wr, wb; + + wt = wl = wr = wb = MAX(3, + ob_rr_theme->handle_height + + ob_rr_theme->bwidth * 2); + + x = focus_cycle_target->frame->area.x; + y = focus_cycle_target->frame->area.y; + w = focus_cycle_target->frame->area.width; + h = wt; + + XMoveResizeWindow(ob_display, focus_indicator.top.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = h-1; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = 0; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = 0; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = (wl-1); + a_focus_indicator->texture[3].data.lineart.y1 = h-1; + a_focus_indicator->texture[3].data.lineart.x2 = w - wr; + a_focus_indicator->texture[3].data.lineart.y2 = h-1; + RrPaint(a_focus_indicator, focus_indicator.top.win, + w, h); + + x = focus_cycle_target->frame->area.x; + y = focus_cycle_target->frame->area.y; + w = wl; + h = focus_cycle_target->frame->area.height; + + XMoveResizeWindow(ob_display, focus_indicator.left.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = w-1; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = 0; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = 0; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = w-1; + a_focus_indicator->texture[3].data.lineart.y1 = wt-1; + a_focus_indicator->texture[3].data.lineart.x2 = w-1; + a_focus_indicator->texture[3].data.lineart.y2 = h - wb; + RrPaint(a_focus_indicator, focus_indicator.left.win, + w, h); + + x = focus_cycle_target->frame->area.x + + focus_cycle_target->frame->area.width - wr; + y = focus_cycle_target->frame->area.y; + w = wr; + h = focus_cycle_target->frame->area.height ; + + XMoveResizeWindow(ob_display, focus_indicator.right.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = w-1; + a_focus_indicator->texture[0].data.lineart.y2 = 0; + a_focus_indicator->texture[1].data.lineart.x1 = w-1; + a_focus_indicator->texture[1].data.lineart.y1 = 0; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = 0; + a_focus_indicator->texture[2].data.lineart.y2 = h-1; + a_focus_indicator->texture[3].data.lineart.x1 = 0; + a_focus_indicator->texture[3].data.lineart.y1 = wt-1; + a_focus_indicator->texture[3].data.lineart.x2 = 0; + a_focus_indicator->texture[3].data.lineart.y2 = h - wb; + RrPaint(a_focus_indicator, focus_indicator.right.win, + w, h); + + x = focus_cycle_target->frame->area.x; + y = focus_cycle_target->frame->area.y + + focus_cycle_target->frame->area.height - wb; + w = focus_cycle_target->frame->area.width; + h = wb; + + XMoveResizeWindow(ob_display, focus_indicator.bottom.win, + x, y, w, h); + a_focus_indicator->texture[0].data.lineart.x1 = 0; + a_focus_indicator->texture[0].data.lineart.y1 = 0; + a_focus_indicator->texture[0].data.lineart.x2 = 0; + a_focus_indicator->texture[0].data.lineart.y2 = h-1; + a_focus_indicator->texture[1].data.lineart.x1 = 0; + a_focus_indicator->texture[1].data.lineart.y1 = h-1; + a_focus_indicator->texture[1].data.lineart.x2 = w-1; + a_focus_indicator->texture[1].data.lineart.y2 = h-1; + a_focus_indicator->texture[2].data.lineart.x1 = w-1; + a_focus_indicator->texture[2].data.lineart.y1 = h-1; + a_focus_indicator->texture[2].data.lineart.x2 = w-1; + a_focus_indicator->texture[2].data.lineart.y2 = 0; + a_focus_indicator->texture[3].data.lineart.x1 = wl-1; + a_focus_indicator->texture[3].data.lineart.y1 = 0; + a_focus_indicator->texture[3].data.lineart.x2 = w - wr; + a_focus_indicator->texture[3].data.lineart.y2 = 0; + RrPaint(a_focus_indicator, focus_indicator.bottom.win, + w, h); + + XMapWindow(ob_display, focus_indicator.top.win); + XMapWindow(ob_display, focus_indicator.left.win); + XMapWindow(ob_display, focus_indicator.right.win); + XMapWindow(ob_display, focus_indicator.bottom.win); + } +} + static gboolean valid_focus_target(ObClient *ft) { /* 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 */ - return (!ft->transients && client_normal(ft) && - ((ft->can_focus || ft->focus_notify) && - !ft->skip_taskbar && - (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL))); + 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_taskbar && + (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL)) && + ft == client_focus_target(ft)) + return TRUE; +/* + { + GSList *it; + + for (it = ft->transients; it; it = g_slist_next(it)) { + ObClient *c = it->data; + + if (c->frame->visible) + return FALSE; + } + return TRUE; + } +*/ + + return FALSE; } void focus_cycle(gboolean forward, gboolean linear, @@ -310,15 +549,10 @@ void focus_cycle(gboolean forward, gboolean linear, ObClient *ft = NULL; if (cancel) { - if (focus_cycle_target) - frame_adjust_focus(focus_cycle_target->frame, FALSE); - if (focus_client) - frame_adjust_focus(focus_client->frame, TRUE); focus_cycle_target = NULL; goto done_cycle; - } else if (done && dialog) { + } else if (done) goto done_cycle; - } if (!focus_order[screen_desktop]) goto done_cycle; @@ -345,10 +579,8 @@ void focus_cycle(gboolean forward, gboolean linear, ft = it->data; if (valid_focus_target(ft)) { if (ft != focus_cycle_target) { /* prevents flicker */ - if (focus_cycle_target) - frame_adjust_focus(focus_cycle_target->frame, FALSE); focus_cycle_target = ft; - frame_adjust_focus(focus_cycle_target->frame, TRUE); + focus_cycle_draw_indicator(); } popup_cycle(ft, dialog); return; @@ -365,6 +597,7 @@ done_cycle: g_list_free(order); order = NULL; + focus_cycle_draw_indicator(); popup_cycle(ft, FALSE); return; @@ -377,15 +610,10 @@ void focus_directional_cycle(ObDirection dir, ObClient *ft = NULL; if (cancel) { - if (focus_cycle_target) - frame_adjust_focus(focus_cycle_target->frame, FALSE); - if (focus_client) - frame_adjust_focus(focus_client->frame, TRUE); focus_cycle_target = NULL; goto done_cycle; - } else if (done && dialog) { + } else if (done) goto done_cycle; - } if (!focus_order[screen_desktop]) goto done_cycle; @@ -405,10 +633,8 @@ void focus_directional_cycle(ObDirection dir, if (ft) { if (ft != focus_cycle_target) {/* prevents flicker */ - if (focus_cycle_target) - frame_adjust_focus(focus_cycle_target->frame, FALSE); focus_cycle_target = ft; - frame_adjust_focus(focus_cycle_target->frame, TRUE); + focus_cycle_draw_indicator(); } } if (focus_cycle_target) { @@ -425,6 +651,7 @@ done_cycle: first = NULL; focus_cycle_target = NULL; + focus_cycle_draw_indicator(); popup_cycle(ft, FALSE); return; @@ -440,16 +667,19 @@ void focus_order_add_new(ObClient *c) d = c->desktop; if (d == DESKTOP_ALL) { for (i = 0; i < screen_num_desktops; ++i) { + g_assert(!g_list_find(focus_order[i], c)); if (focus_order[i] && ((ObClient*)focus_order[i]->data)->iconic) focus_order[i] = g_list_insert(focus_order[i], c, 0); else focus_order[i] = g_list_insert(focus_order[i], c, 1); } - } else - if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic) + } else { + g_assert(!g_list_find(focus_order[d], c)); + if (focus_order[d] && ((ObClient*)focus_order[d]->data)->iconic) focus_order[d] = g_list_insert(focus_order[d], c, 0); else focus_order[d] = g_list_insert(focus_order[d], c, 1); + } } } @@ -475,7 +705,7 @@ static void to_top(ObClient *c, guint d) /* insert before first iconic window */ for (it = focus_order[d]; - it && !((ObClient*)it->data)->iconic; it = it->next); + it && !((ObClient*)it->data)->iconic; it = g_list_next(it)); focus_order[d] = g_list_insert_before(focus_order[d], it, c); } } @@ -502,7 +732,7 @@ static void to_bottom(ObClient *c, guint d) /* insert before first iconic window */ for (it = focus_order[d]; - it && !((ObClient*)it->data)->iconic; it = it->next); + it && !((ObClient*)it->data)->iconic; it = g_list_next(it)); g_list_insert_before(focus_order[d], it, c); } }