X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Ffocus.c;h=44f8edb213c89cef51313efa7509ce133643c231;hb=b84a934ab7b3ebd68b8b90961146463ac17d396e;hp=16ab571e9c1928fbaa48fc3601d3e58ee2e41efc;hpb=9bac22eb402a477b802416287b9e76bf908408ed;p=chaz%2Fopenbox diff --git a/openbox/focus.c b/openbox/focus.c index 16ab571e..44f8edb2 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -30,16 +30,28 @@ #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_black; +RrColor *color_white; + static ObIconPopup *focus_cycle_popup; static void focus_cycle_destructor(ObClient *client, gpointer data) @@ -49,15 +61,67 @@ static void focus_cycle_destructor(ObClient *client, gpointer data) focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE); } +static Window createWindow(Window parent, unsigned long 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.override_redirect = True; + attr.background_pixel = BlackPixel(ob_display, ob_screen); + focus_indicator.top.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.left.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.right.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &attr); + focus_indicator.bottom.win = + createWindow(RootWindow(ob_display, ob_screen), + CWOverrideRedirect | CWBackPixel, &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_black = RrColorNew(ob_rr_inst, 0, 0, 0); + 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 = color_black; + 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 +140,16 @@ void focus_shutdown(gboolean reconfig) /* reset focus to root */ XSetInputFocus(ob_display, PointerRoot, RevertToNone, event_lasttime); + + RrColorFree(color_black); + 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); } } @@ -131,15 +205,6 @@ void focus_set_client(ObClient *client) } } -static gboolean focus_under_pointer() -{ - ObClient *c; - - if ((c = client_under_pointer())) - return client_normal(c) && client_focus(c); - return FALSE; -} - /* 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) @@ -156,31 +221,29 @@ static ObClient *find_transient_recursive(ObClient *c, ObClient *top, ObClient * return NULL; } -static gboolean focus_fallback_transient(ObClient *top, ObClient *old) +static ObClient* focus_fallback_transient(ObClient *top, ObClient *old) { ObClient *target = find_transient_recursive(top, top, old); if (!target) { /* make sure client_normal is true always */ if (!client_normal(top)) - return FALSE; + return NULL; target = top; /* no transient, keep the top */ } - return client_focus(target); + if (client_can_focus(target)) + return target; + else + return NULL; } -void focus_fallback(ObFocusFallbackType type) +ObClient* focus_fallback_target(ObFocusFallbackType type) { GList *it; ObClient *old = NULL; + ObClient *target = NULL; old = focus_client; - /* unfocus any focused clients.. they can be focused by Pointer events - and such, and then when I try focus them, I won't get a FocusIn event - at all for them. - */ - focus_set_client(NULL); - if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) { if (old->transient_for) { gboolean trans = FALSE; @@ -188,16 +251,14 @@ void focus_fallback(ObFocusFallbackType type) if (!config_focus_follow) trans = TRUE; else { - ObClient *c; - - if ((c = client_under_pointer()) && - client_search_transient(client_search_top_transient(c), - old)) + if ((target = client_under_pointer()) && + client_search_transient + (client_search_top_transient(target), old)) + { trans = TRUE; + } } - g_message("trans %d", trans); - /* try for transient relations */ if (trans) { if (old->transient_for == OB_TRAN_GROUP) { @@ -206,20 +267,24 @@ void focus_fallback(ObFocusFallbackType type) for (sit = old->group->members; sit; sit = sit->next) if (sit->data == it->data) - if (focus_fallback_transient(sit->data, old)) - return; + if ((target = + focus_fallback_transient(sit->data, old))) + return target; } } else { - if (focus_fallback_transient(old->transient_for, old)) - return; + if ((target = + focus_fallback_transient(old->transient_for, old))) + return target; } } } } - if (config_focus_follow) - if (focus_under_pointer()) - return; + if (config_focus_follow) { + if ((target = client_under_pointer())) + if (client_normal(target) && client_can_focus(target)) + return target; + } #if 0 /* try for group relations */ @@ -230,23 +295,31 @@ void focus_fallback(ObFocusFallbackType type) for (sit = old->group->members; sit; sit = sit->next) if (sit->data == it->data) if (sit->data != old && client_normal(sit->data)) - if (client_can_focus(sit->data)) { - gboolean r = client_focus(sit->data); - assert(r); - return; - } + if (client_can_focus(sit->data)) + return sit->data; } #endif for (it = focus_order[screen_desktop]; it != NULL; it = it->next) if (type != OB_FOCUS_FALLBACK_UNFOCUSING || it->data != old) - if (client_normal(it->data) && client_can_focus(it->data)) { - gboolean r = client_focus(it->data); - assert(r); - return; - } + if (client_normal(it->data) && client_can_focus(it->data)) + return it->data; + + return NULL; +} + +void focus_fallback(ObFocusFallbackType type) +{ + ObClient *new; - /* nothing to focus, and already set it to none above */ + /* unfocus any focused clients.. they can be focused by Pointer events + and such, and then when I try focus them, I won't get a FocusIn event + at all for them. + */ + focus_set_client(NULL); + + if ((new = focus_fallback_target(type))) + client_focus(new); } static void popup_cycle(ObClient *c, gboolean show) @@ -289,6 +362,132 @@ 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); + */ + int x, y, w, h; + int wt, wl, wr, wb; + + wt = wl = wr = wb = MAX(5, ob_rr_theme->handle_height); + + 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); + } +} + static gboolean valid_focus_target(ObClient *ft) { /* we don't use client_can_focus here, because that doesn't let you @@ -311,10 +510,12 @@ 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) { @@ -346,10 +547,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; @@ -366,6 +565,7 @@ done_cycle: g_list_free(order); order = NULL; + focus_cycle_draw_indicator(); popup_cycle(ft, FALSE); return;