X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=a1deded5a06fcb790e2a7bdc7d3a4d41ef42cd1d;hb=7120face258ee4bd71fb19ded271665acde6465c;hp=ebff0bae8d6a0156b9da20f2706e6028c6a2f7b9;hpb=853d5f4b70ccc475ae25806a6683406119236b29;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index ebff0bae..a1deded5 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -18,6 +18,8 @@ #include "group.h" #include "config.h" #include "menu.h" +#include "keyboard.h" +#include "mouse.h" #include "render/render.h" #include @@ -302,7 +304,8 @@ void client_manage(Window window) dispatch_client(Event_Client_New, self, 0, 0); /* make sure the window is visible */ - client_move_onscreen(self, TRUE); + if (ob_state() == OB_STATE_RUNNING) + client_move_onscreen(self, TRUE); screen_update_areas(); @@ -327,6 +330,9 @@ void client_manage(Window window) /* update the list hints */ client_set_list(); + keyboard_grab_for_client(self, TRUE); + mouse_grab_for_client(self, TRUE); + dispatch_client(Event_Client_Mapped, self, 0, 0); ob_debug("Managed window 0x%lx (%s)\n", window, self->class); @@ -355,6 +361,9 @@ void client_unmanage(ObClient *self) 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); @@ -1097,7 +1106,7 @@ void client_setup_decor_and_functions(ObClient *self) /* 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)) @@ -1114,14 +1123,8 @@ void client_setup_decor_and_functions(ObClient *self) client_change_allowed_actions(self); if (self->frame) { - if (self->decorations != self->frame->decorations) - /* adjust the client's decorations, etc. */ - client_reconfigure(self); - /* we actually have to do this twice :P - the first time it removes the decorations, but now it may need to - be reconstrained for being maximized etc, so calling this again - will work with the new setup of decorations on the window */ - 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 && @@ -1711,6 +1714,12 @@ void client_configure_full(ObClient *self, ObCorner anchor, gboolean force_reply) { gboolean moved = FALSE, resized = FALSE; + guint fdecor = self->frame->decorations; + + /* 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); @@ -1757,8 +1766,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; @@ -1896,11 +1905,11 @@ void client_configure_full(ObClient *self, ObCorner anchor, /* move/resize the frame to match the request */ if (self->frame) { - if (self->decorations != self->frame->decorations) + if (self->decorations != fdecor) 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)))) { @@ -2170,7 +2179,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) @@ -2524,16 +2533,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; @@ -2616,7 +2628,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 @@ -2744,3 +2757,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; +}