X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=5a6f443ae82d3b157a136067044b74a6357653bd;hb=5074d902aa215a2a656980d31b19574a5db1f795;hp=5c180024277a7d2a08f69595b91e782da47c3efa;hpb=93d9201cbaa2d753a52226687c57161f5a85d7c8;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 5c180024..5a6f443a 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -67,7 +67,6 @@ GList *client_list = NULL; static GSList *client_destroy_notifies = NULL; static void client_get_all(ObClient *self, gboolean real); -static void client_toggle_border(ObClient *self, gboolean show); static void client_get_startup_id(ObClient *self); static void client_get_session_ids(ObClient *self); static void client_get_area(ObClient *self); @@ -79,7 +78,8 @@ static void client_get_colormap(ObClient *self); static void client_change_allowed_actions(ObClient *self); static void client_change_state(ObClient *self); static void client_change_wm_state(ObClient *self); -static void client_apply_startup_state(ObClient *self); +static void client_apply_startup_state(ObClient *self, + gint x, gint y, gint w, gint h); static void client_restore_session_state(ObClient *self); static gboolean client_restore_session_stacking(ObClient *self); static ObAppSettings *client_get_settings_state(ObClient *self); @@ -241,7 +241,8 @@ void client_manage(Window window) XWMHints *wmhint; gboolean activate = FALSE; ObAppSettings *settings; - gint placex, placey; + gint placex, placey, placew, placeh; + gboolean transient = FALSE; grab_server(TRUE); @@ -278,7 +279,7 @@ void client_manage(Window window) XFree(wmhint); } - ob_debug("Managing window: %lx\n", window); + ob_debug("Managing window: 0x%lx\n", window); /* choose the events we want to receive on the CLIENT window */ attrib_set.event_mask = CLIENT_EVENTMASK; @@ -322,11 +323,8 @@ void client_manage(Window window) client_restore_session_state(self); /* now we have all of the window's information so we can set this up */ - client_setup_decor_and_functions(self); + client_setup_decor_and_functions(self, FALSE); - /* remove the client's border (and adjust re gravity) */ - client_toggle_border(self, FALSE); - { Time t = sn_app_started(self->startup_id, self->class); if (t) self->user_time = t; @@ -348,18 +346,22 @@ void client_manage(Window window) !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)) && + client_search_focus_tree_full(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 */ + /* note the check against type Normal/Dialog/Utility, + 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_UTILITY || self->type == OB_CLIENT_TYPE_DIALOG)) { activate = TRUE; } + /* remove the client's border */ + XSetWindowBorderWidth(ob_display, self->window, 0); + /* adjust the frame to the client's size before showing or placing the window */ frame_adjust_area(self->frame, FALSE, TRUE, FALSE); @@ -368,22 +370,33 @@ void client_manage(Window window) /* where the frame was placed is where the window was originally */ placex = self->area.x; placey = self->area.y; + placew = self->area.width; + placeh = self->area.height; - /* figure out placement for the window */ + /* 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); - + (self->positioned == (PPosition | USPosition) ? + "program + user specified" : + "BADNESS !?")))), placex, placey); + + ob_debug("Sized: %s @ %d %d\n", + (!self->sized ? "no" : + (self->sized == PSize ? "program specified" : + (self->sized == USSize ? "user specified" : + (self->sized == (PSize | USSize) ? + "program + user specified" : + "BADNESS !?")))), placew, placeh); + + /* splash screens are also returned as TRUE for transient, + and so will be forced on screen below */ transient = place_client(self, &placex, &placey, settings); /* make sure the window is visible. */ - client_find_onscreen(self, &placex, &placey, - self->area.width, self->area.height, + client_find_onscreen(self, &placex, &placey, placew, placeh, /* non-normal clients has less rules, and windows that are being restored from a session do also. we can assume you want @@ -393,42 +406,65 @@ void client_manage(Window window) 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) */ + the xinerama divides) + + splash screens get "transient" set to TRUE by + the place_client call + */ transient || - (((self->positioned & PPosition) && - !(self->positioned & USPosition)) && + (!(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); + /* if the window isn't user-sized, then make it fit inside + the visible screen area on its monitor. Use basically the same rules + for forcing the window on screen in the client_find_onscreen call. - /* 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 + do this after place_client, it chooses the monitor! + + splash screens get "transient" set to TRUE by + the place_client call */ - client_apply_startup_state(self); + if (transient || + (!(self->sized & USSize) && + client_normal(self) && + !self->session)) + { + /* make a copy to modify */ + Rect a = *screen_area_monitor(self->desktop, client_monitor(self)); - /* move the client to its placed position, or it it's already there, - generate a ConfigureNotify telling the client where it is. + /* 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; - do this after adjusting the frame. otherwise it gets all weird and - clients don't work right + /* fit the window inside the area */ + if (placew > a.width || self->area.height > a.height) { + placew = MIN(self->area.width, a.width); + placeh = MIN(self->area.height, a.height); - 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); + ob_debug("setting window size to %dx%d\n", + self->area.width, self->area.height); + } + } + ob_debug("placing window 0x%x at %d, %d with size %d x %d. " + "some restrictions may apply\n", + self->window, placex, placey, placew, placeh); + if (self->session) + ob_debug(" but session requested %d, %d %d x %d instead, " + "overriding\n", + self->session->x, self->session->y, + self->session->w, self->session->h); + + /* do this after the window is placed, so the premax/prefullscreen numbers + won't be all wacko!! + + this also places the window + */ + client_apply_startup_state(self, placex, placey, placew, placeh); + if (activate) { guint32 last_time = focus_client ? focus_client->user_time : CurrentTime; @@ -450,8 +486,8 @@ void client_manage(Window window) "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 something is focused, and it's not our relative... */ + else if (focus_client && client_search_focus_tree_full(self) == NULL) { /* If time stamp is old, don't steal focus */ if (self->user_time && last_time && @@ -462,15 +498,37 @@ void client_manage(Window window) "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 (client_has_parent(self) && + (!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. */ - if (!(focus_client->can_focus || focus_client->focus_notify)) { + 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"); } + /* Don't move focus if it's not going to go to this window + anyway */ + else if (client_focus_target(self) != self) { + activate = FALSE; + ob_debug_type(OB_DEBUG_FOCUS, + "Not focusing the window because another window " + "would get the focus anyway\n"); + } } if (!activate) { @@ -522,7 +580,7 @@ void client_manage(Window window) g_free(settings); ob_debug("Managed window 0x%lx plate 0x%x (%s)\n", - window, self->frame->plate, self->class); + window, self->frame->window, self->class); return; } @@ -545,12 +603,16 @@ ObClient *client_fake_manage(Window window) uses too. this returns a shallow copy that needs to be freed */ settings = client_get_settings_state(self); - client_setup_decor_and_functions(self); + client_setup_decor_and_functions(self, FALSE); /* create the decoration frame for the client window and adjust its size */ self->frame = frame_new(self); frame_adjust_area(self->frame, FALSE, TRUE, TRUE); + ob_debug("gave extents left %d right %d top %d bottom %d\n", + self->frame->size.left, self->frame->size.right, + self->frame->size.top, self->frame->size.bottom); + /* free the ObAppSettings shallow copy */ g_free(settings); @@ -569,7 +631,7 @@ void client_unmanage(ObClient *self) GSList *it; ob_debug("Unmanaging window: 0x%x plate 0x%x (%s) (%s)\n", - self->window, self->frame->plate, + self->window, self->frame->window, self->class, self->title ? self->title : ""); g_assert(self != NULL); @@ -641,9 +703,6 @@ void client_unmanage(ObClient *self) { Rect a; - /* give the client its border back */ - client_toggle_border(self, TRUE); - a = self->area; if (self->fullscreen) @@ -664,6 +723,9 @@ void client_unmanage(ObClient *self) self->functions = OB_CLIENT_FUNC_MOVE | OB_CLIENT_FUNC_RESIZE; self->decorations = 0; /* unmanaged windows have no decor */ + /* give the client its border back */ + XSetWindowBorderWidth(ob_display, self->window, self->border_width); + client_move_resize(self, a.x, a.y, a.width, a.height); } @@ -815,6 +877,7 @@ static void client_restore_session_state(ObClient *self) RECT_SET_POINT(self->area, self->session->x, self->session->y); self->positioned = USPosition; + self->sized = USSize; if (self->session->w > 0) self->area.width = self->session->w; if (self->session->h > 0) @@ -976,71 +1039,6 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, return ox != *x || oy != *y; } -static void client_toggle_border(ObClient *self, gboolean show) -{ - /* adjust our idea of where the client is, based on its border. When the - border is removed, the client should now be considered to be in a - different position. - when re-adding the border to the client, the same operation needs to be - reversed. */ - gint oldx = self->area.x, oldy = self->area.y; - gint x = oldx, y = oldy; - switch(self->gravity) { - default: - case NorthWestGravity: - case WestGravity: - case SouthWestGravity: - break; - case NorthEastGravity: - case EastGravity: - case SouthEastGravity: - if (show) x -= self->border_width * 2; - else x += self->border_width * 2; - break; - case NorthGravity: - case SouthGravity: - case CenterGravity: - case ForgetGravity: - case StaticGravity: - if (show) x -= self->border_width; - else x += self->border_width; - break; - } - switch(self->gravity) { - default: - case NorthWestGravity: - case NorthGravity: - case NorthEastGravity: - break; - case SouthWestGravity: - case SouthGravity: - case SouthEastGravity: - if (show) y -= self->border_width * 2; - else y += self->border_width * 2; - break; - case WestGravity: - case EastGravity: - case CenterGravity: - case ForgetGravity: - case StaticGravity: - if (show) y -= self->border_width; - else y += self->border_width; - break; - } - self->area.x = x; - self->area.y = y; - - if (show) { - XSetWindowBorderWidth(ob_display, self->window, self->border_width); - - /* 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); -} - - static void client_get_all(ObClient *self, gboolean real) { /* this is needed for the frame to set itself up */ @@ -1118,8 +1116,8 @@ static void client_get_area(ObClient *self) 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, - wattrib.width, wattrib.height); + ob_debug("client area: %d %d %d %d bw %d\n", wattrib.x, wattrib.y, + wattrib.width, wattrib.height, wattrib.border_width); } static void client_get_desktop(ObClient *self) @@ -1131,23 +1129,38 @@ static void client_get_desktop(ObClient *self) self->desktop = screen_num_desktops - 1; else self->desktop = d; + ob_debug("client requested desktop 0x%x\n", self->desktop); } else { gboolean trdesk = FALSE; if (self->transient_for) { if (self->transient_for != OB_TRAN_GROUP) { - self->desktop = self->transient_for->desktop; - trdesk = TRUE; + if (self->transient_for->desktop != DESKTOP_ALL) { + self->desktop = self->transient_for->desktop; + trdesk = TRUE; + } } else { + /* if all the group is on one desktop, then open it on the + same desktop */ GSList *it; + gboolean first = TRUE; + guint all = screen_num_desktops; /* not a valid value */ - for (it = self->group->members; it; it = g_slist_next(it)) - if (it->data != self && - !((ObClient*)it->data)->transient_for) { - self->desktop = ((ObClient*)it->data)->desktop; - trdesk = TRUE; - break; + for (it = self->group->members; it; it = g_slist_next(it)) { + ObClient *c = it->data; + if (c != self) { + if (first) { + all = c->desktop; + first = FALSE; + } + else if (all != c->desktop) + all = screen_num_desktops; /* make it invalid */ } + } + if (all != screen_num_desktops) { + self->desktop = all; + trdesk = TRUE; + } } } if (!trdesk) { @@ -1531,7 +1544,16 @@ void client_get_colormap(ObClient *self) void client_update_colormap(ObClient *self, Colormap colormap) { - self->colormap = colormap; + if (colormap == self->colormap) return; + + ob_debug("Setting client %s colormap: 0x%x\n", self->title, colormap); + + if (client_focused(self)) { + screen_install_colormap(self, FALSE); /* uninstall old one */ + self->colormap = colormap; + screen_install_colormap(self, FALSE); /* install new one */ + } else + self->colormap = colormap; } void client_update_normal_hints(ObClient *self) @@ -1553,6 +1575,7 @@ void client_update_normal_hints(ObClient *self) if (!client_normal(self)) */ self->positioned = (size.flags & (PPosition|USPosition)); + self->sized = (size.flags & (PSize|USSize)); if (size.flags & PWinGravity) self->gravity = size.win_gravity; @@ -1580,9 +1603,7 @@ void client_update_normal_hints(ObClient *self) } } -/*! This needs to be followed by a call to client_configure to make - the changes show */ -void client_setup_decor_and_functions(ObClient *self) +void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) { /* start with everything (cept fullscreen) */ self->decorations = @@ -1619,15 +1640,17 @@ void client_setup_decor_and_functions(ObClient *self) break; case OB_CLIENT_TYPE_DIALOG: + case OB_CLIENT_TYPE_UTILITY: /* these windows don't have anything added or removed by default */ break; - case OB_CLIENT_TYPE_UTILITY: case OB_CLIENT_TYPE_MENU: case OB_CLIENT_TYPE_TOOLBAR: - /* these windows can't iconify */ - self->decorations &= ~OB_FRAME_DECOR_ICONIFY; - self->functions &= ~OB_CLIENT_FUNC_ICONIFY; + /* these windows can't iconify or maximize */ + self->decorations &= ~(OB_FRAME_DECOR_ICONIFY | + OB_FRAME_DECOR_MAXIMIZE); + self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | + OB_CLIENT_FUNC_MAXIMIZE); break; case OB_CLIENT_TYPE_SPLASH: @@ -1736,6 +1759,9 @@ void client_setup_decor_and_functions(ObClient *self) } client_change_allowed_actions(self); + + if (reconfig) + client_reconfigure(self); } static void client_change_allowed_actions(ObClient *self) @@ -1795,11 +1821,9 @@ static void client_change_allowed_actions(ObClient *self) void client_reconfigure(ObClient *self) { - /* by making this pass FALSE for user, we avoid the emacs event storm where - every configurenotify causes an update in its normal hints, i think this - is generally what we want anyways... */ client_configure(self, self->area.x, self->area.y, - self->area.width, self->area.height, FALSE, TRUE); + self->area.width, self->area.height, + FALSE, TRUE); } void client_update_wmhints(ObClient *self) @@ -1880,7 +1904,8 @@ void client_update_wmhints(ObClient *self) } /* the WM_HINTS can contain an icon */ - client_update_icons(self); + if (hints->flags & IconPixmapHint) + client_update_icons(self); XFree(hints); } @@ -1932,8 +1957,14 @@ void client_update_title(ObClient *self) PROP_GETS(self->window, wm_icon_name, utf8, &data))) data = g_strdup(self->title); - PROP_SETS(self->window, net_wm_visible_icon_name, data); - self->icon_title = data; + if (self->client_machine) { + visible = g_strdup_printf("%s (%s)", data, self->client_machine); + g_free(data); + } else + visible = data; + + PROP_SETS(self->window, net_wm_visible_icon_name, visible); + self->icon_title = visible; } void client_update_strut(ObClient *self) @@ -2274,7 +2305,6 @@ static void client_change_wm_state(ObClient *self) state[0] = self->wmstate; state[1] = None; PROP_SETA32(self->window, wm_state, wm_state, state, 2); - ob_debug("setting wm_state %d\n", self->wmstate); } } @@ -2333,27 +2363,44 @@ ObClient *client_search_focus_tree_full(ObClient *self) return client_search_focus_tree_full(self->transient_for); } else { GSList *it; - gboolean recursed = FALSE; - for (it = self->group->members; it; it = g_slist_next(it)) - if (!((ObClient*)it->data)->transient_for) { - ObClient *c; - if ((c = client_search_focus_tree_full(it->data))) - return c; - recursed = TRUE; + for (it = self->group->members; it; it = g_slist_next(it)) { + if (it->data != self) { + ObClient *c = it->data; + + if (client_focused(c)) return c; + if ((c = client_search_focus_tree(it->data))) return c; } - if (recursed) - return NULL; + } } } - /* this function checks the whole tree, the client_search_focus_tree~ + /* this function checks the whole tree, the client_search_focus_tree does not, so we need to check this window */ if (client_focused(self)) return self; return client_search_focus_tree(self); } +gboolean client_has_parent(ObClient *self) +{ + if (self->transient_for) { + if (self->transient_for != OB_TRAN_GROUP) { + if (client_normal(self->transient_for)) + return TRUE; + } + else if (self->group) { + GSList *it; + + for (it = self->group->members; it; it = g_slist_next(it)) { + if (it->data != self && client_normal(it->data)) + return TRUE; + } + } + } + return FALSE; +} + static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; @@ -2366,10 +2413,10 @@ static ObStackingLayer calc_layer(ObClient *self) } else if ((self->fullscreen || /* No decorations and fills the monitor = oldskool fullscreen. - But not for undecorated windows, because the user can do that + But not for maximized windows. */ (self->decorations == 0 && - !self->undecorated && + !(self->max_horz && self->max_vert) && RECT_EQUAL(self->area, *screen_physical_area_monitor (client_monitor(self))))) && @@ -2458,8 +2505,7 @@ gboolean client_hide(ObClient *self) actions should not rely on being able to move focus during an interactive grab. */ - if (keyboard_interactively_grabbed()) - keyboard_interactive_cancel(); + event_cancel_all_key_grabs(); } frame_hide(self->frame); @@ -2509,44 +2555,59 @@ gboolean client_enter_focusable(ObClient *self) } -static void client_apply_startup_state(ObClient *self) +static void client_apply_startup_state(ObClient *self, + gint x, gint y, gint w, gint h) { - /* set the desktop hint, to make sure that it always exists */ - PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); + /* save the states that we are going to apply */ + gboolean iconic = self->iconic; + gboolean fullscreen = self->fullscreen; + gboolean undecorated = self->undecorated; + gboolean shaded = self->shaded; + gboolean demands_attention = self->demands_attention; + gboolean max_horz = self->max_horz; + gboolean max_vert = self->max_vert; + + /* turn them all off in the client, so they won't affect the window + being placed */ + self->iconic = self->fullscreen = self->undecorated = self->shaded = + self->demands_attention = self->max_horz = self->max_vert = FALSE; + + /* 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 + + do this before applying the states so they have the correct + pre-max/pre-fullscreen values + */ + client_configure(self, x, y, w, h, FALSE, TRUE); + ob_debug("placed window 0x%x at %d, %d with size %d x %d\n", + self->window, self->area.x, self->area.y, + self->area.width, self->area.height); - /* these are in a carefully crafted order.. */ + /* apply the states. these are in a carefully crafted order.. */ - if (self->iconic) { - self->iconic = FALSE; + if (iconic) client_iconify(self, TRUE, FALSE, TRUE); - } - if (self->fullscreen) { - self->fullscreen = FALSE; + if (fullscreen) client_fullscreen(self, TRUE); - } - if (self->undecorated) { - self->undecorated = FALSE; + if (undecorated) client_set_undecorated(self, TRUE); - } - if (self->shaded) { - self->shaded = FALSE; + if (shaded) client_shade(self, TRUE); - } - if (self->demands_attention) { - self->demands_attention = FALSE; + if (demands_attention) client_hilite(self, TRUE); - } - if (self->max_vert && self->max_horz) { - self->max_vert = self->max_horz = FALSE; + if (max_vert && max_horz) client_maximize(self, TRUE, 0); - } else if (self->max_vert) { - self->max_vert = FALSE; + else if (max_vert) client_maximize(self, TRUE, 2); - } else if (self->max_horz) { - self->max_horz = FALSE; + else if (max_horz) client_maximize(self, TRUE, 1); - } + + /* set the desktop hint, to make sure that it always exists */ + PROP_SET32(self->window, net_wm_desktop, cardinal, self->desktop); /* nothing to do for the other states: skip_taskbar @@ -2790,8 +2851,8 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, SIZE_SET(self->logical_size, logicalw, logicalh); /* figure out if we moved or resized or what */ - moved = x != self->area.x || y != self->area.y; - resized = w != self->area.width || h != self->area.height; + moved = (x != self->area.x || y != self->area.y); + resized = (w != self->area.width || h != self->area.height); oldw = self->area.width; oldh = self->area.height; @@ -2806,9 +2867,7 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* if the client is enlarging, then resize the client before the frame */ if (send_resize_client && (w > oldw || h > oldh)) { - XResizeWindow(ob_display, self->window, - MAX(w, oldw), MAX(h, oldh)); - /* resize the plate to show the client padding color underneath */ + XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh)); frame_adjust_client_area(self->frame); } @@ -2831,6 +2890,8 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, { XEvent event; + /* we have reset the client to 0 border width, so don't include + it in these coords */ POINT_SET(self->root_pos, self->frame->area.x + self->frame->size.left - self->border_width, @@ -2850,20 +2911,21 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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.border_width = self->border_width; + event.xconfigure.above = None; 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 */ + /* if the client is shrinking, then resize the frame before the client. + + both of these resize sections may run, because the top one only resizes + in the direction that is growing + */ if (send_resize_client && (w <= oldw || h <= oldh)) { - /* resize the plate to show the client padding color underneath */ frame_adjust_client_area(self->frame); - - if (send_resize_client) - XResizeWindow(ob_display, self->window, w, h); + XResizeWindow(ob_display, self->window, w, h); } XFlush(ob_display); @@ -2909,8 +2971,7 @@ void client_fullscreen(ObClient *self, gboolean fs) RECT_SET(self->pre_fullscreen_area, 0, 0, 0, 0); } - client_setup_decor_and_functions(self); - + client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); /* and adjust our layer/stacking. do this after resizing the window, @@ -2943,9 +3004,8 @@ static void client_iconify_recursive(ObClient *self, self->iconic = iconic; /* update the focus lists.. iconic windows go to the bottom of - the list, put the new iconic window at the 'top of the - bottom'. */ - focus_order_to_top(self); + the list */ + focus_order_to_bottom(self); changed = TRUE; } @@ -3055,8 +3115,7 @@ void client_maximize(ObClient *self, gboolean max, gint dir) client_change_state(self); /* change the state hints on the client */ - client_setup_decor_and_functions(self); - + client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); } @@ -3423,6 +3482,10 @@ gboolean client_can_focus(ObClient *self) gboolean client_focus(ObClient *self) { + /* we might not focus this window, so if we have modal children which would + be focused instead, bring them to this desktop */ + client_bring_modal_windows(self); + /* choose the correct target */ self = client_focus_target(self); @@ -3431,12 +3494,14 @@ gboolean client_focus(ObClient *self) /* update the focus lists */ focus_order_to_top(self); } + ob_debug_type(OB_DEBUG_FOCUS, + "Client %s can't be focused\n", self->title); return FALSE; } ob_debug_type(OB_DEBUG_FOCUS, - "Focusing client \"%s\" at time %u\n", - self->title, event_curtime); + "Focusing client \"%s\" (0x%x) at time %u\n", + self->title, self->window, event_curtime); /* if there is a grab going on, then we need to cancel it. if we move focus during the grab, applications will get NotifyWhileGrabbed events @@ -3445,8 +3510,7 @@ gboolean client_focus(ObClient *self) actions should not rely on being able to move focus during an interactive grab. */ - if (keyboard_interactively_grabbed()) - keyboard_interactive_cancel(); + event_cancel_all_key_grabs(); xerror_set_ignore(TRUE); xerror_occured = FALSE; @@ -3475,6 +3539,7 @@ gboolean client_focus(ObClient *self) xerror_set_ignore(FALSE); + ob_debug_type(OB_DEBUG_FOCUS, "Error focusing? %d\n", xerror_occured); return !xerror_occured; } @@ -3542,15 +3607,18 @@ void client_activate(ObClient *self, gboolean here, gboolean user) client_hilite(self, TRUE); } -static void client_bring_helper_windows_recursive(ObClient *self, - guint desktop) +static void client_bring_windows_recursive(ObClient *self, + guint desktop, + gboolean helpers, + gboolean modals) { GSList *it; for (it = self->transients; it; it = g_slist_next(it)) - client_bring_helper_windows_recursive(it->data, desktop); + client_bring_windows_recursive(it->data, desktop, helpers, modals); - if (client_helper(self) && + if (((helpers && client_helper(self)) || + (modals && self->modal))&& self->desktop != desktop && self->desktop != DESKTOP_ALL) { client_set_desktop(self, desktop, FALSE); @@ -3559,7 +3627,12 @@ static void client_bring_helper_windows_recursive(ObClient *self, void client_bring_helper_windows(ObClient *self) { - client_bring_helper_windows_recursive(self, self->desktop); + client_bring_windows_recursive(self, self->desktop, TRUE, FALSE); +} + +void client_bring_modal_windows(ObClient *self) +{ + client_bring_windows_recursive(self, self->desktop, FALSE, TRUE); } gboolean client_focused(ObClient *self) @@ -3603,7 +3676,7 @@ static ObClientIcon* client_icon_recursive(ObClient *self, gint w, gint h) for (i = 1; i < self->nicons; ++i) { gulong diff; - diff = ABS(self->icons[0].width - w) + ABS(self->icons[0].height - h); + diff = ABS(self->icons[i].width - w) + ABS(self->icons[i].height - h); if (diff < min_diff) { min_diff = diff; min_i = i; @@ -3648,8 +3721,7 @@ void client_set_undecorated(ObClient *self, gboolean undecorated) (self->functions & OB_CLIENT_FUNC_UNDECORATE || !undecorated)) { self->undecorated = undecorated; - client_setup_decor_and_functions(self); - client_reconfigure(self); /* show the lack of decorations */ + client_setup_decor_and_functions(self, TRUE); client_change_state(self); /* reflect this in the state hints */ } }