/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
-
-client.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.
+
+ client.c for the Openbox window manager
+ Copyright (c) 2006 Mikael Magnusson
+ 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 "client.h"
windows = NULL;
PROP_SETA32(RootWindow(ob_display, ob_screen),
- net_client_list, window, (guint32*)windows, size);
+ net_client_list, window, (gulong*)windows, size);
if (windows)
g_free(windows);
XFree(children);
}
+static ObAppSettings *get_settings(ObClient *client)
+{
+ GSList *a = config_per_app_settings;
+
+ while (a) {
+ ObAppSettings *app = (ObAppSettings *) a->data;
+
+ if (
+ (app->name && !app->class && !strcmp(app->name, client->name))
+ || (app->class && !app->name && !strcmp(app->class, client->class))
+ || (app->class && app->name && !strcmp(app->class, client->class)
+ && !strcmp(app->name, client->name))
+ ) {
+ ob_debug("Window matching: %s\n", app->name);
+ /* Match if no role was specified in the per app setting, or if the string
+ * matches the beginning of the role, since apps like to set the role to
+ * things like browser-window-23c4b2f */
+ if (!app->role || !strncmp(app->role, client->role, strlen(app->role)))
+ return app;
+ }
+
+ a = a->next;
+ }
+ return NULL;
+}
+
void client_manage(Window window)
{
ObClient *self;
XSetWindowAttributes attrib_set;
XWMHints *wmhint;
gboolean activate = FALSE;
+ ObAppSettings *settings;
grab_server(TRUE);
client_apply_startup_state(self);
+ /* get and set application level settings */
+ settings = get_settings(self);
+
stacking_add(CLIENT_AS_WINDOW(self));
client_restore_session_stacking(self);
+ if (settings) {
+ /* Don't worry, we won't actually both shade and undecorate the
+ * window when push comes to shove. */
+ if (settings->shade != -1)
+ client_shade(self, settings->shade);
+ if (settings->decor != -1)
+ client_set_undecorated(self, !settings->decor);
+ if (settings->iconic != -1)
+ client_iconify(self, settings->iconic, FALSE);
+ if (settings->skip_pager != -1) {
+ self->skip_pager = !!settings->skip_pager;
+ client_change_state(self);
+ }
+ if (settings->skip_taskbar != -1) {
+ self->skip_taskbar = !!settings->skip_taskbar;
+ client_change_state(self);
+ }
+
+ /* 1 && -1 shouldn't be possible by the code in config.c */
+ if (settings->max_vert == 1 && settings->max_horz == 1)
+ client_maximize(self, TRUE, 0, TRUE);
+ else if (settings->max_vert == 0 && settings->max_horz == 0)
+ client_maximize(self, FALSE, 0, TRUE);
+ else if (settings->max_vert == 1 && settings->max_horz == 0) {
+ client_maximize(self, TRUE, 2, TRUE);
+ client_maximize(self, FALSE, 1, TRUE);
+ } else if (settings->max_vert == 0 && settings->max_horz == 1) {
+ client_maximize(self, TRUE, 1, TRUE);
+ client_maximize(self, FALSE, 2, TRUE);
+ }
+
+ if (settings->fullscreen != -1)
+ client_fullscreen(self, !!settings->fullscreen, TRUE);
+
+ if (settings->desktop < screen_num_desktops
+ || settings->desktop == DESKTOP_ALL)
+ client_set_desktop(self, settings->desktop, TRUE);
+
+ if (settings->layer > -2 && settings->layer < 2)
+ client_set_layer(self, settings->layer);
+
+ }
+
/* focus the new window? */
if (ob_state() != OB_STATE_STARTING &&
- (config_focus_new || client_search_focus_parent(self)) &&
+ (config_focus_new || client_search_focus_parent(self)) ||
+ (settings && settings->focus == TRUE) &&
/* note the check against Type_Normal/Dialog, not client_normal(self),
which would also include other types. in this case we want more
strict rules for focus */
if (ob_state() == OB_STATE_RUNNING) {
gint x = self->area.x, ox = x;
gint y = self->area.y, oy = y;
+ gboolean transient;
- place_client(self, &x, &y);
+ transient = place_client(self, &x, &y, settings);
- /* make sure the window is visible */
+ /* make sure the window is visible. */
client_find_onscreen(self, &x, &y,
self->frame->area.width,
self->frame->area.height,
/* non-normal clients has less rules, and
- windows that are being restored from a session
- do also. we can assume you want it back where
- you saved it */
- client_normal(self) && !self->session);
-
- if (x != ox || y != oy)
+ windows that are being restored from a
+ session do also. we can assume you want
+ it back where you saved it. Clients saying
+ they placed themselves are subjected to
+ harder rules, ones that are placed by
+ place.c or by the user are allowed partially
+ off-screen and on xinerama divides (ie,
+ it is up to the placement routines to avoid
+ the xinerama divides) */
+ transient ||
+ (((self->positioned & PPosition) &&
+ !(self->positioned & USPosition)) &&
+ client_normal(self) &&
+ !self->session));
+ if (x != ox || y != oy)
client_move(self, x, y);
}
+ keyboard_grab_for_client(self, TRUE);
+ mouse_grab_for_client(self, TRUE);
+
client_showhide(self);
/* use client_focus instead of client_activate cuz client_activate does
/* update the list hints */
client_set_list();
- keyboard_grab_for_client(self, TRUE);
- mouse_grab_for_client(self, TRUE);
-
ob_debug("Managed window 0x%lx (%s)\n", window, self->class);
}
/* tell our parent(s) that we're gone */
if (self->transient_for == OB_TRAN_GROUP) { /* transient of group */
- GSList *it;
-
for (it = self->group->members; it; it = g_slist_next(it))
if (it->data != self)
((ObClient*)it->data)->transients =
self->session = it->data;
RECT_SET_POINT(self->area, self->session->x, self->session->y);
- self->positioned = TRUE;
+ self->positioned = PPosition;
if (self->session->w > 0)
self->area.width = self->session->w;
if (self->session->h > 0)
would be */
/* XXX watch for xinerama dead areas */
-
- a = screen_area(self->desktop);
+ /* This makes sure windows aren't entirely outside of the screen so you
+ * can't see them at all */
if (client_normal(self)) {
+ a = screen_area(self->desktop);
if (!self->strut.right && *x >= a->x + a->width - 1)
*x = a->x + a->width - self->frame->area.width;
if (!self->strut.bottom && *y >= a->y + a->height - 1)
*y = a->y;
}
+ /* This here doesn't let windows even a pixel outside the screen,
+ * when called from client_manage, programs placing themselves are
+ * forced completely onscreen, while things like
+ * xterm -geometry resolution-width/2 will work fine. Trying to
+ * place it completely offscreen will be handled in the above code.
+ * Sorry for this confused comment, i am tired. */
if (rude) {
- /* this is my MOZILLA BITCHSLAP. oh ya it fucking feels good.
- Java can suck it too. */
-
+ /* avoid the xinerama monitor divide while we're at it,
+ * remember to fix the placement stuff to avoid it also and
+ * then remove this XXX */
+ a = screen_physical_area_monitor(client_monitor(self));
/* dont let windows map/move into the strut unless they
are bigger than the available area */
if (w <= a->width) {
/* normal windows can't request placement! har har
if (!client_normal(self))
*/
- self->positioned = !!(size.flags & (PPosition|USPosition));
+ self->positioned = (size.flags & (PPosition|USPosition));
if (size.flags & PWinGravity) {
self->gravity = size.win_gravity;
if (size.flags & PBaseSize)
SIZE_SET(self->base_size, size.base_width, size.base_height);
- if (size.flags & PResizeInc)
+ if (size.flags & PResizeInc && size.width_inc && size.height_inc)
SIZE_SET(self->size_inc, size.width_inc, size.height_inc);
}
}
/* start with everything (cept fullscreen) */
self->decorations =
(OB_FRAME_DECOR_TITLEBAR |
- (ob_rr_theme->show_handle ? OB_FRAME_DECOR_HANDLE : 0) |
+ OB_FRAME_DECOR_HANDLE |
OB_FRAME_DECOR_GRIPS |
OB_FRAME_DECOR_BORDER |
OB_FRAME_DECOR_ICON |
if (! ((self->mwmhints.decorations & OB_MWM_DECOR_HANDLE) ||
(self->mwmhints.decorations & OB_MWM_DECOR_TITLE)))
/* if the mwm hints request no handle or title, then all
- decorations are disabled */
- self->decorations = 0;
+ decorations are disabled, but keep the border if that's
+ specified */
+ if (self->mwmhints.decorations & OB_MWM_DECOR_BORDER)
+ self->decorations = OB_FRAME_DECOR_BORDER;
+ else
+ self->decorations = 0;
}
}
/* 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; //&= OB_FRAME_DECOR_BORDER;
+ if (self->undecorated) {
+ if (config_theme_keepborder)
+ self->decorations &= OB_FRAME_DECOR_BORDER;
+ else
+ self->decorations = 0;
+ }
/* if we don't have a titlebar, then we cannot shade! */
if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR))
static void client_change_allowed_actions(ObClient *self)
{
- guint32 actions[9];
+ gulong actions[9];
gint num = 0;
/* desktop windows are kept on all desktops */
old_title = self->title;
/* try netwm */
- if (!PROP_GETS(self->window, net_wm_name, utf8, &data))
+ if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
/* try old x stuff */
- if (!PROP_GETS(self->window, wm_name, locale, &data))
+ if (!(PROP_GETS(self->window, wm_name, locale, &data)
+ || PROP_GETS(self->window, wm_name, utf8, &data))) {
// http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
- if (self->transient)
- data = '\0';
- else
+ if (self->transient) {
+ data = g_strdup("");
+ goto no_number;
+ } else
data = g_strdup("Unnamed Window");
+ }
+ }
- /* did the title change? then reset the title_count */
- if (old_title && 0 != strncmp(old_title, data, strlen(data)))
- self->title_count = 1;
+ if (config_title_number) {
- /* look for duplicates and append a number */
- nums = 0;
- for (it = client_list; it; it = g_list_next(it))
- if (it->data != self) {
- ObClient *c = it->data;
- if (0 == strncmp(c->title, data, strlen(data)))
- nums |= 1 << c->title_count;
- }
- /* find first free number */
- for (i = 1; i <= 32; ++i)
- if (!(nums & (1 << i))) {
- if (self->title_count == 1 || i == 1)
- self->title_count = i;
- break;
+ /* did the title change? then reset the title_count */
+ if (old_title && 0 != strncmp(old_title, data, strlen(data)))
+ self->title_count = 1;
+
+ /* look for duplicates and append a number */
+ nums = 0;
+ for (it = client_list; it; it = g_list_next(it))
+ if (it->data != self) {
+ ObClient *c = it->data;
+ if (0 == strncmp(c->title, data, strlen(data)))
+ nums |= 1 << c->title_count;
+ }
+ /* find first free number */
+ for (i = 1; i <= 32; ++i)
+ if (!(nums & (1 << i))) {
+ if (self->title_count == 1 || i == 1)
+ self->title_count = i;
+ break;
+ }
+ /* dont display the number for the first window */
+ if (self->title_count > 1) {
+ gchar *ndata;
+ ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
+ g_free(data);
+ data = ndata;
}
- /* dont display the number for the first window */
- if (self->title_count > 1) {
- gchar *ndata;
- ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
- g_free(data);
- data = ndata;
- }
+ } else
+ self->title_count = 1;
+no_number:
PROP_SETS(self->window, net_wm_visible_name, data);
-
self->title = data;
if (self->frame)
/* try netwm */
if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
/* try old x stuff */
- if (!PROP_GETS(self->window, wm_icon_name, locale, &data)) {
+ if (!(PROP_GETS(self->window, wm_icon_name, locale, &data)
+ || PROP_GETS(self->window, wm_icon_name, utf8, &data))) {
data = g_strdup(self->title);
read_title = FALSE;
}
- /* append the title count, dont display the number for the first window */
+ /* append the title count, dont display the number for the first window.
+ * We don't need to check for config_title_number here since title_count
+ * is not set above 1 then. */
if (read_title && self->title_count > 1) {
gchar *vdata, *ndata;
ndata = g_strdup_printf(" - [%u]", self->title_count);
static void client_change_state(ObClient *self)
{
- guint32 state[2];
- guint32 netstate[11];
+ gulong state[2];
+ gulong netstate[11];
guint num;
state[0] = self->wmstate;
else if (self->type == OB_CLIENT_TYPE_DESKTOP)
l = OB_STACKING_LAYER_DESKTOP;
else if (self->type == OB_CLIENT_TYPE_DOCK) {
- if (self->above) l = OB_STACKING_LAYER_DOCK_ABOVE;
- else if (self->below) l = OB_STACKING_LAYER_DOCK_BELOW;
- else l = OB_STACKING_LAYER_DOCK_NORMAL;
+ if (self->below) l = OB_STACKING_LAYER_NORMAL;
+ else l = OB_STACKING_LAYER_ABOVE;
}
else if (self->above) l = OB_STACKING_LAYER_ABOVE;
else if (self->below) l = OB_STACKING_LAYER_BELOW;
/* set the size and position if fullscreen */
if (self->fullscreen) {
-#ifdef VIDMODE
- gint dot;
- XF86VidModeModeLine mode;
-#endif
Rect *a;
guint i;
i = client_monitor(self);
a = screen_physical_area_monitor(i);
-#ifdef VIDMODE
- if (i == 0 && /* primary head */
- extensions_vidmode &&
- XF86VidModeGetViewPort(ob_display, ob_screen, &x, &y) &&
- /* get the mode last so the mode.privsize isnt freed incorrectly */
- XF86VidModeGetModeLine(ob_display, ob_screen, &dot, &mode)) {
- x += a->x;
- y += a->y;
- w = mode.hdisplay;
- h = mode.vdisplay;
- if (mode.privsize) XFree(mode.private);
- } else
-#endif
- {
- x = a->x;
- y = a->y;
- w = a->width;
- h = a->height;
- }
+ x = a->x;
+ y = a->y;
+ w = a->width;
+ h = a->height;
user = FALSE; /* ignore that increment etc shit when in fullscreen */
} else {
focus_order_remove(self);
focus_order_add_new(self);
- /* this is here cuz with the VIDMODE extension, the viewport can
- change while a fullscreen window is iconic, and when it
- uniconifies, it would be nice if it did so to the new position
- of the viewport */
- client_reconfigure(self);
-
changed = TRUE;
}
}
gboolean max_horz = self->max_horz;
gboolean max_vert = self->max_vert;
gboolean modal = self->modal;
+ gboolean iconic = self->iconic;
gint i;
if (!(action == prop_atoms.net_wm_state_add ||
action = self->skip_pager ?
prop_atoms.net_wm_state_remove :
prop_atoms.net_wm_state_add;
+ else if (state == prop_atoms.net_wm_state_hidden)
+ action = self->iconic ?
+ prop_atoms.net_wm_state_remove :
+ prop_atoms.net_wm_state_add;
else if (state == prop_atoms.net_wm_state_fullscreen)
action = fullscreen ?
prop_atoms.net_wm_state_remove :
self->skip_taskbar = TRUE;
} else if (state == prop_atoms.net_wm_state_skip_pager) {
self->skip_pager = TRUE;
+ } else if (state == prop_atoms.net_wm_state_hidden) {
+ iconic = TRUE;
} else if (state == prop_atoms.net_wm_state_fullscreen) {
fullscreen = TRUE;
} else if (state == prop_atoms.net_wm_state_above) {
self->skip_taskbar = FALSE;
} else if (state == prop_atoms.net_wm_state_skip_pager) {
self->skip_pager = FALSE;
+ } else if (state == prop_atoms.net_wm_state_hidden) {
+ iconic = FALSE;
} else if (state == prop_atoms.net_wm_state_fullscreen) {
fullscreen = FALSE;
} else if (state == prop_atoms.net_wm_state_above) {
transients needs to change */
client_raise(self);
}
+ if (iconic != self->iconic)
+ client_iconify(self, iconic, FALSE);
+
client_calc_layer(self);
client_change_state(self); /* change the hint to reflect these changes */
}
return TRUE;
}
+/* Used when the current client is closed, focus_last will then prevent
+ * focus from going to the mouse pointer */
void client_unfocus(ObClient *self)
{
if (focus_client == self) {
#ifdef DEBUG_FOCUS
ob_debug("client_unfocus for %lx\n", self->window);
#endif
- focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING);
+ focus_fallback(OB_FOCUS_FALLBACK_CLOSED);
}
}
continue;
if (!client_normal(cur))
continue;
- if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
+ /* using c->desktop instead of screen_desktop doesn't work if the
+ * current window was omnipresent, hope this doesn't have any other
+ * side effects */
+ if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
continue;
if(cur->iconic)
continue;
if (self->undecorated != undecorated) {
self->undecorated = undecorated;
client_setup_decor_and_functions(self);
+ /* Make sure the client knows it might have moved. Maybe there is a
+ * better way of doing this so only one client_configure is sent, but
+ * since 125 of these are sent per second when moving the window (with
+ * user = FALSE) i doubt it matters much.
+ */
+ client_configure(self, OB_CORNER_TOPLEFT, self->area.x, self->area.y,
+ self->area.width, self->area.height, TRUE, TRUE);
client_change_state(self); /* reflect this in the state hints */
}
}
+/* Determines which physical monitor a client is on by calculating the
+ area of the part of the client on each monitor. The number of the
+ monitor containing the greatest area of the client is returned.*/
guint client_monitor(ObClient *self)
{
guint i;
&self->sm_client_id);
}
+#define WANT_EDGE(cur, c) \
+ if(cur == c) \
+ continue; \
+ if(!client_normal_or_dock(cur)) \
+ continue; \
+ if(screen_desktop != cur->desktop && cur->desktop != DESKTOP_ALL) \
+ continue; \
+ if(cur->iconic) \
+ continue; \
+ if(cur->layer < c->layer && !config_resist_layers_below) \
+ continue;
+
+#define HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end) \
+ if ((his_edge_start >= my_edge_start && \
+ his_edge_start <= my_edge_end) || \
+ (my_edge_start >= his_edge_start && \
+ my_edge_start <= his_edge_end)) \
+ dest = his_offset;
+
/* finds the nearest edge in the given direction from the current client
* note to self: the edge is the -frame- edge (the actual one), not the
* client edge.
*/
-gint client_directional_edge_search(ObClient *c, ObDirection dir)
+gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
{
- gint dest;
+ gint dest, monitor_dest;
gint my_edge_start, my_edge_end, my_offset;
GList *it;
- Rect *a;
+ Rect *a, *monitor;
if(!client_list)
return -1;
a = screen_area(c->desktop);
+ monitor = screen_area_monitor(c->desktop, client_monitor(c));
switch(dir) {
case OB_DIRECTION_NORTH:
my_edge_start = c->frame->area.x;
my_edge_end = c->frame->area.x + c->frame->area.width;
- my_offset = c->frame->area.y;
+ my_offset = c->frame->area.y + (hang ? c->frame->area.height : 0);
/* default: top of screen */
- dest = a->y;
-
- for(it = client_list; it; it = g_list_next(it)) {
+ dest = a->y + (hang ? c->frame->area.height : 0);
+ monitor_dest = monitor->y + (hang ? c->frame->area.height : 0);
+ /* if the monitor edge comes before the screen edge, */
+ /* use that as the destination instead. (For xinerama) */
+ if (monitor_dest != dest && my_offset > monitor_dest)
+ dest = monitor_dest;
+
+ for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
- if(cur == c)
- continue;
- if(!client_normal(cur))
- continue;
- if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
- continue;
- if(cur->iconic)
- continue;
+ WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.x;
his_edge_end = cur->frame->area.x + cur->frame->area.width;
- his_offset = cur->frame->area.y + cur->frame->area.height;
+ his_offset = cur->frame->area.y + (hang ? 0 : cur->frame->area.height);
if(his_offset + 1 > my_offset)
continue;
if(his_offset < dest)
continue;
-
- if(his_edge_start >= my_edge_start &&
- his_edge_start <= my_edge_end)
- dest = his_offset;
-
- if(my_edge_start >= his_edge_start &&
- my_edge_start <= his_edge_end)
- dest = his_offset;
+ HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_SOUTH:
my_edge_start = c->frame->area.x;
my_edge_end = c->frame->area.x + c->frame->area.width;
- my_offset = c->frame->area.y + c->frame->area.height;
+ my_offset = c->frame->area.y + (hang ? 0 : c->frame->area.height);
/* default: bottom of screen */
- dest = a->y + a->height;
-
- for(it = client_list; it; it = g_list_next(it)) {
+ dest = a->y + a->height - (hang ? c->frame->area.height : 0);
+ monitor_dest = monitor->y + monitor->height - (hang ? c->frame->area.height : 0);
+ /* if the monitor edge comes before the screen edge, */
+ /* use that as the destination instead. (For xinerama) */
+ if (monitor_dest != dest && my_offset < monitor_dest)
+ dest = monitor_dest;
+
+ for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
- if(cur == c)
- continue;
- if(!client_normal(cur))
- continue;
- if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
- continue;
- if(cur->iconic)
- continue;
+ WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.x;
his_edge_end = cur->frame->area.x + cur->frame->area.width;
- his_offset = cur->frame->area.y;
+ his_offset = cur->frame->area.y + (hang ? cur->frame->area.height : 0);
if(his_offset - 1 < my_offset)
if(his_offset > dest)
continue;
-
- if(his_edge_start >= my_edge_start &&
- his_edge_start <= my_edge_end)
- dest = his_offset;
-
- if(my_edge_start >= his_edge_start &&
- my_edge_start <= his_edge_end)
- dest = his_offset;
+ HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_WEST:
my_edge_start = c->frame->area.y;
my_edge_end = c->frame->area.y + c->frame->area.height;
- my_offset = c->frame->area.x;
+ my_offset = c->frame->area.x + (hang ? c->frame->area.width : 0);
/* default: leftmost egde of screen */
- dest = a->x;
-
- for(it = client_list; it; it = g_list_next(it)) {
+ dest = a->x + (hang ? c->frame->area.width : 0);
+ monitor_dest = monitor->x + (hang ? c->frame->area.width : 0);
+ /* if the monitor edge comes before the screen edge, */
+ /* use that as the destination instead. (For xinerama) */
+ if (monitor_dest != dest && my_offset > monitor_dest)
+ dest = monitor_dest;
+
+ for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
- if(cur == c)
- continue;
- if(!client_normal(cur))
- continue;
- if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
- continue;
- if(cur->iconic)
- continue;
+ WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.y;
his_edge_end = cur->frame->area.y + cur->frame->area.height;
- his_offset = cur->frame->area.x + cur->frame->area.width;
+ his_offset = cur->frame->area.x + (hang ? 0 : cur->frame->area.width);
if(his_offset + 1 > my_offset)
continue;
-
+
if(his_offset < dest)
continue;
-
- if(his_edge_start >= my_edge_start &&
- his_edge_start <= my_edge_end)
- dest = his_offset;
-
- if(my_edge_start >= his_edge_start &&
- my_edge_start <= his_edge_end)
- dest = his_offset;
-
+ HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
- break;
+ break;
case OB_DIRECTION_EAST:
my_edge_start = c->frame->area.y;
my_edge_end = c->frame->area.y + c->frame->area.height;
- my_offset = c->frame->area.x + c->frame->area.width;
+ my_offset = c->frame->area.x + (hang ? 0 : c->frame->area.width);
/* default: rightmost edge of screen */
- dest = a->x + a->width;
-
- for(it = client_list; it; it = g_list_next(it)) {
+ dest = a->x + a->width - (hang ? c->frame->area.width : 0);
+ monitor_dest = monitor->x + monitor->width - (hang ? c->frame->area.width : 0);
+ /* if the monitor edge comes before the screen edge, */
+ /* use that as the destination instead. (For xinerama) */
+ if (monitor_dest != dest && my_offset < monitor_dest)
+ dest = monitor_dest;
+
+ for(it = client_list; it && my_offset != dest; it = g_list_next(it)) {
gint his_edge_start, his_edge_end, his_offset;
ObClient *cur = it->data;
- if(cur == c)
- continue;
- if(!client_normal(cur))
- continue;
- if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL)
- continue;
- if(cur->iconic)
- continue;
+ WANT_EDGE(cur, c)
his_edge_start = cur->frame->area.y;
his_edge_end = cur->frame->area.y + cur->frame->area.height;
- his_offset = cur->frame->area.x;
+ his_offset = cur->frame->area.x + (hang ? cur->frame->area.width : 0);
if(his_offset - 1 < my_offset)
continue;
if(his_offset > dest)
continue;
-
- if(his_edge_start >= my_edge_start &&
- his_edge_start <= my_edge_end)
- dest = his_offset;
-
- if(my_edge_start >= his_edge_start &&
- my_edge_start <= his_edge_end)
- dest = his_offset;
+ HIT_EDGE(my_edge_start, my_edge_end, his_edge_start, his_edge_end)
}
break;
case OB_DIRECTION_NORTHEAST:
/* not implemented */
default:
g_assert_not_reached();
+ dest = 0; /* suppress warning */
}
return dest;
}