X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=787ed673739e4a72d75d6d4c3074baf1d3f759d7;hb=6c538915c86b0330bd78e8d8f3e77d78cf0c5680;hp=064d68512572390f96db8fd68250b4f85f9245fb;hpb=ad8a7e2e025cd6eba8f7b8b29f85cb9e81b808b5;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 064d6851..787ed673 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -1281,88 +1281,45 @@ static void client_update_transient_tree(ObClient *self, oldgtran == newgtran && oldparent == newparent) return; - /** Remove the client from the transient tree wherever it has changed **/ + /** Remove the client from the transient tree **/ - /* If the window is becoming a direct transient for a window in its group - then any group transients which were our children and are now becoming - our parents need to stop being our children. - - Group transients can't be children of group transients already, but - we could have any number of direct parents above up, any of which could - be transient for the group, and we need to remove it from our children. - */ - if (!oldgtran && oldparent != newparent && newparent != NULL && - newgroup != NULL && newgroup == oldgroup && - client_normal(newparent)) - { - ObClient *look = client_search_top_direct_parent(newparent); - self->transients = g_slist_remove(self->transients, look); - look->parents = g_slist_remove(look->parents, self); + for (it = self->transients; it; it = next) { + next = g_slist_next(it); + c = it->data; + self->transients = g_slist_delete_link(self->transients, it); + c->parents = g_slist_remove(c->parents, self); } - - - /* If the group changed, or if we are just becoming transient for the - group, then we need to remove any old group transient windows - from our children. But if we were already transient for the group, then - other group transients are not our children. */ - if ((oldgroup != newgroup || (newgtran && oldgtran != newgtran)) && - oldgroup != NULL && !oldgtran) - { - for (it = self->transients; it; it = next) { - next = g_slist_next(it); - c = it->data; - if (c->group == oldgroup && client_normal(self)) { - self->transients = g_slist_delete_link(self->transients, it); - c->parents = g_slist_remove(c->parents, self); - } - } + for (it = self->parents; it; it = next) { + next = g_slist_next(it); + c = it->data; + self->parents = g_slist_delete_link(self->parents, it); + c->transients = g_slist_remove(c->transients, self); } - /* If we used to be transient for a group and now we are not, or we're - transient for a new group, then we need to remove ourselves from all - our ex-parents */ - if (oldgtran && (oldgroup != newgroup || oldgtran != newgtran)) - { - for (it = self->parents; it; it = next) { - next = g_slist_next(it); - c = it->data; - if (!c->transient_for_group && client_normal(c)) { - c->transients = g_slist_remove(c->transients, self); - self->parents = g_slist_delete_link(self->parents, it); - } - } - } - /* If we used to be transient for a single window and we are no longer - transient for it, then we need to remove ourself from its children */ - else if (oldparent && oldparent != newparent && - client_normal(oldparent)) - { - oldparent->transients = g_slist_remove(oldparent->transients, self); - self->parents = g_slist_remove(self->parents, oldparent); - } - - /** Re-add the client to the transient tree wherever it has changed **/ + /** Re-add the client to the transient tree **/ - /* If we're now transient for a group and we weren't transient for it - before then we need to add ourselves to all our new parents */ - if (newgtran && (oldgroup != newgroup || oldgtran != newgtran)) - { - for (it = oldgroup->members; it; it = g_slist_next(it)) { + /* If we're transient for a group then we need to add ourselves to all our + parents */ + if (newgtran) { + for (it = newgroup->members; it; it = g_slist_next(it)) { c = it->data; - if (c != self && !c->transient_for_group && client_normal(c)) + if (c != self && + !client_search_top_direct_parent(c)->transient_for_group && + client_normal(c)) { c->transients = g_slist_prepend(c->transients, self); self->parents = g_slist_prepend(self->parents, c); } } } - /* If we are now transient for a single window which we weren't before, - we need to add ourselves to its children + + /* If we are now transient for a single window we need to add ourselves to + its children WARNING: Cyclical transient ness is possible if two windows are transient for eachother. */ - else if (newparent && newparent != oldparent && + else if (newparent && /* don't make ourself its child if it is already our child */ !client_is_direct_child(self, newparent) && client_normal(newparent)) @@ -1371,9 +1328,8 @@ static void client_update_transient_tree(ObClient *self, self->parents = g_slist_prepend(self->parents, newparent); } - /* If the group changed then we need to add any new group transient - windows to our children. But if we're transient for the group, then - other group transients are not our children. + /* Add any group transient windows to our children. But if we're transient + for the group, then other group transients are not our children. WARNING: Cyclical transient-ness is possible. For e.g. if: A is transient for the group @@ -1381,7 +1337,9 @@ static void client_update_transient_tree(ObClient *self, C is transient for B A can't be transient for C or we have a cycle */ - if (oldgroup != newgroup && newgroup != NULL && !newgtran && + if (!newgtran && newgroup && + (!newparent || + !client_search_top_direct_parent(newparent)->transient_for_group) && client_normal(self)) { for (it = newgroup->members; it; it = g_slist_next(it)) { @@ -1395,6 +1353,20 @@ static void client_update_transient_tree(ObClient *self, } } } + + /** If we change our group transient-ness, our children change their + effect group transient-ness, which affects how they relate to other + group windows **/ + + for (it = self->transients; it; it = g_slist_next(it)) { + c = it->data; + if (!c->transient_for_group) + client_update_transient_tree(c, c->group, c->group, + c->transient_for_group, + c->transient_for_group, + client_direct_parent(c), + client_direct_parent(c)); + } } static void client_get_mwm_hints(ObClient *self) @@ -3877,6 +3849,96 @@ ObClient *client_search_transient(ObClient *self, ObClient *search) return NULL; } +static void detect_edge(Rect area, ObDirection dir, + gint my_head, gint my_size, + gint my_edge_start, gint my_edge_size, + gint *dest, gboolean *near_edge) +{ + gint edge_start, edge_size, head, tail; + gboolean skip_head = FALSE, skip_tail = FALSE; + + switch(dir) { + case OB_DIRECTION_NORTH: + case OB_DIRECTION_SOUTH: + edge_start = area.x; + edge_size = area.width; + break; + case OB_DIRECTION_EAST: + case OB_DIRECTION_WEST: + edge_start = area.y; + edge_size = area.height; + break; + default: + g_assert_not_reached(); + } + + /* do we collide with this window? */ + if (!RANGES_INTERSECT(my_edge_start, my_edge_size, + edge_start, edge_size)) + return; + + switch(dir) { + case OB_DIRECTION_NORTH: + head = RECT_BOTTOM(area); + tail = RECT_TOP(area); + break; + case OB_DIRECTION_SOUTH: + head = RECT_TOP(area); + tail = RECT_BOTTOM(area); + break; + case OB_DIRECTION_EAST: + head = RECT_LEFT(area); + tail = RECT_RIGHT(area); + break; + case OB_DIRECTION_WEST: + head = RECT_RIGHT(area); + tail = RECT_LEFT(area); + break; + default: + g_assert_not_reached(); + } + switch(dir) { + case OB_DIRECTION_NORTH: + case OB_DIRECTION_WEST: + if (my_head <= head + 1) + skip_head = TRUE; + if (my_head + my_size - 1 <= tail) + skip_tail = TRUE; + if (head < *dest) + skip_head = TRUE; + if (tail - my_size < *dest) + skip_tail = TRUE; + break; + case OB_DIRECTION_SOUTH: + case OB_DIRECTION_EAST: + if (my_head >= head - 1) + skip_head = TRUE; + if (my_head - my_size + 1 >= tail) + skip_tail = TRUE; + if (head > *dest) + skip_head = TRUE; + if (tail + my_size > *dest) + skip_tail = TRUE; + break; + default: + g_assert_not_reached(); + } + + ob_debug("my head %d size %d\n", my_head, my_size); + ob_debug("head %d tail %d deest %d\n", head, tail, *dest); + if (!skip_head) { + ob_debug("using near edge %d\n", head); + *dest = head; + *near_edge = TRUE; + } + else if (!skip_tail) { + ob_debug("using far edge %d\n", tail); + *dest = tail; + *near_edge = FALSE; + } + +} + void client_find_edge_directional(ObClient *self, ObDirection dir, gint my_head, gint my_size, gint my_edge_start, gint my_edge_size, @@ -3884,6 +3946,7 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, { GList *it; Rect *a, *mon; + Rect dock_area; gint edge; a = screen_area(self->desktop, SCREEN_AREA_ALL_MONITORS, @@ -3925,8 +3988,6 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, for(it = client_list; it; it = g_list_next(it)) { ObClient *cur = it->data; - gint edge_start, edge_size, head, tail; - gboolean skip_head = FALSE, skip_tail = FALSE; /* skip windows to not bump into */ if (cur == self) @@ -3939,87 +4000,12 @@ void client_find_edge_directional(ObClient *self, ObDirection dir, ob_debug("trying window %s\n", cur->title); - switch(dir) { - case OB_DIRECTION_NORTH: - case OB_DIRECTION_SOUTH: - edge_start = cur->frame->area.x; - edge_size = cur->frame->area.width; - break; - case OB_DIRECTION_EAST: - case OB_DIRECTION_WEST: - edge_start = cur->frame->area.y; - edge_size = cur->frame->area.height; - break; - default: - g_assert_not_reached(); - } - - /* do we collide with this window? */ - if (!RANGES_INTERSECT(my_edge_start, my_edge_size, - edge_start, edge_size)) - continue; - - switch(dir) { - case OB_DIRECTION_NORTH: - head = RECT_BOTTOM(cur->frame->area); - tail = RECT_TOP(cur->frame->area); - break; - case OB_DIRECTION_SOUTH: - head = RECT_TOP(cur->frame->area); - tail = RECT_BOTTOM(cur->frame->area); - break; - case OB_DIRECTION_EAST: - head = RECT_LEFT(cur->frame->area); - tail = RECT_RIGHT(cur->frame->area); - break; - case OB_DIRECTION_WEST: - head = RECT_RIGHT(cur->frame->area); - tail = RECT_LEFT(cur->frame->area); - break; - default: - g_assert_not_reached(); - } - - switch(dir) { - case OB_DIRECTION_NORTH: - case OB_DIRECTION_WEST: - if (my_head <= head + 1) - skip_head = TRUE; - if (my_head + my_size - 1 <= tail + 1) - skip_tail = TRUE; - if (head < *dest) - skip_head = TRUE; - if (tail - my_size < *dest) - skip_tail = TRUE; - break; - case OB_DIRECTION_SOUTH: - case OB_DIRECTION_EAST: - if (my_head >= head - 1) - skip_head = TRUE; - if (my_head - my_size + 1 >= tail - 1) - skip_tail = TRUE; - if (head > *dest) - skip_head = TRUE; - if (tail + my_size > *dest) - skip_tail = TRUE; - break; - default: - g_assert_not_reached(); - } - - ob_debug("my head %d size %d\n", my_head, my_size); - ob_debug("head %d tail %d deest %d\n", head, tail, *dest); - if (!skip_head) { - ob_debug("using near edge %d\n", head); - *dest = head; - *near_edge = TRUE; - } - else if (!skip_tail) { - ob_debug("using far edge %d\n", tail); - *dest = tail; - *near_edge = FALSE; - } + detect_edge(cur->frame->area, dir, my_head, my_size, my_edge_start, + my_edge_size, dest, near_edge); } + dock_get_area(&dock_area); + detect_edge(dock_area, dir, my_head, my_size, my_edge_start, + my_edge_size, dest, near_edge); } void client_find_move_directional(ObClient *self, ObDirection dir, @@ -4093,36 +4079,36 @@ void client_find_resize_directional(ObClient *self, ObDirection side, gboolean grow, gint *x, gint *y, gint *w, gint *h) { - gint head, size; + gint head; gint e, e_start, e_size, delta; gboolean near; ObDirection dir; switch (side) { case OB_DIRECTION_EAST: - head = RECT_RIGHT(self->frame->area) + (self->size_inc.width - 1); - size = self->frame->area.width; + head = RECT_RIGHT(self->frame->area) + + (self->size_inc.width - 1) * (grow ? 1 : -1); e_start = RECT_TOP(self->frame->area); e_size = self->frame->area.height; dir = grow ? OB_DIRECTION_EAST : OB_DIRECTION_WEST; break; case OB_DIRECTION_WEST: - head = RECT_LEFT(self->frame->area) - (self->size_inc.width - 1); - size = self->frame->area.width; + head = RECT_LEFT(self->frame->area) - + (self->size_inc.width - 1) * (grow ? 1 : -1); e_start = RECT_TOP(self->frame->area); e_size = self->frame->area.height; dir = grow ? OB_DIRECTION_WEST : OB_DIRECTION_EAST; break; case OB_DIRECTION_NORTH: - head = RECT_TOP(self->frame->area) - (self->size_inc.height - 1); - size = self->frame->area.height; + head = RECT_TOP(self->frame->area) - + (self->size_inc.height - 1) * (grow ? 1 : -1); e_start = RECT_LEFT(self->frame->area); e_size = self->frame->area.width; dir = grow ? OB_DIRECTION_NORTH : OB_DIRECTION_SOUTH; break; case OB_DIRECTION_SOUTH: - head = RECT_BOTTOM(self->frame->area) + (self->size_inc.height - 1); - size = self->frame->area.height; + head = RECT_BOTTOM(self->frame->area) + + (self->size_inc.height - 1) * (grow ? 1 : -1); e_start = RECT_LEFT(self->frame->area); e_size = self->frame->area.width; dir = grow ? OB_DIRECTION_SOUTH : OB_DIRECTION_NORTH; @@ -4131,32 +4117,34 @@ void client_find_resize_directional(ObClient *self, ObDirection side, g_assert_not_reached(); } - client_find_edge_directional(self, dir, head, size, + ob_debug("head %d dir %d\n", head, dir); + client_find_edge_directional(self, dir, head, 1, e_start, e_size, &e, &near); + ob_debug("edge %d\n", e); *x = self->frame->area.x; *y = self->frame->area.y; *w = self->frame->area.width; *h = self->frame->area.height; switch (side) { case OB_DIRECTION_EAST: - if (near) --e; + if (grow == near) --e; delta = e - RECT_RIGHT(self->frame->area); *w += delta; break; case OB_DIRECTION_WEST: - if (near) ++e; + if (grow == near) ++e; delta = RECT_LEFT(self->frame->area) - e; *x -= delta; *w += delta; break; case OB_DIRECTION_NORTH: - if (near) ++e; + if (grow == near) ++e; delta = RECT_TOP(self->frame->area) - e; *y -= delta; *h += delta; break; case OB_DIRECTION_SOUTH: - if (near) --e; + if (grow == near) --e; delta = e - RECT_BOTTOM(self->frame->area); *h += delta; break; @@ -4201,30 +4189,3 @@ gboolean client_has_group_siblings(ObClient *self) { return self->group && self->group->members->next; } - -ObClientIcon *client_thumbnail(ObClient *self, gint wantw, gint wanth) -{ - ObClientIcon *ret; - RrPixel32 *data; - gint w, h; - - if (!self->frame->pixmap) return NULL; - if (!RrPixmapToRGBA(ob_rr_inst, self->frame->pixmap, None, &w, &h, &data)) - return NULL; - - /* resize the thumbnail (within aspect ratio) to the given sizes */ - - ret = g_new(ObClientIcon, 1); - ret->data = data; - ret->width = w; - ret->height = h; - return ret; -} - -void clienticon_free(ObClientIcon *ci) -{ - if (ci) { - g_free(ci->data); - g_free(ci); - } -}