X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=c57c66e84571ec5e4ec90813ffb6e3a150722924;hb=960a7f0184a84f99545fa2d3dd22cefc77f2cbc6;hp=697b6d8a7d86d4a2bf2c287cea2f4d8de48b66f5;hpb=eb1fb5580e6a4c3620dfefdfd5704f9927f82ab1;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 697b6d8a..c57c66e8 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -8,6 +8,7 @@ #include "prop.h" #include "extensions.h" #include "frame.h" +#include "session.h" #include "event.h" #include "grab.h" #include "focus.h" @@ -43,6 +44,7 @@ static void client_showhide(ObClient *self); 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); void client_startup() { @@ -231,7 +233,11 @@ void client_manage(Window window) self = g_new(ObClient, 1); self->obwin.type = Window_Client; self->window = window; + client_get_all(self); + client_restore_session_state(self); + + client_change_state(self); /* remove the client's border (and adjust re gravity) */ client_toggle_border(self, FALSE); @@ -249,10 +255,6 @@ void client_manage(Window window) grab_server(FALSE); - /* add to client list/map */ - client_list = g_list_append(client_list, self); - g_hash_table_insert(window_map, &self->window, self); - /* update the focus lists */ focus_order_add_new(self); @@ -300,7 +302,7 @@ void client_manage(Window window) dispatch_client(Event_Client_New, self, 0, 0); /* make sure the window is visible */ - client_move_onscreen(self); + client_move_onscreen(self, TRUE); screen_update_areas(); @@ -318,6 +320,10 @@ void client_manage(Window window) if (screen_showing_desktop) screen_show_desktop(FALSE); + /* add to client list/map */ + client_list = g_list_append(client_list, self); + g_hash_table_insert(window_map, &self->window, self); + /* update the list hints */ client_set_list(); @@ -425,8 +431,9 @@ void client_unmanage(ObClient *self) if (ob_state() != OB_STATE_EXITING) { /* these values should not be persisted across a window unmapping/mapping */ - prop_erase(self->window, prop_atoms.net_wm_desktop); - prop_erase(self->window, prop_atoms.net_wm_state); + PROP_ERASE(self->window, net_wm_desktop); + PROP_ERASE(self->window, net_wm_state); + PROP_ERASE(self->window, wm_state); } else { /* if we're left in an iconic state, the client wont be mapped. this is bad, since we will no longer be managing the window on restart */ @@ -454,27 +461,89 @@ void client_unmanage(ObClient *self) client_set_list(); } -void client_move_onscreen(ObClient *self) +static void client_restore_session_state(ObClient *self) +{ + ObSessionState *s; + + s = session_state_find(self); + if (!(s)) return; + + RECT_SET(self->area, s->x, s->y, s->w, s->h); + self->positioned = TRUE; + XResizeWindow(ob_display, self->window, s->w, s->h); + + self->desktop = s->desktop == DESKTOP_ALL ? s->desktop : + MIN(screen_num_desktops - 1, s->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; + + session_state_free(s); +} + +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)) { + client_configure(self, OB_CORNER_TOPLEFT, x, y, + self->area.width, self->area.height, + TRUE, TRUE); + } +} + +gboolean client_find_onscreen(ObClient *self, int *x, int *y, int w, int h, + gboolean rude) { Rect *a; - int x = self->frame->area.x, y = self->frame->area.y; + int ox = *x, oy = *y; + + frame_client_gravity(self->frame, x, y); /* get where the frame + would be */ /* XXX watch for xinerama dead areas */ + a = screen_area(self->desktop); - if (x >= a->x + a->width - 1) - x = a->x + a->width - self->frame->area.width; - if (y >= a->y + a->height - 1) - y = a->y + a->height - self->frame->area.height; - if (x + self->frame->area.width - 1 < a->x) - x = a->x; - if (y + self->frame->area.height - 1< a->y) - y = a->y; - - frame_frame_gravity(self->frame, &x, &y); /* get where the client - should be */ - client_configure(self, OB_CORNER_TOPLEFT, x, y, - self->area.width, self->area.height, - TRUE, TRUE); + 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 + a->height - self->frame->area.height; + if (!self->strut.left && *x + self->frame->area.width - 1 < a->x) + *x = a->x; + if (!self->strut.top && *y + self->frame->area.height - 1 < a->y) + *y = a->y; + + if (rude) { + /* this is my MOZILLA BITCHSLAP. oh ya it fucking feels good. + Java can suck it too. */ + + /* dont let windows map/move into the strut unless they + are bigger than the available area */ + if (w <= a->width) { + if (!self->strut.left && *x < a->x) *x = a->x; + if (!self->strut.right && *x + w > a->x + a->width) + *x = a->x + a->width - w; + } + if (h <= a->height) { + if (!self->strut.top && *y < a->y) *y = a->y; + if (!self->strut.bottom && *y + h > a->y + a->height) + *y = a->y + a->height - h; + } + } + + frame_frame_gravity(self->frame, x, y); /* get where the client + should be */ + + return ox != *x || oy != *y; } static void client_toggle_border(ObClient *self, gboolean show) @@ -589,8 +658,6 @@ static void client_get_all(ObClient *self) client_update_class(self); client_update_strut(self); client_update_icons(self); - - client_change_state(self); } static void client_get_area(ObClient *self) @@ -636,7 +703,6 @@ static void client_get_desktop(ObClient *self) if (!trdesk) /* defaults to the current desktop */ self->desktop = screen_desktop; - } if (self->desktop != d) { /* set the desktop hint, to make sure that it always exists */ @@ -891,22 +957,7 @@ void client_update_normal_hints(ObClient *self) /* get the hints from the window */ if (XGetWMNormalHints(ob_display, self->window, &size, &ret)) { - if (size.flags & (PPosition|USPosition)) { - Rect *a; - - /* this is my MOZILLA BITCHSLAP. oh ya it fucking feels good. - Java can suck it too. */ - - /* dont let windows map above/left into the strut unless they - are bigger than the available area */ - a = screen_area(self->desktop); - if (self->area.width <= a->width && self->area.x < a->x) - self->area.x = a->x; - if (self->area.height <= a->height && self->area.y < a->y) - self->area.y = a->y; - - self->positioned = TRUE; - } + self->positioned = !!(size.flags & (PPosition|USPosition)); if (size.flags & PWinGravity) { self->gravity = size.win_gravity; @@ -1191,9 +1242,6 @@ void client_update_wmhints(ObClient *self) } } - /* the WM_HINTS can contain an icon */ - client_update_icons(self); - /* because the self->transient flag wont change from this call, we don't need to update the window's type and such, only its transient_for, and the transients lists of other windows in @@ -1201,6 +1249,9 @@ void client_update_wmhints(ObClient *self) client_update_transient_for(self); } + /* the WM_HINTS can contain an icon */ + client_update_icons(self); + XFree(hints); } @@ -1323,17 +1374,35 @@ void client_update_strut(ObClient *self) { guint num; guint32 *data; + gboolean got = FALSE; + + if (PROP_GETA32(self->window, net_wm_strut_partial, cardinal, + &data, &num)) { + if (num == 12) { + got = TRUE; + STRUT_PARTIAL_SET(self->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]); + } + g_free(data); + } - if (!PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) { - STRUT_SET(self->strut, 0, 0, 0, 0); - } else { - if (num == 4) - STRUT_SET(self->strut, data[0], data[2], data[1], data[3]); - else - STRUT_SET(self->strut, 0, 0, 0, 0); - g_free(data); + if (!got && + PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) { + if (num == 4) { + got = TRUE; + STRUT_PARTIAL_SET(self->strut, + data[0], data[2], data[1], data[3], + 0, 0, 0, 0, 0, 0, 0, 0); + } + g_free(data); } + if (!got) + STRUT_PARTIAL_SET(self->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) @@ -1634,9 +1703,10 @@ static void client_apply_startup_state(ObClient *self) */ } -void client_configure(ObClient *self, ObCorner anchor, - int x, int y, int w, int h, - gboolean user, gboolean final) +void client_configure_full(ObClient *self, ObCorner anchor, + int x, int y, int w, int h, + gboolean user, gboolean final, + gboolean force_reply) { gboolean moved = FALSE, resized = FALSE; @@ -1765,11 +1835,13 @@ void client_configure(ObClient *self, ObCorner anchor, h /= self->size_inc.height; /* you cannot resize to nothing */ - if (w < 1) w = 1; - if (h < 1) h = 1; + if (basew + w < 1) w = 1 - basew; + if (baseh + h < 1) h = 1 - baseh; /* store the logical size */ - SIZE_SET(self->logical_size, w, h); + SIZE_SET(self->logical_size, + self->size_inc.width > 1 ? w : w + basew, + self->size_inc.height > 1 ? h : h + baseh); w *= self->size_inc.width; h *= self->size_inc.height; @@ -1828,21 +1900,19 @@ void client_configure(ObClient *self, ObCorner anchor, if (moved || resized) frame_adjust_area(self->frame, moved, resized); - /* If you send this and the client hasn't changed you end up with buggy - clients (emacs) freaking out, cuz they send back a configure every - time they receive this event, which resends them this event... etc. - */ - if ((!user && moved) || (user && final)) { + if (!resized && (force_reply || ((!user && moved) || (user && final)))) + { XEvent event; event.type = ConfigureNotify; event.xconfigure.display = ob_display; event.xconfigure.event = self->window; event.xconfigure.window = self->window; - + /* root window real coords */ - event.xconfigure.x = self->frame->area.x + self->frame->size.left; - event.xconfigure.y = self->frame->area.y + self->frame->size.top; - + event.xconfigure.x = self->frame->area.x + self->frame->size.left - + self->border_width; + event.xconfigure.y = self->frame->area.y + self->frame->size.top - + self->border_width; event.xconfigure.width = w; event.xconfigure.height = h; event.xconfigure.border_width = 0; @@ -2663,3 +2733,12 @@ ObClient *client_search_transient(ObClient *self, ObClient *search) } return NULL; } + +gchar* client_get_sm_client_id(ObClient *self) +{ + gchar *id = NULL; + + if (!PROP_GETS(self->window, sm_client_id, locale, &id) && self->group) + PROP_GETS(self->group->leader, sm_client_id, locale, &id); + return id; +}