X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=adbab7a74774e9e2b618910efdca192490e0961e;hb=0185445e3ab64ec4435f9b27164ce1508b840f86;hp=c57c66e84571ec5e4ec90813ffb6e3a150722924;hpb=4a2400c5c2f86cacbf907cfc13488cd212cc3d17;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index c57c66e8..adbab7a7 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -5,6 +5,7 @@ #include "startup.h" #include "screen.h" #include "moveresize.h" +#include "place.h" #include "prop.h" #include "extensions.h" #include "frame.h" @@ -13,11 +14,12 @@ #include "grab.h" #include "focus.h" #include "stacking.h" -#include "dispatch.h" #include "openbox.h" #include "group.h" #include "config.h" -#include "menu.h" +#include "menuframe.h" +#include "keyboard.h" +#include "mouse.h" #include "render/render.h" #include @@ -30,7 +32,8 @@ #define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \ ButtonMotionMask) -GList *client_list = NULL; +GList *client_list = NULL; +GSList *client_destructors = NULL; static void client_get_all(ObClient *self); static void client_toggle_border(ObClient *self, gboolean show); @@ -45,6 +48,7 @@ static void client_change_allowed_actions(ObClient *self); static void client_change_state(ObClient *self); static void client_apply_startup_state(ObClient *self); static void client_restore_session_state(ObClient *self); +static void client_restore_session_stacking(ObClient *self); void client_startup() { @@ -55,6 +59,16 @@ void client_shutdown() { } +void client_add_destructor(ObClientDestructorFunc func) +{ + client_destructors = g_slist_prepend(client_destructors, (gpointer)func); +} + +void client_remove_destructor(ObClientDestructorFunc func) +{ + client_destructors = g_slist_remove(client_destructors, (gpointer)func); +} + void client_set_list() { Window *windows, *win_it; @@ -230,7 +244,7 @@ void client_manage(Window window) /* create the ObClient struct, and populate it from the hints on the window */ - self = g_new(ObClient, 1); + self = g_new0(ObClient, 1); self->obwin.type = Window_Client; self->window = window; @@ -251,14 +265,15 @@ void client_manage(Window window) frame_grab_client(self->frame, self); - client_apply_startup_state(self); - grab_server(FALSE); + client_apply_startup_state(self); + /* update the focus lists */ focus_order_add_new(self); stacking_add(CLIENT_AS_WINDOW(self)); + client_restore_session_stacking(self); /* focus the new window? */ if (ob_state() != OB_STATE_STARTING && config_focus_new && @@ -268,6 +283,8 @@ void client_manage(Window window) (self->type == OB_CLIENT_TYPE_NORMAL || self->type == OB_CLIENT_TYPE_DIALOG)) { + activate = TRUE; +#if 0 if (self->desktop != screen_desktop) { /* activate the window */ activate = TRUE; @@ -297,14 +314,28 @@ void client_manage(Window window) activate = TRUE; } } +#endif } - dispatch_client(Event_Client_New, self, 0, 0); + if (ob_state() == OB_STATE_RUNNING) { + int x = self->area.x, ox = x; + int y = self->area.y, oy = y; - /* make sure the window is visible */ - client_move_onscreen(self, TRUE); + place_client(self, &x, &y); - screen_update_areas(); + client_find_onscreen(self, &x, &y, + self->frame->area.width, + self->frame->area.height, + client_normal(self)); + + if (x != ox || y != oy) + client_configure(self, OB_CORNER_TOPLEFT, x, y, + self->area.width, self->area.height, + TRUE, TRUE); + } + + /* make sure the window is visible */ + client_move_onscreen(self, client_normal(self)); client_showhide(self); @@ -324,10 +355,14 @@ void client_manage(Window window) client_list = g_list_append(client_list, self); g_hash_table_insert(window_map, &self->window, self); + /* this has to happen after we're in the client_list */ + screen_update_areas(); + /* update the list hints */ client_set_list(); - dispatch_client(Event_Client_Mapped, self, 0, 0); + keyboard_grab_for_client(self, TRUE); + mouse_grab_for_client(self, TRUE); ob_debug("Managed window 0x%lx (%s)\n", window, self->class); } @@ -338,13 +373,6 @@ void client_unmanage_all() client_unmanage(client_list->data); } -/* called by client_unmanage() to close any menus referencing this client */ -void client_close_menus(gpointer key, gpointer value, gpointer self) -{ - if (((ObMenu *)value)->client == (ObClient *)self) - menu_hide((ObMenu *)value); -} - void client_unmanage(ObClient *self) { guint j; @@ -352,9 +380,11 @@ void client_unmanage(ObClient *self) ob_debug("Unmanaging window: %lx (%s)\n", self->window, self->class); - dispatch_client(Event_Client_Destroy, self, 0, 0); g_assert(self != NULL); + keyboard_grab_for_client(self, FALSE); + mouse_grab_for_client(self, FALSE); + /* remove the window from our save set */ XChangeSaveSet(ob_display, self->window, SetModeDelete); @@ -395,13 +425,11 @@ void client_unmanage(ObClient *self) } } - if (moveresize_client == self) - moveresize_end(TRUE); - - /* close any windows that are attached to this window */ - g_hash_table_foreach(menu_hash, client_close_menus, self); - - + for (it = client_destructors; it; it = g_slist_next(it)) { + ObClientDestructorFunc func = (ObClientDestructorFunc) it->data; + func(self); + } + if (focus_client == self) { XEvent e; @@ -417,10 +445,6 @@ void client_unmanage(ObClient *self) self->group = NULL; } - /* dispatch the unmapped event */ - dispatch_client(Event_Client_Unmapped, self, 0, 0); - g_assert(self != NULL); - /* give the client its border back */ client_toggle_border(self, TRUE); @@ -463,30 +487,55 @@ void client_unmanage(ObClient *self) static void client_restore_session_state(ObClient *self) { - ObSessionState *s; + GList *it; - s = session_state_find(self); - if (!(s)) return; + if (!(it = session_state_find(self))) + return; + + self->session = it->data; - RECT_SET(self->area, s->x, s->y, s->w, s->h); + RECT_SET(self->area, self->session->x, self->session->y, + self->session->w, self->session->h); self->positioned = TRUE; - XResizeWindow(ob_display, self->window, s->w, s->h); + XResizeWindow(ob_display, self->window, + self->session->w, self->session->h); - self->desktop = s->desktop == DESKTOP_ALL ? s->desktop : - MIN(screen_num_desktops - 1, s->desktop); + self->desktop = (self->session->desktop == DESKTOP_ALL ? + self->session->desktop : + MIN(screen_num_desktops - 1, self->session->desktop)); PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); - self->shaded = s->shaded; - self->iconic = s->iconic; - self->skip_pager = s->skip_pager; - self->skip_taskbar = s->skip_taskbar; - self->fullscreen = s->fullscreen; - self->above = s->above; - self->below = s->below; - self->max_horz = s->max_horz; - self->max_vert = s->max_vert; + self->shaded = self->session->shaded; + self->iconic = self->session->iconic; + self->skip_pager = self->session->skip_pager; + self->skip_taskbar = self->session->skip_taskbar; + self->fullscreen = self->session->fullscreen; + self->above = self->session->above; + self->below = self->session->below; + self->max_horz = self->session->max_horz; + self->max_vert = self->session->max_vert; +} - session_state_free(s); +static void client_restore_session_stacking(ObClient *self) +{ + GList *it; + + if (!self->session) return; + + it = g_list_find(session_saved_state, self->session); + for (it = g_list_previous(it); it; it = g_list_previous(it)) { + GList *cit; + + for (cit = client_list; cit; cit = g_list_next(cit)) + if (session_state_cmp(it->data, cit->data)) + break; + if (cit) { + client_calc_layer(self); + stacking_below(CLIENT_AS_WINDOW(self), + CLIENT_AS_WINDOW(cit->data)); + break; + } + } } void client_move_onscreen(ObClient *self, gboolean rude) @@ -494,7 +543,8 @@ void client_move_onscreen(ObClient *self, gboolean rude) int x = self->area.x; int y = self->area.y; if (client_find_onscreen(self, &x, &y, - self->area.width, self->area.height, rude)) { + self->frame->area.width, + self->frame->area.height, rude)) { client_configure(self, OB_CORNER_TOPLEFT, x, y, self->area.width, self->area.height, TRUE, TRUE); @@ -614,25 +664,11 @@ static void client_toggle_border(ObClient *self, gboolean show) static void client_get_all(ObClient *self) { - /* update EVERYTHING!! */ - - self->ignore_unmaps = 0; - - /* defaults */ - self->frame = NULL; - self->title = self->icon_title = NULL; + /* non-zero defaults */ self->title_count = 1; - self->name = self->class = self->role = NULL; self->wmstate = NormalState; - self->transient = FALSE; - self->transients = NULL; - self->transient_for = NULL; self->layer = -1; - self->urgent = FALSE; - self->positioned = FALSE; self->decorate = TRUE; - self->group = NULL; - self->nicons = 0; client_get_area(self); client_update_transient_for(self); @@ -997,20 +1033,22 @@ void client_update_normal_hints(ObClient *self) void client_setup_decor_and_functions(ObClient *self) { /* start with everything (cept fullscreen) */ - self->decorations = (OB_FRAME_DECOR_TITLEBAR | - OB_FRAME_DECOR_HANDLE | - OB_FRAME_DECOR_GRIPS | - OB_FRAME_DECOR_BORDER | - OB_FRAME_DECOR_ICON | - OB_FRAME_DECOR_ALLDESKTOPS | - OB_FRAME_DECOR_ICONIFY | - OB_FRAME_DECOR_MAXIMIZE | - OB_FRAME_DECOR_SHADE); - self->functions = (OB_CLIENT_FUNC_RESIZE | - OB_CLIENT_FUNC_MOVE | - OB_CLIENT_FUNC_ICONIFY | - OB_CLIENT_FUNC_MAXIMIZE | - OB_CLIENT_FUNC_SHADE); + self->decorations = + (OB_FRAME_DECOR_TITLEBAR | + (ob_rr_theme->show_handle ? OB_FRAME_DECOR_HANDLE : 0) | + OB_FRAME_DECOR_GRIPS | + OB_FRAME_DECOR_BORDER | + OB_FRAME_DECOR_ICON | + OB_FRAME_DECOR_ALLDESKTOPS | + OB_FRAME_DECOR_ICONIFY | + OB_FRAME_DECOR_MAXIMIZE | + OB_FRAME_DECOR_SHADE); + self->functions = + (OB_CLIENT_FUNC_RESIZE | + OB_CLIENT_FUNC_MOVE | + OB_CLIENT_FUNC_ICONIFY | + OB_CLIENT_FUNC_MAXIMIZE | + OB_CLIENT_FUNC_SHADE); if (self->delete_window) { self->functions |= OB_CLIENT_FUNC_CLOSE; self->decorations |= OB_FRAME_DECOR_CLOSE; @@ -1093,10 +1131,14 @@ void client_setup_decor_and_functions(ObClient *self) self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE; } + /* kill the handle on fully maxed windows */ + if (self->max_vert && self->max_horz) + self->decorations &= ~OB_FRAME_DECOR_HANDLE; + /* finally, the user can have requested no decorations, which overrides everything */ if (!self->decorate) - self->decorations = 0; + self->decorations = OB_FRAME_DECOR_BORDER; /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) @@ -1113,13 +1155,8 @@ void client_setup_decor_and_functions(ObClient *self) client_change_allowed_actions(self); if (self->frame) { - /* this makes sure that these windows appear on all desktops */ - if (self->type == OB_CLIENT_TYPE_DESKTOP && - self->desktop != DESKTOP_ALL) - client_set_desktop(self, DESKTOP_ALL, FALSE); - - /* adjust the client's decorations, etc. */ - client_reconfigure(self); + /* adjust the client's decorations, etc. */ + client_reconfigure(self); } else { /* this makes sure that these windows appear on all desktops */ if (self->type == OB_CLIENT_TYPE_DESKTOP && @@ -1261,8 +1298,9 @@ void client_update_wmhints(ObClient *self) ur ? "ON" : "OFF"); /* fire the urgent callback if we're mapped, otherwise, wait until after we're mapped */ - if (self->frame) - dispatch_client(Event_Client_Urgent, self, self->urgent, 0); + if (self->frame) { + /* XXX do shit */ + } } } @@ -1375,12 +1413,13 @@ void client_update_strut(ObClient *self) guint num; guint32 *data; gboolean got = FALSE; + StrutPartial strut; if (PROP_GETA32(self->window, net_wm_strut_partial, cardinal, &data, &num)) { if (num == 12) { got = TRUE; - STRUT_PARTIAL_SET(self->strut, + STRUT_PARTIAL_SET(strut, data[0], data[2], data[1], data[3], data[4], data[5], data[8], data[9], data[6], data[7], data[10], data[11]); @@ -1392,7 +1431,7 @@ void client_update_strut(ObClient *self) PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) { if (num == 4) { got = TRUE; - STRUT_PARTIAL_SET(self->strut, + STRUT_PARTIAL_SET(strut, data[0], data[2], data[1], data[3], 0, 0, 0, 0, 0, 0, 0, 0); } @@ -1400,13 +1439,17 @@ void client_update_strut(ObClient *self) } if (!got) - STRUT_PARTIAL_SET(self->strut, 0, 0, 0, 0, + STRUT_PARTIAL_SET(strut, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - /* updating here is pointless while we're being mapped cuz we're not in - the client list yet */ - if (self->frame) - screen_update_areas(); + if (!STRUT_EQUAL(strut, self->strut)) { + self->strut = strut; + + /* updating here is pointless while we're being mapped cuz we're not in + the client list yet */ + if (self->frame) + screen_update_areas(); + } } void client_update_icons(ObClient *self) @@ -1681,7 +1724,7 @@ static void client_apply_startup_state(ObClient *self) client_shade(self, TRUE); } if (self->urgent) - dispatch_client(Event_Client_Urgent, self, self->urgent, 0); + /* XXX do shit */; if (self->max_vert && self->max_horz) { self->max_vert = self->max_horz = FALSE; @@ -1709,6 +1752,13 @@ void client_configure_full(ObClient *self, ObCorner anchor, gboolean force_reply) { gboolean moved = FALSE, resized = FALSE; + guint fdecor = self->frame->decorations; + gboolean fhorz = self->frame->max_horz; + + /* make the frame recalculate its dimentions n shit without changing + anything visible for real, this way the constraints below can work with + the updated frame dimensions. */ + frame_adjust_area(self->frame, TRUE, TRUE, TRUE); /* gets the frame's position */ frame_client_gravity(self->frame, &x, &y); @@ -1755,8 +1805,8 @@ void client_configure_full(ObClient *self, ObCorner anchor, /* set the size and position if maximized */ if (self->max_horz) { - x = a->x - self->frame->size.left; - w = a->width; + x = a->x; + w = a->width - self->frame->size.left - self->frame->size.right; } if (self->max_vert) { y = a->y; @@ -1781,6 +1831,7 @@ void client_configure_full(ObClient *self, ObCorner anchor, if (!(w == self->area.width && h == self->area.height)) { int basew, baseh, minw, minh; + int mw, mh, aw, ah; /* base size is substituted with min size if not specified */ if (self->base_size.width || self->base_size.height) { @@ -1799,33 +1850,31 @@ void client_configure_full(ObClient *self, ObCorner anchor, minh = self->base_size.height; } - if (user) { - /* for interactive resizing. have to move half an increment in each - direction. */ - - /* how far we are towards the next size inc */ - int mw = (w - basew) % self->size_inc.width; - int mh = (h - baseh) % self->size_inc.height; - /* amount to add */ - int aw = self->size_inc.width / 2; - int ah = self->size_inc.height / 2; - /* don't let us move into a new size increment */ - if (mw + aw >= self->size_inc.width) - aw = self->size_inc.width - mw - 1; - if (mh + ah >= self->size_inc.height) - ah = self->size_inc.height - mh - 1; - w += aw; - h += ah; + /* for interactive resizing. have to move half an increment in each + direction. */ + + /* how far we are towards the next size inc */ + mw = (w - basew) % self->size_inc.width; + mh = (h - baseh) % self->size_inc.height; + /* amount to add */ + aw = self->size_inc.width / 2; + ah = self->size_inc.height / 2; + /* don't let us move into a new size increment */ + if (mw + aw >= self->size_inc.width) + aw = self->size_inc.width - mw - 1; + if (mh + ah >= self->size_inc.height) + ah = self->size_inc.height - mh - 1; + w += aw; + h += ah; - /* if this is a user-requested resize, then check against min/max - sizes */ - - /* smaller than min size or bigger than max size? */ - if (w > self->max_size.width) w = self->max_size.width; - if (w < minw) w = minw; - if (h > self->max_size.height) h = self->max_size.height; - if (h < minh) h = minh; - } + /* if this is a user-requested resize, then check against min/max + sizes */ + + /* smaller than min size or bigger than max size? */ + if (w > self->max_size.width) w = self->max_size.width; + if (w < minw) w = minw; + if (h > self->max_size.height) h = self->max_size.height; + if (h < minh) h = minh; w -= basew; h -= baseh; @@ -1849,20 +1898,18 @@ void client_configure_full(ObClient *self, ObCorner anchor, w += basew; h += baseh; - if (user) { - /* adjust the height to match the width for the aspect ratios. - for this, min size is not substituted for base size ever. */ - w -= self->base_size.width; - h -= self->base_size.height; + /* adjust the height to match the width for the aspect ratios. + for this, min size is not substituted for base size ever. */ + w -= self->base_size.width; + h -= self->base_size.height; - if (self->min_ratio) - if (h * self->min_ratio > w) h = (int)(w / self->min_ratio); - if (self->max_ratio) - if (h * self->max_ratio < w) h = (int)(w / self->max_ratio); + if (self->min_ratio) + if (h * self->min_ratio > w) h = (int)(w / self->min_ratio); + if (self->max_ratio) + if (h * self->max_ratio < w) h = (int)(w / self->max_ratio); - w += self->base_size.width; - h += self->base_size.height; - } + w += self->base_size.width; + h += self->base_size.height; } switch (anchor) { @@ -1887,18 +1934,18 @@ void client_configure_full(ObClient *self, ObCorner anchor, /* for app-requested resizes, always resize if 'resized' is true. for user-requested ones, only resize if final is true, or when - resizing in opaque mode */ + resizing in redraw mode */ if ((!user && resized) || - (user && (final || (resized && config_opaque_resize)))) + (user && (final || (resized && config_redraw_resize)))) XResizeWindow(ob_display, self->window, w, h); /* move/resize the frame to match the request */ if (self->frame) { - if (self->decorations != self->frame->decorations) + if (self->decorations != fdecor || self->max_horz != fhorz) moved = resized = TRUE; if (moved || resized) - frame_adjust_area(self->frame, moved, resized); + frame_adjust_area(self->frame, moved, resized, FALSE); if (!resized && (force_reply || ((!user && moved) || (user && final)))) { @@ -2034,9 +2081,6 @@ static void client_iconify_recursive(ObClient *self, client_change_state(self); client_showhide(self); screen_update_areas(); - - dispatch_client(iconic ? Event_Client_Unmapped : Event_Client_Mapped, - self, 0, 0); } /* iconify all transients */ @@ -2151,6 +2195,8 @@ void client_maximize(ObClient *self, gboolean max, int dir, gboolean savearea) client_change_state(self); /* change the state hints on the client */ + client_setup_decor_and_functions(self); + /* figure out where the client should be going */ frame_frame_gravity(self->frame, &x, &y); client_configure(self, OB_CORNER_TOPLEFT, x, y, w, h, TRUE, TRUE); @@ -2168,7 +2214,7 @@ void client_shade(ObClient *self, gboolean shade) self->shaded = shade; client_change_state(self); /* resize the frame to just the titlebar */ - frame_adjust_area(self->frame, FALSE, FALSE); + frame_adjust_area(self->frame, FALSE, FALSE, FALSE); } void client_close(ObClient *self) @@ -2236,8 +2282,6 @@ void client_set_desktop_recursive(ObClient *self, focus_order_to_top(self); else focus_order_to_bottom(self); - - dispatch_client(Event_Client_Desktop, self, target, old); } /* move all transients */ @@ -2522,16 +2566,19 @@ void client_unfocus(ObClient *self) focus_fallback(OB_FOCUS_FALLBACK_UNFOCUSING); } -void client_activate(ObClient *self) +void client_activate(ObClient *self, gboolean here) { if (client_normal(self) && screen_showing_desktop) screen_show_desktop(FALSE); if (self->iconic) client_iconify(self, FALSE, FALSE); if (self->desktop != DESKTOP_ALL && - self->desktop != screen_desktop) - screen_set_desktop(self->desktop); - else if (!self->frame->visible) + self->desktop != screen_desktop) { + if (here) + client_set_desktop(self, screen_desktop, FALSE); + else + screen_set_desktop(self->desktop); + } else if (!self->frame->visible) /* if its not visible for other reasons, then don't mess with it */ return; @@ -2614,7 +2661,8 @@ ObClient *client_find_directional(ObClient *c, ObDirection dir) his_cy = (cur->frame->area.y - my_cy) + cur->frame->area.height / 2; - if(dir > 3) { + if(dir == OB_DIRECTION_NORTHEAST || dir == OB_DIRECTION_SOUTHEAST || + dir == OB_DIRECTION_SOUTHWEST || dir == OB_DIRECTION_NORTHWEST) { int tx; /* Rotate the diagonals 45 degrees counterclockwise. * To do this, multiply the matrix /+h +h\ with the @@ -2742,3 +2790,194 @@ gchar* client_get_sm_client_id(ObClient *self) PROP_GETS(self->group->leader, sm_client_id, locale, &id); return id; } + +/* 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. + */ +int client_directional_edge_search(ObClient *c, ObDirection dir) +{ + int dest; + int my_edge_start, my_edge_end, my_offset; + GList *it; + Rect *a; + + if(!client_list) + return -1; + + a = screen_area(c->desktop); + + 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; + + dest = a->y; /* default: top of screen */ + + for(it = g_list_first(client_list); it; it = it->next) { + int 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; + + 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; + + 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; + + } + 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; + + dest = a->y + a->height; /* default: bottom of screen */ + + for(it = g_list_first(client_list); it; it = it->next) { + int 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; + + his_edge_start = cur->frame->area.x; + his_edge_end = cur->frame->area.x + cur->frame->area.width; + his_offset = cur->frame->area.y; + + + 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; + + } + 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; + + dest = a->x; /* default: leftmost egde of screen */ + + for(it = g_list_first(client_list); it; it = it->next) { + int 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; + + 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; + + 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; + + + } + 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; + + dest = a->x + a->width; /* default: rightmost edge of screen */ + + for(it = g_list_first(client_list); it; it = it->next) { + int 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; + + his_edge_start = cur->frame->area.y; + his_edge_end = cur->frame->area.y + cur->frame->area.height; + his_offset = cur->frame->area.x; + + 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; + + } + break; + case OB_DIRECTION_NORTHEAST: + case OB_DIRECTION_SOUTHEAST: + case OB_DIRECTION_NORTHWEST: + case OB_DIRECTION_SOUTHWEST: + /* not implemented */ + break; + default: + g_assert_not_reached(); + } + return dest; +}