X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=152f2316d8ae5c81312a061c4a484646fd06545b;hb=44bc0dab886c924b6aac1d3f1eaf4cc0164950c9;hp=d42f4f85adcdb526503ca7206d7e6ac916007f3b;hpb=4b3b71c54eb21c23cdb64b8abc8e93a732282f75;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index d42f4f85..152f2316 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -314,18 +314,12 @@ void client_manage(Window window) /* 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_tree_full(self)) && /* this checks for focus=false for the window */ (!settings || settings->focus != 0) && - /* 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)) + focus_valid_target(self, FALSE, TRUE, FALSE, FALSE)) { activate = TRUE; } @@ -404,21 +398,26 @@ void client_manage(Window window) client_normal(self) && !self->session))) { - /* make a copy to modify */ - Rect a = *screen_area_monitor(self->desktop, client_monitor(self)); + Rect placer; + + RECT_SET(placer, placex, placey, placew, placeh); + frame_rect_to_frame(self->frame, &placer); + + Rect *a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &placer); /* 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; + 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 */ - if (placew > a.width || self->area.height > a.height) { - placew = MIN(self->area.width, a.width); - placeh = MIN(self->area.height, a.height); + if (placew > a->width || self->area.height > a->height) { + placew = MIN(self->area.width, a->width); + placeh = MIN(self->area.height, a->height); ob_debug("setting window size to %dx%d\n", self->area.width, self->area.height); } + g_free(a); } @@ -923,15 +922,14 @@ void client_move_onscreen(ObClient *self, gboolean rude) gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, gboolean rude) { - Rect *mon_a, *all_a; gint ox = *x, oy = *y; gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude; gint fw, fh; Rect desired; + guint i; RECT_SET(desired, *x, *y, w, h); - all_a = screen_area(self->desktop); - mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired)); + frame_rect_to_frame(self->frame, &desired); /* get where the frame would be */ frame_client_gravity(self->frame, x, y, w, h); @@ -940,30 +938,8 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, fw = self->frame->size.left + w + self->frame->size.right; fh = self->frame->size.top + h + self->frame->size.bottom; - /* This makes sure windows aren't entirely outside of the screen so you - can't see them at all. - It makes sure 10% of the window is on the screen at least. At don't let - it move itself off the top of the screen, which would hide the titlebar - on you. (The user can still do this if they want too, it's only limiting - the application. - - XXX watch for xinerama dead areas... - */ - if (client_normal(self)) { - if (!self->strut.right && *x + fw/10 >= all_a->x + all_a->width - 1) - *x = all_a->x + all_a->width - fw/10; - if (!self->strut.bottom && *y + fh/10 >= all_a->y + all_a->height - 1) - *y = all_a->y + all_a->height - fh/10; - if (!self->strut.left && *x + fw*9/10 - 1 < all_a->x) - *x = all_a->x - fw*9/10; - if (!self->strut.top && *y + fh*9/10 - 1 < all_a->y) - *y = all_a->y - fw*9/10; - } - - /* If rudeness wasn't requested, then figure out of the client is currently - entirely on the screen. If it is, and the position isn't changing by - request, and it is enlarging, then be rude even though it wasn't - requested */ + /* If rudeness wasn't requested, then still be rude in a given direction + if the client is not moving, only resizing in that direction */ if (!rude) { Point oldtl, oldtr, oldbl, oldbr; Point newtl, newtr, newbl, newbr; @@ -1000,19 +976,48 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, rudeb = TRUE; } - /* This here doesn't let windows even a pixel outside the struts/screen. - * When called from client_manage, programs placing themselves are - * forced completely onscreen, while things like - * 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 (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); + for (i = 0; i < screen_num_monitors; ++i) { + Rect *a; + + if (!screen_physical_area_monitor_contains(i, &desired)) + continue; - 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); + a = screen_area(self->desktop, SCREEN_AREA_ONE_MONITOR, &desired); + + /* This makes sure windows aren't entirely outside of the screen so you + can't see them at all. + It makes sure 10% of the window is on the screen at least. At don't + let it move itself off the top of the screen, which would hide the + titlebar on you. (The user can still do this if they want too, it's + only limiting the application. + */ + if (client_normal(self)) { + if (!self->strut.right && *x + fw/10 >= a->x + a->width - 1) + *x = a->x + a->width - fw/10; + if (!self->strut.bottom && *y + fh/10 >= a->y + a->height - 1) + *y = a->y + a->height - fh/10; + if (!self->strut.left && *x + fw*9/10 - 1 < a->x) + *x = a->x - fw*9/10; + if (!self->strut.top && *y + fh*9/10 - 1 < a->y) + *y = a->y - fw*9/10; + } + + /* This here doesn't let windows even a pixel outside the + struts/screen. When called from client_manage, programs placing + themselves are forced completely onscreen, while things like + 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 (rudel && !self->strut.left && *x < a->x) *x = a->x; + if (ruder && !self->strut.right && *x + fw > a->x + a->width) + *x = a->x + MAX(0, a->width - fw); + + if (rudet && !self->strut.top && *y < a->y) *y = a->y; + if (rudeb && !self->strut.bottom && *y + fh > a->y + a->height) + *y = a->y + MAX(0, a->height - fh); + + g_free(a); + } /* get where the client should be */ frame_frame_gravity(self->frame, x, y, w, h); @@ -1578,7 +1583,16 @@ void client_update_normal_hints(ObClient *self) if (size.flags & PResizeInc && size.width_inc && size.height_inc) SIZE_SET(self->size_inc, size.width_inc, size.height_inc); + + ob_debug("Normal hints: min size (%d %d) max size (%d %d)\n " + "size inc (%d %d) base size (%d %d)\n", + self->min_size.width, self->min_size.height, + self->max_size.width, self->max_size.height, + self->size_inc.width, self->size_inc.height, + self->base_size.width, self->base_size.height); } + else + ob_debug("Normal hints: not set\n"); } void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) @@ -1965,12 +1979,12 @@ void client_update_strut(ObClient *self) if (!got && PROP_GETA32(self->window, net_wm_strut, cardinal, &data, &num)) { if (num == 4) { - const Rect *a; + Rect *a; got = TRUE; /* use the screen's width/height */ - a = screen_physical_area(); + a = screen_physical_area_all_monitors(); STRUT_PARTIAL_SET(strut, data[0], data[2], data[1], data[3], @@ -1978,6 +1992,7 @@ void client_update_strut(ObClient *self) a->x, a->x + a->width - 1, a->y, a->y + a->height - 1, a->x, a->x + a->width - 1); + g_free(a); } g_free(data); } @@ -2378,6 +2393,9 @@ gboolean client_has_parent(ObClient *self) static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; + Rect *monitor; + + monitor = screen_physical_area_monitor(client_monitor(self)); if (self->type == OB_CLIENT_TYPE_DESKTOP) l = OB_STACKING_LAYER_DESKTOP; @@ -2391,15 +2409,15 @@ static ObStackingLayer calc_layer(ObClient *self) */ (self->decorations == 0 && !(self->max_horz && self->max_vert) && - RECT_EQUAL(self->area, - *screen_physical_area_monitor - (client_monitor(self))))) && + RECT_EQUAL(self->area, *monitor))) && (client_focused(self) || client_search_focus_tree(self))) l = OB_STACKING_LAYER_FULLSCREEN; else if (self->above) l = OB_STACKING_LAYER_ABOVE; else if (self->below) l = OB_STACKING_LAYER_BELOW; else l = OB_STACKING_LAYER_NORMAL; + g_free(monitor); + return l; } @@ -2469,7 +2487,6 @@ gboolean client_show(ObClient *self) gboolean client_hide(ObClient *self) { gboolean hide = FALSE; - gulong ignore_start; if (!client_should_show(self)) { if (self == focus_client) { @@ -2483,15 +2500,22 @@ gboolean client_hide(ObClient *self) event_cancel_all_key_grabs(); } - if (!config_focus_under_mouse) - ignore_start = event_start_ignore_all_enters(); + /* We don't need to ignore enter events here. + The window can hide/iconify in 3 different ways: + 1 - through an x message. in this case we ignore all enter events + caused by responding to the x message (unless underMouse) + 2 - by a keyboard action. in this case we ignore all enter events + caused by the action + 3 - by a mouse action. in this case they are doing stuff with the + mouse and focus _should_ move. + + Also in action_end, we simulate an enter event that can't be ignored + so trying to ignore them is futile in case 3 anyways + */ frame_hide(self->frame); hide = TRUE; - if (!config_focus_under_mouse) - event_end_ignore_all_enters(ignore_start); - /* 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! @@ -2671,16 +2695,76 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, gint *logicalw, gint *logicalh, gboolean user) { - Rect desired_area = {*x, *y, *w, *h}; + Rect desired = {*x, *y, *w, *h}; + frame_rect_to_frame(self->frame, &desired); /* 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, FALSE, TRUE, TRUE); + /* gets the frame's position */ + frame_client_gravity(self->frame, x, y, *w, *h); + + /* 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); + 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 fullscreening */ + + g_free(a); + } else if (self->max_horz || self->max_vert) { + Rect *a; + guint i; + + /* use all possible struts when maximizing to the full screen */ + i = screen_find_monitor(&desired); + a = screen_area(self->desktop, i, + (self->max_horz && self->max_vert ? NULL : &desired)); + + /* 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; + } + + user = FALSE; /* ignore if the client can't be moved/resized when it + is maximizing */ + + g_free(a); + } + + /* gets the client's position */ + frame_frame_gravity(self->frame, x, y, *w, *h); + /* work within the prefered sizes given by the window */ if (!(*w == self->area.width && *h == self->area.height)) { gint basew, baseh, minw, minh; + gint incw, inch; + gfloat minratio, maxratio; + + incw = self->fullscreen || self->max_horz ? 1 : self->size_inc.width; + inch = self->fullscreen || self->max_vert ? 1 : self->size_inc.height; + minratio = self->fullscreen || (self->max_horz && self->max_vert) ? + 0 : self->min_ratio; + maxratio = self->fullscreen || (self->max_horz && self->max_vert) ? + 0 : self->max_ratio; /* base size is substituted with min size if not specified */ if (self->base_size.width || self->base_size.height) { @@ -2712,19 +2796,19 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *h -= baseh; /* keep to the increments */ - *w /= self->size_inc.width; - *h /= self->size_inc.height; + *w /= incw; + *h /= inch; /* you cannot resize to nothing */ if (basew + *w < 1) *w = 1 - basew; if (baseh + *h < 1) *h = 1 - baseh; /* save the logical size */ - *logicalw = self->size_inc.width > 1 ? *w : *w + basew; - *logicalh = self->size_inc.height > 1 ? *h : *h + baseh; + *logicalw = incw > 1 ? *w : *w + basew; + *logicalh = inch > 1 ? *h : *h + baseh; - *w *= self->size_inc.width; - *h *= self->size_inc.height; + *w *= incw; + *h *= inch; *w += basew; *h += baseh; @@ -2734,77 +2818,31 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *w -= self->base_size.width; *h -= self->base_size.height; - if (!self->fullscreen) { - if (self->min_ratio) - if (*h * self->min_ratio > *w) { - *h = (gint)(*w / self->min_ratio); + if (minratio) + if (*h * minratio > *w) { + *h = (gint)(*w / minratio); - /* you cannot resize to nothing */ - if (*h < 1) { - *h = 1; - *w = (gint)(*h * self->min_ratio); - } + /* you cannot resize to nothing */ + if (*h < 1) { + *h = 1; + *w = (gint)(*h * minratio); } - if (self->max_ratio) - if (*h * self->max_ratio < *w) { - *h = (gint)(*w / self->max_ratio); - - /* you cannot resize to nothing */ - if (*h < 1) { - *h = 1; - *w = (gint)(*h * self->min_ratio); - } + } + if (maxratio) + if (*h * maxratio < *w) { + *h = (gint)(*w / maxratio); + + /* you cannot resize to nothing */ + if (*h < 1) { + *h = 1; + *w = (gint)(*h * minratio); } - } + } *w += self->base_size.width; *h += self->base_size.height; } - /* gets the frame's position */ - frame_client_gravity(self->frame, x, y, *w, *h); - - /* 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 fullscreening */ - } 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; - } - - user = FALSE; /* ignore if the client can't be moved/resized when it - is maximizing */ - } - - /* gets the client's position */ - frame_frame_gravity(self->frame, x, y, *w, *h); - /* these override the above states! if you cant move you can't move! */ if (user) { if (!(self->functions & OB_CLIENT_FUNC_MOVE)) { @@ -3136,7 +3174,7 @@ void client_shade(ObClient *self, gboolean shade) client_change_state(self); client_change_wm_state(self); /* the window is being hidden/shown */ /* resize the frame to just the titlebar */ - frame_adjust_area(self->frame, FALSE, FALSE, FALSE); + frame_adjust_area(self->frame, FALSE, TRUE, FALSE); } void client_close(ObClient *self) @@ -3216,6 +3254,9 @@ void client_set_desktop_recursive(ObClient *self, /* raise if it was not already on the desktop */ if (old != DESKTOP_ALL) stacking_raise(CLIENT_AS_WINDOW(self)); + /* the new desktop's geometry may be different, so we may need to + resize, for example if we are maximized */ + client_reconfigure(self); if (STRUT_EXISTS(self->strut)) screen_update_areas(); } @@ -3833,13 +3874,13 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) gint dest, monitor_dest; gint my_edge_start, my_edge_end, my_offset; GList *it; - Rect *a, *monitor; + Rect *a, *mon; if(!client_list) return -1; - a = screen_area(c->desktop); - monitor = screen_area_monitor(c->desktop, client_monitor(c)); + a = screen_area(c->desktop, SCREEN_AREA_ALL_MONITORS, &c->frame->area); + mon = screen_area(c->desktop, SCREEN_AREA_ONE_MONITOR, &c->frame->area); switch(dir) { case OB_DIRECTION_NORTH: @@ -3849,7 +3890,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: top of screen */ dest = a->y + (hang ? c->frame->area.height : 0); - monitor_dest = monitor->y + (hang ? c->frame->area.height : 0); + monitor_dest = mon->y + (hang ? c->frame->area.height : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ if (monitor_dest != dest && my_offset > monitor_dest) @@ -3882,7 +3923,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: bottom of screen */ dest = a->y + a->height - (hang ? c->frame->area.height : 0); - monitor_dest = monitor->y + monitor->height - + monitor_dest = mon->y + mon->height - (hang ? c->frame->area.height : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ @@ -3917,7 +3958,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: leftmost egde of screen */ dest = a->x + (hang ? c->frame->area.width : 0); - monitor_dest = monitor->x + (hang ? c->frame->area.width : 0); + monitor_dest = mon->x + (hang ? c->frame->area.width : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ if (monitor_dest != dest && my_offset > monitor_dest) @@ -3950,7 +3991,7 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) /* default: rightmost edge of screen */ dest = a->x + a->width - (hang ? c->frame->area.width : 0); - monitor_dest = monitor->x + monitor->width - + monitor_dest = mon->x + mon->width - (hang ? c->frame->area.width : 0); /* if the monitor edge comes before the screen edge, */ /* use that as the destination instead. (For xinerama) */ @@ -3986,6 +4027,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) g_assert_not_reached(); dest = 0; /* suppress warning */ } + + g_free(a); + g_free(mon); return dest; }