X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Ffocus.c;h=b6d294bbd076096e107df463e908a02469cb0144;hb=8aee387193fd73bbe4a8019bc7e31d5d0e18e83d;hp=2582736bb59ac24ae485622dbc4ef05422410d64;hpb=4ccc4c5ed7d5cffc4bf733191f7bc30fbbf069c8;p=chaz%2Fopenbox diff --git a/openbox/focus.c b/openbox/focus.c index 2582736b..b6d294bb 100644 --- a/openbox/focus.c +++ b/openbox/focus.c @@ -1,3 +1,21 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + focus.c for the Openbox window manager + Copyright (c) 2003 Ben Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + #include "debug.h" #include "event.h" #include "openbox.h" @@ -24,13 +42,23 @@ ObClient *focus_cycle_target; static ObIconPopup *focus_cycle_popup; +static void focus_cycle_destructor(ObClient *c) +{ + /* end cycling if the target disappears */ + if (focus_cycle_target == c) + focus_cycle(TRUE, TRUE, TRUE, TRUE, TRUE); +} + void focus_startup(gboolean reconfig) { focus_cycle_popup = icon_popup_new(TRUE); - if (!reconfig) + if (!reconfig) { + client_add_destructor((GDestroyNotify) focus_cycle_destructor); + /* start with nothing focused */ focus_set_client(NULL); + } } void focus_shutdown(gboolean reconfig) @@ -40,6 +68,8 @@ void focus_shutdown(gboolean reconfig) icon_popup_free(focus_cycle_popup); if (!reconfig) { + client_remove_destructor((GDestroyNotify) focus_cycle_destructor); + for (i = 0; i < screen_num_desktops; ++i) g_list_free(focus_order[i]); g_free(focus_order); @@ -73,7 +103,7 @@ void focus_set_client(ObClient *client) screen_install_colormap(focus_client, FALSE); screen_install_colormap(client, TRUE); - if (!client) { + if (client == NULL) { /* when nothing will be focused, send focus to the backup target */ XSetInputFocus(ob_display, screen_support_win, RevertToPointerRoot, event_lasttime); @@ -87,43 +117,24 @@ void focus_set_client(ObClient *client) old = focus_client; focus_client = client; - if (old) { - /* focus state can affect the stacking layer */ - client_calc_layer(old); - } - if (client) { - /* focus state can affect the stacking layer */ - client_calc_layer(client); - - /* move to the top of the list */ + /* move to the top of the list */ + if (client != NULL) push_to_top(client); - } - /* set the NET_ACTIVE_WINDOW hint */ - active = client ? client->window : None; - PROP_SET32(RootWindow(ob_display, ob_screen), - net_active_window, window, active); + /* set the NET_ACTIVE_WINDOW hint, but preserve it on shutdown */ + if (ob_state() != OB_STATE_EXITING) { + active = client ? client->window : None; + PROP_SET32(RootWindow(ob_display, ob_screen), + net_active_window, window, active); + } } static gboolean focus_under_pointer() { - int x, y; - GList *it; + ObClient *c; - if (screen_pointer_pos(&x, &y)) { - for (it = stacking_list; it != NULL; it = it->next) { - if (WINDOW_IS_CLIENT(it->data)) { - ObClient *c = WINDOW_AS_CLIENT(it->data); - if (c->desktop == screen_desktop && - RECT_CONTAINS(c->frame->area, x, y)) - break; - } - } - if (it != NULL) { - g_assert(WINDOW_IS_CLIENT(it->data)); - return client_normal(it->data) && client_focus(it->data); - } - } + if ((c = client_under_pointer())) + return client_normal(c) && client_focus(c); return FALSE; } @@ -168,9 +179,6 @@ void focus_fallback(ObFocusFallbackType type) */ focus_set_client(NULL); - if (config_focus_follow && focus_under_pointer()) - return; - if (type == OB_FOCUS_FALLBACK_UNFOCUSING && old) { /* try for transient relations */ if (old->transient_for) { @@ -189,6 +197,10 @@ void focus_fallback(ObFocusFallbackType type) } } + if (!config_focus_last && config_focus_follow) + if (focus_under_pointer()) + return; + #if 0 /* try for group relations */ if (old->group) { @@ -209,12 +221,7 @@ void focus_fallback(ObFocusFallbackType type) 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) && - /* dont fall back to 'anonymous' fullscreen windows. theres no - checks for this is in transient/group fallbacks, so they can - be fallback targets there. */ - !((ObClient*)it->data)->fullscreen && - client_can_focus(it->data)) { + if (client_normal(it->data) && client_can_focus(it->data)) { gboolean r = client_focus(it->data); assert(r); return; @@ -269,7 +276,7 @@ static gboolean valid_focus_target(ObClient *ft) 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 == NULL && client_normal(ft) && + return (ft == client_focus_target(ft) && client_normal(ft) && ((ft->can_focus || ft->focus_notify) && !ft->skip_taskbar && (ft->desktop == screen_desktop || ft->desktop == DESKTOP_ALL))); @@ -282,7 +289,7 @@ void focus_cycle(gboolean forward, gboolean linear, static ObClient *t = NULL; static GList *order = NULL; GList *it, *start, *list; - ObClient *ft; + ObClient *ft = NULL; if (cancel) { if (focus_cycle_target) @@ -317,7 +324,6 @@ void focus_cycle(gboolean forward, gboolean linear, it = it->prev; if (it == NULL) it = g_list_last(list); } - /*ft = client_focus_target(it->data);*/ ft = it->data; if (valid_focus_target(ft)) { if (ft != focus_cycle_target) { /* prevents flicker */ @@ -386,11 +392,14 @@ void focus_directional_cycle(ObDirection dir, focus_cycle_target = ft; frame_adjust_focus(focus_cycle_target->frame, TRUE); } - popup_cycle(ft, dialog); + } + if (focus_cycle_target) { + popup_cycle(focus_cycle_target, dialog); if (dialog) return; } + done_cycle: if (done && focus_cycle_target) client_activate(focus_cycle_target, FALSE);