+ /* do this after we have a frame.. it uses the frame to help determine the
+ WM_STATE to apply. */
+ client_change_state(self);
+
+ /* add ourselves to the focus order */
+ focus_order_add_new(self);
+
+ /* do this to add ourselves to the stacking list in a non-intrusive way */
+ client_calc_layer(self);
+
+ /* focus the new window? */
+ if (ob_state() != OB_STATE_STARTING &&
+ (!self->session || self->session->focused) &&
+ !self->iconic &&
+ /* this means focus=true for window is same as config_focus_new=true */
+ ((config_focus_new || (settings && settings->focus == 1)) ||
+ client_search_focus_parent(self)) &&
+ /* this checks for focus=false for the window */
+ (!settings || settings->focus != 0) &&
+ /* note the check against Type_Normal/Dialog, not client_normal(self),
+ which would also include other types. in this case we want more
+ strict rules for focus */
+ (self->type == OB_CLIENT_TYPE_NORMAL ||
+ self->type == OB_CLIENT_TYPE_DIALOG))
+ {
+ activate = TRUE;
+ }
+
+ /* adjust the frame to the client's size before showing or placing
+ the window */
+ frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+ frame_adjust_client_area(self->frame);
+
+ /* where the frame was placed is where the window was originally */
+ placex = self->area.x;
+ placey = self->area.y;
+
+ /* figure out placement for the window if the window is new */
+ if (ob_state() == OB_STATE_RUNNING) {
+ gboolean transient;
+
+ ob_debug("Positioned: %s @ %d %d\n",
+ (!self->positioned ? "no" :
+ (self->positioned == PPosition ? "program specified" :
+ (self->positioned == USPosition ? "user specified" :
+ "BADNESS !?"))), self->area.x, self->area.y);
+
+ transient = place_client(self, &placex, &placey, settings);
+
+ /* if the window isn't user-positioned, then make it fit inside
+ the visible screen area on its monitor.
+
+ the monitor is chosen by place_client! */
+ if (!(self->positioned & USPosition)) {
+ /* make a copy to modify */
+ Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
+
+ /* shrink by the frame's area */
+ a.width -= self->frame->size.left + self->frame->size.right;
+ a.height -= self->frame->size.top + self->frame->size.bottom;
+
+ /* fit the window inside the area */
+ self->area.width = MIN(self->area.width, a.width);
+ self->area.height = MIN(self->area.height, a.height);
+
+ ob_debug("setting window size to %dx%d\n",
+ self->area.width, self->area.height);
+
+ /* adjust the frame to the client's new size */
+ frame_adjust_area(self->frame, FALSE, TRUE, FALSE);
+ frame_adjust_client_area(self->frame);
+ }
+
+ /* make sure the window is visible. */
+ client_find_onscreen(self, &placex, &placey,
+ self->area.width, self->area.height,
+ /* non-normal clients has less rules, and
+ windows that are being restored from a
+ session do also. we can assume you want
+ it back where you saved it. Clients saying
+ they placed themselves are subjected to
+ harder rules, ones that are placed by
+ place.c or by the user are allowed partially
+ off-screen and on xinerama divides (ie,
+ it is up to the placement routines to avoid
+ the xinerama divides) */
+ transient ||
+ (((self->positioned & PPosition) &&
+ !(self->positioned & USPosition)) &&
+ client_normal(self) &&
+ !self->session));
+ }
+
+ ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
+ self->window, placex, placey,
+ self->area.width, self->area.height);
+ if (self->session)
+ ob_debug(" but session requested %d %d instead, overriding\n",
+ self->session->x, self->session->y);
+
+ /* do this after the window is placed, so the premax/prefullscreen numbers
+ won't be all wacko!!
+ also, this moves the window to the position where it has been placed
+ */
+ client_apply_startup_state(self);
+
+ /* move the client to its placed position, or it it's already there,
+ generate a ConfigureNotify telling the client where it is.
+
+ do this after adjusting the frame. otherwise it gets all weird and
+ clients don't work right
+
+ also do this after applying the startup state so maximize and fullscreen
+ will get the right sizes and positions if the client is starting with
+ those states
+ */
+ client_configure(self, placex, placey,
+ self->area.width, self->area.height,
+ FALSE, TRUE);
+
+
+ if (activate) {
+ guint32 last_time = focus_client ?
+ focus_client->user_time : CurrentTime;
+
+ /* This is focus stealing prevention */
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Want to focus new window 0x%x with time %u "
+ "(last time %u)\n",
+ self->window, self->user_time, last_time);
+
+ /* if it's on another desktop */
+ if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
+ && /* the timestamp is from before you changed desktops */
+ self->user_time && screen_desktop_user_time &&
+ !event_time_after(self->user_time, screen_desktop_user_time))
+ {
+ activate = FALSE;
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Not focusing the window because its on another "
+ "desktop\n");
+ }
+ /* If something is focused, and it's not our parent... */
+ else if (focus_client && client_search_focus_parent(self) == NULL)
+ {
+ /* If time stamp is old, don't steal focus */
+ if (self->user_time && last_time &&
+ !event_time_after(self->user_time, last_time))
+ {
+ activate = FALSE;
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Not focusing the window because the time is "
+ "too old\n");
+ }
+ /* If its a transient (and parents aren't focused) and the time
+ is ambiguous (either the current focus target doesn't have
+ a timestamp, or they are the same (we probably inherited it
+ from them) */
+ else if (self->transient_for != NULL &&
+ (!last_time || self->user_time == last_time))
+ {
+ activate = FALSE;
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Not focusing the window because it is a "
+ "transient, and the time is very ambiguous\n");
+ }
+ /* Don't steal focus from globally active clients.
+ I stole this idea from KWin. It seems nice.
+ */
+ else if (!(focus_client->can_focus ||
+ focus_client->focus_notify))
+ {
+ activate = FALSE;
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Not focusing the window because a globally "
+ "active client has focus\n");
+ }
+ }
+
+ if (!activate) {
+ ob_debug_type(OB_DEBUG_FOCUS,
+ "Focus stealing prevention activated for %s with "
+ "time %u (last time %u)\n",
+ self->title, self->user_time, last_time);
+ /* if the client isn't focused, then hilite it so the user
+ knows it is there */
+ client_hilite(self, TRUE);
+ }
+ }
+ else {
+ /* This may look rather odd. Well it's because new windows are added
+ to the stacking order non-intrusively. If we're not going to focus
+ the new window or hilite it, then we raise it to the top. This will
+ take affect for things that don't get focused like splash screens.
+ Also if you don't have focus_new enabled, then it's going to get
+ raised to the top. Legacy begets legacy I guess?
+ */
+ if (!client_restore_session_stacking(self))
+ stacking_raise(CLIENT_AS_WINDOW(self));