X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=e1c5604248442d2d8177ce6e800cb0bebd97dcb4;hb=d6cb5adbeaf0b7fbb55aca942ae5b8f62f77b4ea;hp=8efed96abe5ef532bb6f6dca915311e8e4aa8a42;hpb=a18c1697b1176c26e74267f2ac7a153a2cf2c442;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 8efed96a..e1c56042 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -14,6 +14,7 @@ #include "openbox.h" #include "group.h" #include "config.h" +#include "menu.h" #include "render/render.h" #include @@ -311,6 +312,13 @@ 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 (((Menu *)value)->client == (Client *)self) + menu_hide((Menu *)value); +} + void client_unmanage(Client *self) { int j; @@ -364,6 +372,10 @@ void client_unmanage(Client *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); + + if (focus_client == self) { XEvent e; @@ -2205,7 +2217,7 @@ void client_set_state(Client *self, Atom action, long data1, long data2) if (shaded != self->shaded) client_shade(self, shaded); client_calc_layer(self); - client_change_state(self); /* change the hint to relect these changes */ + client_change_state(self); /* change the hint to reflect these changes */ } Client *client_focus_target(Client *self) @@ -2344,3 +2356,98 @@ Icon *client_icon(Client *self, int w, int h) return &self->icons[si]; return &self->icons[li]; } + +/* this be mostly ripped from fvwm */ +Client *client_find_directional(Client *c, Direction dir) +{ + int my_cx, my_cy, his_cx, his_cy; + int offset = 0; + int distance = 0; + int score, best_score; + Client *best_client, *cur; + GList *it; + + if(!client_list) + return NULL; + + /* first, find the centre coords of the currently focused window */ + my_cx = c->frame->area.x + c->frame->area.width / 2; + my_cy = c->frame->area.y + c->frame->area.height / 2; + + best_score = -1; + best_client = NULL; + + for(it = g_list_first(client_list); it; it = it->next) { + cur = it->data; + + /* the currently selected window isn't interesting */ + if(cur == c) + continue; + if (!client_normal(cur)) + continue; + if(c->desktop != cur->desktop && cur->desktop != DESKTOP_ALL) + continue; + if(cur->iconic) + continue; + if(client_focus_target(cur) == cur && + !(cur->can_focus || cur->focus_notify)) + continue; + + /* find the centre coords of this window, from the + * currently focused window's point of view */ + his_cx = (cur->frame->area.x - my_cx) + + cur->frame->area.width / 2; + his_cy = (cur->frame->area.y - my_cy) + + cur->frame->area.height / 2; + + if(dir > 3) { + int tx; + /* Rotate the diagonals 45 degrees counterclockwise. + * To do this, multiply the matrix /+h +h\ with the + * vector (x y). \-h +h/ + * h = sqrt(0.5). We can set h := 1 since absolute + * distance doesn't matter here. */ + tx = his_cx + his_cy; + his_cy = -his_cx + his_cy; + his_cx = tx; + } + + switch(dir) { + case Direction_North : + case Direction_South : + case Direction_NorthEast : + case Direction_SouthWest : + offset = (his_cx < 0) ? -his_cx : his_cx; + distance = (dir == Direction_North || dir == Direction_NorthEast) ? + -his_cy : his_cy; + break; + case Direction_East : + case Direction_West : + case Direction_SouthEast : + case Direction_NorthWest : + offset = (his_cy < 0) ? -his_cy : his_cy; + distance = (dir == Direction_West || dir == Direction_NorthWest) ? + -his_cx : his_cx; + break; + } + + /* the target must be in the requested direction */ + if(distance <= 0) + continue; + + /* Calculate score for this window. The smaller the better. */ + score = distance + offset; + + /* windows more than 45 degrees off the direction are + * heavily penalized and will only be chosen if nothing + * else within a million pixels */ + if(offset > distance) + score += 1000000; + + if(best_score == -1 || score < best_score) + best_client = cur, + best_score = score; + } + + return best_client; +}