X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=f91a783db0cf0d9b22117959456f1080241812e0;hb=6cf3357036561134383198cc8b853abb3fe5a982;hp=d98ce642868ea112ad030ee76225ec172820cbe0;hpb=3f72b9d67f21781e513a9c058e8624b8b86b92ea;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index d98ce642..f91a783d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -31,15 +31,15 @@ #include "grab.h" #include "prompt.h" #include "focus.h" +#include "focus_cycle.h" #include "stacking.h" #include "openbox.h" -#include "hooks.h" #include "group.h" #include "config.h" #include "menuframe.h" #include "keyboard.h" #include "mouse.h" -#include "render/render.h" +#include "obrender/render.h" #include "gettext.h" #include "obt/display.h" #include "obt/prop.h" @@ -76,11 +76,11 @@ static RrImage *client_default_icon = NULL; static void client_get_all(ObClient *self, gboolean real); static void client_get_startup_id(ObClient *self); static void client_get_session_ids(ObClient *self); +static void client_save_app_rule_values(ObClient *self); static void client_get_area(ObClient *self); static void client_get_desktop(ObClient *self); static void client_get_state(ObClient *self); static void client_get_shaped(ObClient *self); -static void client_get_mwm_hints(ObClient *self); static void client_get_colormap(ObClient *self); static void client_set_desktop_recursive(ObClient *self, guint target, @@ -107,6 +107,8 @@ static GSList *client_search_all_top_parents_internal(ObClient *self, static void client_call_notifies(ObClient *self, GSList *list); static void client_ping_event(ObClient *self, gboolean dead); static void client_prompt_kill(ObClient *self); +static gboolean client_can_steal_focus(ObClient *self, Time steal_time, + Time launch_time); void client_startup(gboolean reconfig) { @@ -222,6 +224,7 @@ void client_manage(Window window, ObPrompt *prompt) self->obwin.type = OB_WINDOW_CLASS_CLIENT; self->window = window; self->prompt = prompt; + self->managed = TRUE; /* non-zero defaults */ self->wmstate = WithdrawnState; /* make sure it gets updated first time */ @@ -233,7 +236,13 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Window type: %d", self->type); ob_debug("Window group: 0x%x", self->group?self->group->leader:0); - ob_debug("Window name: %s class: %s", self->name, self->class); + ob_debug("Window name: %s class: %s role: %s title: %s", + self->name, self->class, self->role, self->title); + + /* per-app settings override stuff from client_get_all, and return the + settings for other uses too. the returned settings is a shallow copy, + that needs to be freed with g_free(). */ + settings = client_get_settings_state(self); /* now we have all of the window's information so we can set this up. do this before creating the frame, so it can tell that we are still @@ -255,10 +264,6 @@ void client_manage(Window window, ObPrompt *prompt) time now */ grab_server(FALSE); - /* per-app settings override stuff from client_get_all, and return the - settings for other uses too. the returned settings is a shallow copy, - that needs to be freed with g_free(). */ - settings = client_get_settings_state(self); /* the session should get the last say though */ client_restore_session_state(self); @@ -288,7 +293,9 @@ void client_manage(Window window, ObPrompt *prompt) (user_time != 0) && /* this checks for focus=false for the window */ (!settings || settings->focus != 0) && - focus_valid_target(self, FALSE, FALSE, TRUE, FALSE, FALSE)) + focus_valid_target(self, self->desktop, + FALSE, FALSE, TRUE, FALSE, FALSE, + settings->focus == 1)) { activate = TRUE; } @@ -323,9 +330,7 @@ void client_manage(Window window, ObPrompt *prompt) "program + user specified" : "BADNESS !?")))), place.width, place.height); - /* splash screens are also returned as TRUE for transient, - and so will be forced on screen below */ - transient = place_client(self, &place.x, &place.y, settings); + place_client(self, &place.x, &place.y, settings); /* make sure the window is visible. */ client_find_onscreen(self, &place.x, &place.y, @@ -341,11 +346,13 @@ void client_manage(Window window, ObPrompt *prompt) it is up to the placement routines to avoid the xinerama divides) - splash screens get "transient" set to TRUE by - the place_client call + children and splash screens are forced on + screen, but i don't remember why i decided to + do that. */ ob_state() == OB_STATE_RUNNING && - (transient || + (self->type == OB_CLIENT_TYPE_DIALOG || + self->type == OB_CLIENT_TYPE_SPLASH || (!((self->positioned & USPosition) || (settings && settings->pos_given)) && client_normal(self) && @@ -419,121 +426,14 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s", activate ? "yes" : "no"); if (activate) { - gboolean raise = FALSE; - gboolean relative_focused; - gboolean parent_focused; - - parent_focused = (focus_client != NULL && - client_search_focus_parent(self)); - relative_focused = (focus_client != NULL && - (client_search_focus_tree_full(self) != NULL || - client_search_focus_group_full(self) != NULL)); - - /* This is focus stealing prevention */ - ob_debug_type(OB_DEBUG_FOCUS, - "Want to focus new window 0x%x at time %u " - "launched at %u (last user interaction time %u)", - self->window, map_time, launch_time, - event_last_user_time); - ob_debug_type(OB_DEBUG_FOCUS, - "Current focus_client: %s", - (focus_client ? focus_client->title : "(none)")); - ob_debug_type(OB_DEBUG_FOCUS, - "parent focused: %d relative focused: %d", - parent_focused, relative_focused); - - if (menu_frame_visible || moveresize_in_progress) { - activate = FALSE; - raise = TRUE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because the user is inside " - "an Openbox menu or is move/resizing a window and " - "we don't want to interrupt them"); - } - - /* if it's on another desktop */ - else if (!(self->desktop == screen_desktop || - self->desktop == DESKTOP_ALL) && - /* the timestamp is from before you changed desktops */ - launch_time && screen_desktop_user_time && - !event_time_after(launch_time, screen_desktop_user_time)) - { - activate = FALSE; - raise = TRUE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because its on another " - "desktop"); - } - /* If something is focused... */ - else if (focus_client) { - /* If the user is working in another window right now, then don't - steal focus */ - if (!parent_focused && - event_last_user_time && launch_time && - event_time_after(event_last_user_time, launch_time) && - event_last_user_time != launch_time && - event_time_after(event_last_user_time, - map_time - OB_EVENT_USER_TIME_DELAY)) - { - activate = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because the user is " - "working in another window that is not " - "its parent"); - } - /* If the new window is a transient (and its relatives aren't - focused) */ - else if (client_has_parent(self) && !relative_focused) { - activate = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because it is a " - "transient, and its relatives aren't focused"); - } - /* Don't steal focus from globally active clients. - I stole this idea from KWin. It seems nice. - */ - else if (!(focus_client->can_focus || - focus_client->focus_notify)) - { - activate = FALSE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because a globally " - "active client has focus"); - } - /* Don't move focus if it's not going to go to this window - anyway */ - else if (client_focus_target(self) != self) { - activate = FALSE; - raise = TRUE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because another window " - "would get the focus anyway"); - } - /* Don't move focus if the window is not visible on the current - desktop and none of its relatives are focused */ - else if (!(self->desktop == screen_desktop || - self->desktop == DESKTOP_ALL) && - !relative_focused) - { - activate = FALSE; - raise = TRUE; - ob_debug_type(OB_DEBUG_FOCUS, - "Not focusing the window because it is on " - "another desktop and no relatives are focused "); - } - } + activate = client_can_steal_focus(self, map_time, launch_time); if (!activate) { - ob_debug_type(OB_DEBUG_FOCUS, - "Focus stealing prevention activated for %s at " - "time %u (last user interaction time %u)", - self->title, map_time, event_last_user_time); - /* if the client isn't focused, then hilite it so the user - knows it is there */ - client_hilite(self, TRUE); - /* we may want to raise it even tho we're not activating it */ - if (raise && !client_restore_session_stacking(self)) - stacking_raise(CLIENT_AS_WINDOW(self)); + /* if the client isn't stealing focus, then hilite it so the user + knows it is there, but don't do this if we're restoring from a + session */ + if (!client_restore_session_stacking(self)) + client_hilite(self, TRUE); } } else { @@ -585,8 +485,6 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug("Managed window 0x%lx plate 0x%x (%s)", window, self->frame->window, self->class); - - hooks_queue(OB_HOOK_WIN_NEW, self); } ObClient *client_fake_manage(Window window) @@ -656,14 +554,13 @@ void client_unmanage(ObClient *self) mouse_grab_for_client(self, FALSE); + self->managed = FALSE; + /* remove the window from our save set, unless we are managing an internal ObPrompt window */ if (!self->prompt) XChangeSaveSet(obt_display, self->window, SetModeDelete); - /* this can't be queued to run later */ - hooks_run(OB_HOOK_WIN_CLOSE, self); - /* update the focus lists */ focus_order_remove(self); if (client_focused(self)) { @@ -787,6 +684,105 @@ void client_fake_unmanage(ObClient *self) g_free(self); } +static gboolean client_can_steal_focus(ObClient *self, Time steal_time, + Time launch_time) +{ + gboolean steal; + gboolean relative_focused; + gboolean parent_focused; + + steal = TRUE; + + parent_focused = (focus_client != NULL && + client_search_focus_parent(self)); + relative_focused = (focus_client != NULL && + (client_search_focus_tree_full(self) != NULL || + client_search_focus_group_full(self) != NULL)); + + /* This is focus stealing prevention */ + ob_debug_type(OB_DEBUG_FOCUS, + "Want to focus new window 0x%x at time %u " + "launched at %u (last user interaction time %u)", + self->window, steal_time, launch_time, + event_last_user_time); + + /* if it's on another desktop */ + if (!(self->desktop == screen_desktop || + self->desktop == DESKTOP_ALL) && + /* the timestamp is from before you changed desktops */ + launch_time && screen_desktop_user_time && + !event_time_after(launch_time, screen_desktop_user_time)) + { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because its on another " + "desktop\n"); + } + /* If something is focused... */ + else if (focus_client) { + /* If the user is working in another window right now, then don't + steal focus */ + if (!parent_focused && + event_last_user_time && launch_time && + event_time_after(event_last_user_time, launch_time) && + event_last_user_time != launch_time && + event_time_after(event_last_user_time, + steal_time - OB_EVENT_USER_TIME_DELAY)) + { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because the user is " + "working in another window that is not " + "its parent"); + } + /* If the new window is a transient (and its relatives aren't + focused) */ + else if (client_has_parent(self) && !relative_focused) { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because it is a " + "transient, and its relatives aren't focused"); + } + /* Don't steal focus from globally active clients. + I stole this idea from KWin. It seems nice. + */ + else if (!(focus_client->can_focus || + focus_client->focus_notify)) + { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because a globally " + "active client has focus"); + } + /* Don't move focus if it's not going to go to this window + anyway */ + else if (client_focus_target(self) != self) { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because another window " + "would get the focus anyway"); + } + /* Don't move focus if the window is not visible on the current + desktop and none of its relatives are focused */ + else if (!(self->desktop == screen_desktop || + self->desktop == DESKTOP_ALL) && + !relative_focused) + { + steal = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because it is on " + "another desktop and no relatives are focused "); + } + } + + if (!steal) + ob_debug_type(OB_DEBUG_FOCUS, + "Focus stealing prevention activated for %s at " + "time %u (last user interaction time %u)", + self->title, steal_time, event_last_user_time); + return steal; +} + /*! Returns a new structure containing the per-app settings for this client. The returned structure needs to be freed with g_free. */ static ObAppSettings *client_get_settings_state(ObClient *self) @@ -800,10 +796,10 @@ static ObAppSettings *client_get_settings_state(ObClient *self) ObAppSettings *app = it->data; gboolean match = TRUE; - g_assert(app->name != NULL || app->class != NULL); + g_assert(app->name != NULL || app->class != NULL || + app->role != NULL || app->title != NULL || + (signed)app->type >= 0); - /* we know that either name or class is not NULL so it will have to - match to use the rule */ if (app->name && !g_pattern_match(app->name, strlen(self->name), self->name, NULL)) match = FALSE; @@ -815,8 +811,13 @@ static ObAppSettings *client_get_settings_state(ObClient *self) !g_pattern_match(app->role, strlen(self->role), self->role, NULL)) match = FALSE; - else if ((signed)app->type >= 0 && app->type != self->type) + else if (app->title && + !g_pattern_match(app->title, + strlen(self->title), self->title, NULL)) + match = FALSE; + else if ((signed)app->type >= 0 && app->type != self->type) { match = FALSE; + } if (match) { ob_debug("Window matching: %s", app->name); @@ -1095,6 +1096,9 @@ static void client_get_all(ObClient *self, gboolean real) /* get this early so we have it for debugging */ client_update_title(self); + /* save the values of the variables used for app rule matching */ + client_save_app_rule_values(self); + client_update_protocols(self); client_update_wmhints(self); @@ -1408,7 +1412,7 @@ static void client_update_transient_tree(ObClient *self, } } -static void client_get_mwm_hints(ObClient *self) +void client_get_mwm_hints(ObClient *self) { guint num; guint32 *hints; @@ -1758,7 +1762,8 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) /* finally, the user can have requested no decorations, which overrides everything (but doesnt give it a border if it doesnt have one) */ if (self->undecorated) - self->decorations = 0; + self->decorations &= (config_theme_keepborder ? + OB_FRAME_DECOR_BORDER : 0); /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) @@ -1919,6 +1924,8 @@ void client_update_wmhints(ObClient *self) XFree(hints); } + + focus_cycle_addremove(self, TRUE); } void client_update_title(ObClient *self) @@ -2042,7 +2049,7 @@ void client_update_strut(ObClient *self) STRUT_PARTIAL_SET(strut, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if (!STRUT_EQUAL(strut, self->strut)) { + if (!PARTIAL_STRUT_EQUAL(strut, self->strut)) { self->strut = strut; /* updating here is pointless while we're being mapped cuz we're not in @@ -2299,6 +2306,39 @@ static void client_get_session_ids(ObClient *self) } } +/*! Save the properties used for app matching rules, as seen by Openbox when + the window mapped, so that users can still access them later if the app + changes them */ +static void client_save_app_rule_values(ObClient *self) +{ + const gchar *type; + + OBT_PROP_SETS(self->window, OB_APP_ROLE, utf8, self->role); + OBT_PROP_SETS(self->window, OB_APP_NAME, utf8, self->name); + OBT_PROP_SETS(self->window, OB_APP_CLASS, utf8, self->class); + OBT_PROP_SETS(self->window, OB_APP_TITLE, utf8, self->original_title); + + switch (self->type) { + case OB_CLIENT_TYPE_NORMAL: + type = "normal"; break; + case OB_CLIENT_TYPE_DIALOG: + type = "dialog"; break; + case OB_CLIENT_TYPE_UTILITY: + type = "utility"; break; + case OB_CLIENT_TYPE_MENU: + type = "menu"; break; + case OB_CLIENT_TYPE_TOOLBAR: + type = "toolbar"; break; + case OB_CLIENT_TYPE_SPLASH: + type = "splash"; break; + case OB_CLIENT_TYPE_DESKTOP: + type = "desktop"; break; + case OB_CLIENT_TYPE_DOCK: + type = "dock"; break; + } + OBT_PROP_SETS(self->window, OB_APP_TYPE, utf8, type); +} + static void client_change_wm_state(ObClient *self) { gulong state[2]; @@ -2378,7 +2418,7 @@ ObClient *client_search_focus_tree_full(ObClient *self) for (it = self->parents; it; it = g_slist_next(it)) { ObClient *c = it->data; - if ((c = client_search_focus_tree_full(it->data))) return c; + if ((c = client_search_focus_tree_full(c))) return c; } return NULL; @@ -2546,8 +2586,6 @@ gboolean client_show(ObClient *self) desktop! */ client_change_wm_state(self); - - hooks_queue(OB_HOOK_WIN_VISIBLE, self); } return show; } @@ -2557,10 +2595,6 @@ gboolean client_hide(ObClient *self) gboolean hide = FALSE; if (!client_should_show(self)) { - if (self == focus_client) { - event_cancel_all_key_grabs(); - } - /* We don't need to ignore enter events here. The window can hide/iconify in 3 different ways: 1 - through an x message. in this case we ignore all enter events @@ -2586,8 +2620,6 @@ gboolean client_hide(ObClient *self) desktop! */ client_change_wm_state(self); - - hooks_queue(OB_HOOK_WIN_INVISIBLE, self); } return hide; } @@ -3155,7 +3187,7 @@ static void client_iconify_recursive(ObClient *self, self->iconic = iconic; /* update the focus lists.. iconic windows go to the bottom of - the list */ + the list. this will also call focus_cycle_addremove(). */ focus_order_to_bottom(self); changed = TRUE; @@ -3167,9 +3199,10 @@ static void client_iconify_recursive(ObClient *self, self->desktop != DESKTOP_ALL) client_set_desktop(self, screen_desktop, FALSE, FALSE); - /* this puts it after the current focused window */ - focus_order_remove(self); - focus_order_add_new(self); + /* this puts it after the current focused window, this will + also cause focus_cycle_addremove() to be called for the + client */ + focus_order_like_new(self); changed = TRUE; } @@ -3181,9 +3214,6 @@ static void client_iconify_recursive(ObClient *self, frame_begin_iconify_animation(self->frame, iconic); /* do this after starting the animation so it doesn't flash */ client_showhide(self); - - hooks_queue((iconic ? OB_HOOK_WIN_ICONIC : OB_HOOK_WIN_UNICONIC), - self); } /* iconify all direct transients, and deiconify all transients @@ -3271,8 +3301,6 @@ void client_maximize(ObClient *self, gboolean max, gint dir) client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); - - hooks_queue((max ? OB_HOOK_WIN_MAX : OB_HOOK_WIN_UNMAX), self); } void client_shade(ObClient *self, gboolean shade) @@ -3286,8 +3314,6 @@ void client_shade(ObClient *self, gboolean shade) client_change_wm_state(self); /* the window is being hidden/shown */ /* resize the frame to just the titlebar */ frame_adjust_area(self->frame, FALSE, TRUE, FALSE); - - hooks_queue((shade ? OB_HOOK_WIN_SHADE : OB_HOOK_WIN_UNSHADE), self); } static void client_ping_event(ObClient *self, gboolean dead) @@ -3459,8 +3485,18 @@ void client_hilite(ObClient *self, gboolean hilite) /* don't allow focused windows to hilite */ self->demands_attention = hilite && !client_focused(self); if (self->frame != NULL) { /* if we're mapping, just set the state */ - if (self->demands_attention) + if (self->demands_attention) { frame_flash_start(self->frame); + + /* if the window is on another desktop then raise it and make it + the most recently used window */ + if (self->desktop != screen_desktop && + self->desktop != DESKTOP_ALL) + { + stacking_raise(CLIENT_AS_WINDOW(self)); + focus_order_to_top(self); + } + } else frame_flash_stop(self->frame); client_change_state(self); @@ -3500,8 +3536,7 @@ static void client_set_desktop_recursive(ObClient *self, resize, for example if we are maximized */ client_reconfigure(self, FALSE); - if (old != self->desktop) - hooks_queue(OB_HOOK_WIN_DESK_CHANGE, self); + focus_cycle_addremove(self, FALSE); } /* move all transients */ @@ -3517,6 +3552,8 @@ void client_set_desktop(ObClient *self, guint target, { self = client_search_top_direct_parent(self); client_set_desktop_recursive(self, target, donthide, dontraise); + + focus_cycle_addremove(NULL, TRUE); } gboolean client_is_direct_child(ObClient *parent, ObClient *child) @@ -3538,19 +3575,38 @@ ObClient *client_search_modal_child(ObClient *self) return NULL; } +static gboolean client_validate_unmap(ObClient *self, int n) +{ + XEvent e; + gboolean ret = TRUE; + + if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) { + if (n < self->ignore_unmaps) // ignore this one, but look for more + ret = client_validate_unmap(self, n+1); + else + ret = FALSE; // the window is going to become unmanaged + + /* put them back on the event stack so they end up in the same order */ + XPutBackEvent(obt_display, &e); + } + + return ret; +} + gboolean client_validate(ObClient *self) { XEvent e; XSync(obt_display, FALSE); /* get all events on the server */ - if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e) || - XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) - { + if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) { XPutBackEvent(obt_display, &e); return FALSE; } + if (!client_validate_unmap(self, 0)) + return FALSE; + return TRUE; } @@ -3620,6 +3676,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) value = self->demands_attention; else if (state == OBT_PROP_ATOM(OB_WM_STATE_UNDECORATED)) value = undecorated; + else + g_assert_not_reached(); action = value ? OBT_PROP_ATOM(NET_WM_STATE_REMOVE) : OBT_PROP_ATOM(NET_WM_STATE_ADD); } @@ -3709,6 +3767,8 @@ void client_set_state(ObClient *self, Atom action, glong data1, glong data2) client_hilite(self, demands_attention); client_change_state(self); /* change the hint to reflect these changes */ + + focus_cycle_addremove(self, TRUE); } ObClient *client_focus_target(ObClient *self) @@ -3757,8 +3817,6 @@ gboolean client_focus(ObClient *self) go moving on us */ event_halt_focus_delay(); - event_cancel_all_key_grabs(); - obt_display_ignore_errors(TRUE); if (self->can_focus) { @@ -3817,12 +3875,17 @@ static void client_present(ObClient *self, gboolean here, gboolean raise, } /* this function exists to map to the net_active_window message in the ewmh */ -void client_activate(ObClient *self, gboolean here, gboolean raise, +void client_activate(ObClient *self, gboolean desktop, + gboolean here, gboolean raise, gboolean unshade, gboolean user) { - if (user || (self->desktop == DESKTOP_ALL || - self->desktop == screen_desktop)) + if ((user && (desktop || + self->desktop == DESKTOP_ALL || + self->desktop == screen_desktop)) || + client_can_steal_focus(self, event_curtime, CurrentTime)) + { client_present(self, here, raise, unshade); + } else client_hilite(self, TRUE); } @@ -3907,9 +3970,6 @@ void client_set_undecorated(ObClient *self, gboolean undecorated) self->undecorated = undecorated; client_setup_decor_and_functions(self, TRUE); client_change_state(self); /* reflect this in the state hints */ - - hooks_queue((undecorated ? - OB_HOOK_WIN_UNDECORATED : OB_HOOK_WIN_DECORATED), self); } } @@ -4121,39 +4181,26 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, gint *dest, gboolean *near_edge) { GList *it; - Rect *a, *mon; + Rect *a; Rect dock_area; gint edge; + guint i; a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS, &self->frame->area); - mon = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, - &self->frame->area); switch (dir) { case OB_DIRECTION_NORTH: - if (my_head >= RECT_TOP(*mon) + 1) - edge = RECT_TOP(*mon) - 1; - else - edge = RECT_TOP(*a) - 1; + edge = RECT_TOP(*a) - 1; break; case OB_DIRECTION_SOUTH: - if (my_head <= RECT_BOTTOM(*mon) - 1) - edge = RECT_BOTTOM(*mon) + 1; - else - edge = RECT_BOTTOM(*a) + 1; + edge = RECT_BOTTOM(*a) + 1; break; case OB_DIRECTION_EAST: - if (my_head <= RECT_RIGHT(*mon) - 1) - edge = RECT_RIGHT(*mon) + 1; - else - edge = RECT_RIGHT(*a) + 1; + edge = RECT_RIGHT(*a) + 1; break; case OB_DIRECTION_WEST: - if (my_head >= RECT_LEFT(*mon) + 1) - edge = RECT_LEFT(*mon) - 1; - else - edge = RECT_LEFT(*a) - 1; + edge = RECT_LEFT(*a) - 1; break; default: g_assert_not_reached(); @@ -4162,6 +4209,15 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, *dest = edge; *near_edge = TRUE; + /* search for edges of monitors */ + for (i = 0; i < screen_num_monitors; ++i) { + Rect *area = screen_area(self->desktop, i, NULL); + detect_edge(*area, dir, my_head, my_size, my_edge_start, + my_edge_size, dest, near_edge); + g_free(area); + } + + /* search for edges of clients */ for (it = client_list; it; it = g_list_next(it)) { ObClient *cur = it->data; @@ -4183,7 +4239,6 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, detect_edge(dock_area, dir, my_head, my_size, my_edge_start, my_edge_size, dest, near_edge); g_free(a); - g_free(mon); } void client_find_move_directional(ObClient *self, ObDirection dir,