X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=7f4cba2129003c14b2908bfbf798c29b5d575104;hb=64dda2375e4d01ca2e81638c1e9595cb73654883;hp=f1be6fa4b2d2f2888e4519c80eeb150e1b16f7b6;hpb=c4732aeed20bc04a1e396a49003c85faccfb4cad;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index f1be6fa4..7f4cba21 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -220,13 +220,14 @@ void client_manage(Window window) grab_server(TRUE); - /* check if it has already been unmapped by the time we started mapping + /* check if it has already been unmapped by the time we started mapping. the grab does a sync so we don't have to here */ if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) || XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e)) { XPutBackEvent(ob_display, &e); + ob_debug("Trying to manage unmapped window. Aborting that.\n"); grab_server(FALSE); return; /* don't manage it */ } @@ -271,13 +272,14 @@ void client_manage(Window window) self->wmstate = WithdrawnState; /* make sure it gets updated first time */ self->layer = -1; self->desktop = screen_num_desktops; /* always an invalid value */ - self->user_time = ~0; /* maximum value, always newer than the real time */ + self->user_time = client_last_user_time; client_get_all(self); - client_restore_session_state(self); /* per-app settings override stuff, and return the settings for other uses too */ settings = client_get_settings_state(self); + /* the session should get the last say */ + client_restore_session_state(self); client_calc_layer(self); @@ -393,6 +395,8 @@ void client_manage(Window window) won't be all wacko!! also, this moves the window to the position where it has been placed */ + ob_debug("placing window 0x%x at %d, %d with size %d x %d\n", + self->window, newx, newy, self->area.width, self->area.height); client_apply_startup_state(self, newx, newy); keyboard_grab_for_client(self, TRUE); @@ -411,8 +415,11 @@ void client_manage(Window window) else { /* If time stamp is old, don't steal focus */ - if (self->user_time && self->user_time < client_last_user_time) + if (self->user_time && + !event_time_after(self->user_time, client_last_user_time)) + { activate = FALSE; + } /* Don't steal focus from globally active clients. I stole this idea from KWin. It seems nice. */ @@ -449,7 +456,7 @@ void client_manage(Window window) /* this has to happen before we try focus the window, but we want it to happen after the client's stacking has been determined or it looks bad */ - client_showhide(self); + client_show(self); /* use client_focus instead of client_activate cuz client_activate does stuff like switch desktops etc and I'm not interested in all that when @@ -570,34 +577,36 @@ void client_unmanage(ObClient *self) self->group = NULL; } - /* give the client its border back */ - client_toggle_border(self, TRUE); + /* restore the window's original geometry so it is not lost */ + { + Rect a = self->area; + + if (self->fullscreen) + a = self->pre_fullscreen_area; + else if (self->max_horz || self->max_vert) { + if (self->max_horz) { + a.x = self->pre_max_area.x; + a.width = self->pre_max_area.width; + } + if (self->max_vert) { + a.y = self->pre_max_area.y; + a.height = self->pre_max_area.height; + } + } + + /* give the client its border back */ + client_toggle_border(self, TRUE); + + self->fullscreen = self->max_horz = self->max_vert = FALSE; + self->decorations = 0; /* unmanaged windows have no decor */ + + client_move_resize(self, a.x, a.y, a.width, a.height); + } /* reparent the window out of the frame, and free the frame */ frame_release_client(self->frame, self); self->frame = NULL; - /* restore the window's original geometry so it is not lost */ - if (self->fullscreen) - XMoveResizeWindow(ob_display, self->window, - self->pre_fullscreen_area.x, - self->pre_fullscreen_area.y, - self->pre_fullscreen_area.width, - self->pre_fullscreen_area.height); - else if (self->max_horz || self->max_vert) { - Rect a = self->area; - if (self->max_horz) { - a.x = self->pre_max_area.x; - a.width = self->pre_max_area.width; - } - if (self->max_vert) { - a.y = self->pre_max_area.y; - a.height = self->pre_max_area.height; - } - XMoveResizeWindow(ob_display, self->window, - a.x, a.y, a.width, a.height); - } - if (ob_state() != OB_STATE_EXITING) { /* these values should not be persisted across a window unmapping/mapping */ @@ -610,7 +619,6 @@ void client_unmanage(ObClient *self) XMapWindow(ob_display, self->window); } - ob_debug("Unmanaged window 0x%lx\n", self->window); /* free all data allocated in the client struct */ @@ -683,7 +691,7 @@ static ObAppSettings *client_get_settings_state(ObClient *self) if (settings->desktop < screen_num_desktops || settings->desktop == DESKTOP_ALL) - client_set_desktop(self, settings->desktop, TRUE); + self->desktop = settings->desktop; if (settings->layer == -1) { self->below = TRUE; @@ -887,10 +895,9 @@ static void client_toggle_border(ObClient *self, gboolean show) if (show) { XSetWindowBorderWidth(ob_display, self->window, self->border_width); - /* move the client so it is back it the right spot _with_ its - border! */ - if (x != oldx || y != oldy) - XMoveWindow(ob_display, self->window, x, y); + /* set border_width to 0 because there is no border to add into + calculations anymore */ + self->border_width = 0; } else XSetWindowBorderWidth(ob_display, self->window, 0); } @@ -962,6 +969,7 @@ static void client_get_area(ObClient *self) g_assert(ret != BadWindow); RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height); + POINT_SET(self->root_pos, wattrib.x, wattrib.y); self->border_width = wattrib.border_width; ob_debug("client area: %d %d %d %d\n", wattrib.x, wattrib.y, @@ -2052,6 +2060,33 @@ gboolean client_should_show(ObClient *self) return FALSE; } +void client_show(ObClient *self) +{ + + if (client_should_show(self)) { + frame_show(self->frame); + } + + /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it + needs to be in IconicState. This includes when it is on another + desktop! + */ + client_change_wm_state(self); +} + +void client_hide(ObClient *self) +{ + if (!client_should_show(self)) { + frame_hide(self->frame); + } + + /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it + needs to be in IconicState. This includes when it is on another + desktop! + */ + client_change_wm_state(self); +} + void client_showhide(ObClient *self) { @@ -2060,10 +2095,6 @@ void client_showhide(ObClient *self) } else { frame_hide(self->frame); - - /* Fall back focus since we're disappearing */ - if (focus_client == self) - client_unfocus(self); } /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it @@ -2128,8 +2159,12 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y) pos = TRUE; } - /* if the client didn't get positioned yet, then do so now */ - if (!pos && (ox != x || oy != y)) { + /* if the client didn't get positioned yet, then do so now + call client_move even if the window is not being moved anywhere, because + when we reparent it and decorate it, it is getting moved and we need to + be telling it so with a ConfigureNotify event. + */ + if (!pos) { /* use the saved position */ self->area.x = ox; self->area.y = oy; @@ -2157,58 +2192,7 @@ void client_try_configure(ObClient *self, ObCorner anchor, the updated frame dimensions. */ frame_adjust_area(self->frame, TRUE, TRUE, TRUE); - /* gets the frame's position */ - frame_client_gravity(self->frame, x, y); - - /* these positions are frame positions, not client positions */ - - /* set the size and position if fullscreen */ - if (self->fullscreen) { - Rect *a; - guint i; - - i = screen_find_monitor(&desired_area); - a = screen_physical_area_monitor(i); - - *x = a->x; - *y = a->y; - *w = a->width; - *h = a->height; - - user = FALSE; /* ignore that increment etc shit when in fullscreen */ - } else { - Rect *a; - guint i; - - i = screen_find_monitor(&desired_area); - a = screen_area_monitor(self->desktop, i); - - /* set the size and position if maximized */ - if (self->max_horz) { - *x = a->x; - *w = a->width - self->frame->size.left - self->frame->size.right; - } - if (self->max_vert) { - *y = a->y; - *h = a->height - self->frame->size.top - self->frame->size.bottom; - } - } - - /* gets the client's position */ - frame_frame_gravity(self->frame, x, y); - - /* these override the above states! if you cant move you can't move! */ - if (user) { - if (!(self->functions & OB_CLIENT_FUNC_MOVE)) { - *x = self->area.x; - *y = self->area.y; - } - if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) { - *w = self->area.width; - *h = self->area.height; - } - } - + /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { gint basew, baseh, minw, minh; @@ -2291,6 +2275,62 @@ void client_try_configure(ObClient *self, ObCorner anchor, *h += self->base_size.height; } + /* gets the frame's position */ + frame_client_gravity(self->frame, x, y); + + /* these positions are frame positions, not client positions */ + + /* set the size and position if fullscreen */ + if (self->fullscreen) { + Rect *a; + guint i; + + i = screen_find_monitor(&desired_area); + a = screen_physical_area_monitor(i); + + *x = a->x; + *y = a->y; + *w = a->width; + *h = a->height; + + user = FALSE; /* ignore if the client can't be moved/resized when it + is entering fullscreen */ + } else if (self->max_horz || self->max_vert) { + Rect *a; + guint i; + + i = screen_find_monitor(&desired_area); + a = screen_area_monitor(self->desktop, i); + + /* set the size and position if maximized */ + if (self->max_horz) { + *x = a->x; + *w = a->width - self->frame->size.left - self->frame->size.right; + } + if (self->max_vert) { + *y = a->y; + *h = a->height - self->frame->size.top - self->frame->size.bottom; + } + + /* maximizing is not allowed if the user can't move+resize the window + */ + } + + /* gets the client's position */ + frame_frame_gravity(self->frame, x, y); + + /* these override the above states! if you cant move you can't move! */ + if (user) { + if (!(self->functions & OB_CLIENT_FUNC_MOVE)) { + *x = self->area.x; + *y = self->area.y; + } + if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) { + *w = self->area.width; + *h = self->area.height; + } + } + g_assert(*w > 0); g_assert(*h > 0); @@ -2316,9 +2356,9 @@ void client_configure_full(ObClient *self, ObCorner anchor, gboolean user, gboolean final, gboolean force_reply) { - gint oldw, oldh; + gint oldw, oldh, oldrx, oldry; gboolean send_resize_client; - gboolean moved = FALSE, resized = FALSE; + gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE; guint fdecor = self->frame->decorations; gboolean fhorz = self->frame->max_horz; gint logicalw, logicalh; @@ -2350,35 +2390,47 @@ void client_configure_full(ObClient *self, ObCorner anchor, if (send_resize_client && user && (w > oldw || h > oldh)) XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh)); - /* move/resize the frame to match the request */ - if (self->frame) { - if (self->decorations != fdecor || self->max_horz != fhorz) - moved = resized = TRUE; - - if (moved || resized) - frame_adjust_area(self->frame, moved, resized, FALSE); - - 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 - - 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; - event.xconfigure.above = self->frame->plate; - event.xconfigure.override_redirect = FALSE; - XSendEvent(event.xconfigure.display, event.xconfigure.window, - FALSE, StructureNotifyMask, &event); - } + /* find the frame's dimensions and move/resize it */ + if (self->decorations != fdecor || self->max_horz != fhorz) + moved = resized = TRUE; + if (moved || resized) + frame_adjust_area(self->frame, moved, resized, FALSE); + + /* find the client's position relative to the root window */ + oldrx = self->root_pos.x; + oldry = self->root_pos.y; + rootmoved = (oldrx != (signed)(self->frame->area.x + + self->frame->size.left - + self->border_width) || + oldry != (signed)(self->frame->area.y + + self->frame->size.top - + self->border_width)); + + if (force_reply || ((!user || (user && final)) && rootmoved)) + { + XEvent event; + + POINT_SET(self->root_pos, + self->frame->area.x + self->frame->size.left - + self->border_width, + self->frame->area.y + self->frame->size.top - + self->border_width); + + 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->root_pos.x; + event.xconfigure.y = self->root_pos.y; + event.xconfigure.width = w; + event.xconfigure.height = h; + event.xconfigure.border_width = 0; + event.xconfigure.above = self->frame->plate; + event.xconfigure.override_redirect = FALSE; + XSendEvent(event.xconfigure.display, event.xconfigure.window, + FALSE, StructureNotifyMask, &event); } /* if the client is shrinking, then resize the frame before the client */ @@ -2957,11 +3009,6 @@ gboolean client_focus(ObClient *self) /* choose the correct target */ self = client_focus_target(self); -#if 0 - if (!client_validate(self)) - return FALSE; -#endif - if (!client_can_focus(self)) { if (!self->frame->visible) { /* update the focus lists */ @@ -3028,9 +3075,11 @@ void client_activate(ObClient *self, gboolean here, gboolean user) "source=%s\n", self->window, event_curtime, client_last_user_time, (user ? "user" : "application")); - if (!user && event_curtime && event_curtime < client_last_user_time) + if (!user && event_curtime && + !event_time_after(event_curtime, client_last_user_time)) + { client_hilite(self, TRUE); - else { + } else { if (client_normal(self) && screen_showing_desktop) screen_show_desktop(FALSE); if (self->iconic)