X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=ffbcd5cae8c7074f08d3e99ea3a762e23246558a;hb=959fff5e1cda35b0a1569ef323aab3129db3cb1f;hp=358b44556bba2566f18af4497bf91dd08e35ca05;hpb=a16f1374eed70bc30a85f35f56c05d3073c6f0e0;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 358b4455..ffbcd5ca 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -348,7 +348,7 @@ 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), @@ -369,7 +369,7 @@ void client_manage(Window window) placex = self->area.x; placey = self->area.y; - /* 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; @@ -377,10 +377,44 @@ void client_manage(Window window) (!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 !?")))), self->area.x, self->area.y); + + 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 !?")))), self->area.width, self->area.height); 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->sized & USSize)) { + /* 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, @@ -450,8 +484,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 +496,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 (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. */ - 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) { @@ -551,6 +607,10 @@ ObClient *client_fake_manage(Window window) 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); @@ -815,6 +875,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) @@ -962,16 +1023,13 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, * xterm -geometry resolution-width/2 will work fine. Trying to * place it completely offscreen will be handled in the above code. * Sorry for this confused comment, i am tired. */ - if (fw <= mon_a->width) { - if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x; - if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width) - *x = mon_a->x + mon_a->width - fw; - } - if (fh <= mon_a->height) { - if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y; - if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height) - *y = mon_a->y + mon_a->height - fh; - } + if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x; + if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width) + *x = mon_a->x + MAX(0, mon_a->width - fw); + + if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y; + if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height) + *y = mon_a->y + MAX(0, mon_a->height - fh); /* get where the client should be */ frame_frame_gravity(self->frame, x, y, w, h); @@ -1142,15 +1200,27 @@ static void client_get_desktop(ObClient *self) 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) { @@ -1541,7 +1611,6 @@ void client_update_normal_hints(ObClient *self) { XSizeHints size; glong ret; - gint oldgravity = self->gravity; /* defaults */ self->min_ratio = 0.0f; @@ -1557,20 +1626,10 @@ 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) { + if (size.flags & PWinGravity) self->gravity = size.win_gravity; - - /* if the client has a frame, i.e. has already been mapped and - is changing its gravity */ - if (self->frame && self->gravity != oldgravity) { - /* move our idea of the client's position based on its new - gravity */ - client_convert_gravity(self, oldgravity, - &self->area.x, &self->area.y, - self->area.width, self->area.height); - } - } if (size.flags & PAspect) { if (size.min_aspect.y) @@ -1635,14 +1694,16 @@ void client_setup_decor_and_functions(ObClient *self) case OB_CLIENT_TYPE_DIALOG: case OB_CLIENT_TYPE_UTILITY: - /* these windows cannot be maximized */ - self->functions &= ~OB_CLIENT_FUNC_MAXIMIZE; + /* these windows don't have anything added or removed by default */ break; case OB_CLIENT_TYPE_MENU: case OB_CLIENT_TYPE_TOOLBAR: - /* these windows get less functionality */ - self->functions &= ~(OB_CLIENT_FUNC_ICONIFY | OB_CLIENT_FUNC_RESIZE); + /* 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: @@ -1717,9 +1778,12 @@ void client_setup_decor_and_functions(ObClient *self) self->decorations &= ~OB_FRAME_DECOR_MAXIMIZE; } - if (self->max_horz && self->max_vert) + if (self->max_horz && self->max_vert) { + /* you can't resize fully maximized windows */ + self->functions &= ~OB_CLIENT_FUNC_RESIZE; /* kill the handle on fully maxed windows */ self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS); + } /* If there are no decorations to remove, don't allow the user to try toggle the state */ @@ -1892,7 +1956,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); } @@ -1944,8 +2009,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) @@ -2377,10 +2448,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))))) && @@ -2446,13 +2517,13 @@ gboolean client_show(ObClient *self) if (client_should_show(self)) { frame_show(self->frame); show = TRUE; - } - /* 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); + /* 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); + } return show; } @@ -2475,13 +2546,13 @@ gboolean client_hide(ObClient *self) frame_hide(self->frame); hide = TRUE; - } - /* 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); + /* 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); + } return hide; } @@ -2489,12 +2560,6 @@ void client_showhide(ObClient *self) { if (!client_show(self)) client_hide(self); - - /* 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); } gboolean client_normal(ObClient *self) { @@ -2574,18 +2639,62 @@ static void client_apply_startup_state(ObClient *self) */ } -void client_convert_gravity(ObClient *self, gint gravity, gint *x, gint *y, - gint w, gint h) +void client_gravity_resize_w(ObClient *self, gint *x, gint oldw, gint neww) { - gint oldg = self->gravity; + /* these should be the current values. this is for when you're not moving, + just resizing */ + g_assert(*x == self->area.x); + g_assert(oldw == self->area.width); - /* get the frame's position from the requested stuff */ - self->gravity = gravity; - frame_client_gravity(self->frame, x, y, w, h); - self->gravity = oldg; + /* horizontal */ + switch (self->gravity) { + default: + case NorthWestGravity: + case WestGravity: + case SouthWestGravity: + case StaticGravity: + case ForgetGravity: + break; + case NorthGravity: + case CenterGravity: + case SouthGravity: + *x -= (neww - oldw) / 2; + break; + case NorthEastGravity: + case EastGravity: + case SouthEastGravity: + *x -= neww - oldw; + break; + } +} - /* get the client's position in its true gravity from that */ - frame_frame_gravity(self->frame, x, y, w, h); +void client_gravity_resize_h(ObClient *self, gint *y, gint oldh, gint newh) +{ + /* these should be the current values. this is for when you're not moving, + just resizing */ + g_assert(*y == self->area.y); + g_assert(oldh == self->area.height); + + /* vertical */ + switch (self->gravity) { + default: + case NorthWestGravity: + case NorthGravity: + case NorthEastGravity: + case StaticGravity: + case ForgetGravity: + break; + case WestGravity: + case CenterGravity: + case EastGravity: + *y -= (newh - oldh) / 2; + break; + case SouthWestGravity: + case SouthGravity: + case SouthEastGravity: + *y -= newh - oldh; + break; + } } void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, @@ -2597,7 +2706,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, /* 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); + frame_adjust_area(self->frame, FALSE, TRUE, TRUE); /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { @@ -2701,7 +2810,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *h = a->height; user = FALSE; /* ignore if the client can't be moved/resized when it - is entering fullscreen */ + is fullscreening */ } else if (self->max_horz || self->max_vert) { Rect *a; guint i; @@ -2719,8 +2828,8 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *h = a->height - self->frame->size.top - self->frame->size.bottom; } - /* maximizing is not allowed if the user can't move+resize the window - */ + user = FALSE; /* ignore if the client can't be moved/resized when it + is maximizing */ } /* gets the client's position */ @@ -2788,11 +2897,15 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* find the frame's dimensions and move/resize it */ fmoved = moved; fresized = resized; + + /* if decorations changed, then readjust everything for the frame */ if (self->decorations != fdecor || self->max_horz != fhorz || self->max_vert != fvert) { fmoved = fresized = TRUE; } + + /* adjust the frame */ if (fmoved || fresized) frame_adjust_area(self->frame, fmoved, fresized, FALSE); @@ -2912,9 +3025,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; } @@ -2957,10 +3069,6 @@ void client_iconify(ObClient *self, gboolean iconic, gboolean curdesk, /* move up the transient chain as far as possible first */ self = client_search_top_normal_parent(self); client_iconify_recursive(self, iconic, curdesk, hide_animation); - - /* try focus the window that was de-iconified if focusNew is on */ - if (!iconic && config_focus_new) - client_focus(self); } } @@ -3576,7 +3684,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;