X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=71be0f94656baf078a48cfb25405da2e75e75b13;hb=809619497d73598a9f3c2bd2e4b8968297af6bfd;hp=03e4c9a5f33a3976691ba8cf18c4cbb2a3cd9710;hpb=7c6050b6f519d10446002da92d12cfc5e6ce2e15;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index 03e4c9a5..71be0f94 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,27 @@ 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_monitor(self->desktop, client_monitor(self), + &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); } @@ -532,7 +532,16 @@ 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_show(self); + { + gulong ignore_start; + if (!config_focus_under_mouse) + ignore_start = event_start_ignore_all_enters(); + + client_show(self); + + if (!config_focus_under_mouse) + event_end_ignore_all_enters(ignore_start); + } if (activate) { gboolean stacked = client_restore_session_stacking(self); @@ -616,14 +625,14 @@ void client_unmanage(ObClient *self) XSelectInput(ob_display, self->window, NoEventMask); /* ignore enter events from the unmap so it doesnt mess with the focus */ - if (!client_focused(self) || !config_focus_under_mouse) + if (!config_focus_under_mouse) ignore_start = event_start_ignore_all_enters(); frame_hide(self->frame); /* flush to send the hide to the server quickly */ XFlush(ob_display); - if (!client_focused(self) || !config_focus_under_mouse) + if (!config_focus_under_mouse) event_end_ignore_all_enters(ignore_start); mouse_grab_for_client(self, FALSE); @@ -921,8 +930,11 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, Rect desired; 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); + + all_a = screen_area(self->desktop, &desired); + mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired), + &desired); /* get where the frame would be */ frame_client_gravity(self->frame, x, y, w, h); @@ -1008,6 +1020,9 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h, /* get where the client should be */ frame_frame_gravity(self->frame, x, y, w, h); + g_free(all_a); + g_free(mon_a); + return ox != *x || oy != *y; } @@ -1569,7 +1584,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) @@ -1708,12 +1732,8 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) /* finally, the user can have requested no decorations, which overrides everything (but doesnt give it a border if it doesnt have one) */ - if (self->undecorated) { - if (config_theme_keepborder) - self->decorations &= OB_FRAME_DECOR_BORDER; - else - self->decorations = 0; - } + if (self->undecorated) + self->decorations = 0; /* if we don't have a titlebar, then we cannot shade! */ if (!(self->decorations & OB_FRAME_DECOR_TITLEBAR)) @@ -1960,7 +1980,7 @@ 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; @@ -1973,6 +1993,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); } @@ -2047,18 +2068,19 @@ void client_update_icons(ObClient *self) if ((hints = XGetWMHints(ob_display, self->window))) { if (hints->flags & IconPixmapHint) { - self->nicons++; + self->nicons = 1; self->icons = g_new(ObClientIcon, self->nicons); xerror_set_ignore(TRUE); if (!RrPixmapToRGBA(ob_rr_inst, hints->icon_pixmap, (hints->flags & IconMaskHint ? hints->icon_mask : None), - &self->icons[self->nicons-1].width, - &self->icons[self->nicons-1].height, - &self->icons[self->nicons-1].data)){ - g_free(&self->icons[self->nicons-1]); - self->nicons--; + &self->icons[0].width, + &self->icons[0].height, + &self->icons[0].data)) + { + g_free(self->icons); + self->nicons = 0; } xerror_set_ignore(FALSE); } @@ -2372,6 +2394,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; @@ -2385,15 +2410,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; } @@ -2476,6 +2501,19 @@ gboolean client_hide(ObClient *self) event_cancel_all_key_grabs(); } + /* 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; @@ -2553,10 +2591,10 @@ static void client_apply_startup_state(ObClient *self, */ client_try_configure(self, &x, &y, &w, &h, &l, &l, FALSE); 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); - oldarea = self->area; /* save the area */ - RECT_SET(self->area, x, y, w, h); /* put where it should be for the premax stuff */ + self->window, x, y, w, h); + /* save the area, and make it where it should be for the premax stuff */ + oldarea = self->area; + RECT_SET(self->area, x, y, w, h); /* apply the states. these are in a carefully crafted order.. */ @@ -2658,16 +2696,74 @@ 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; + + i = screen_find_monitor(&desired); + a = screen_area_monitor(self->desktop, i, &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) { @@ -2699,19 +2795,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; @@ -2721,77 +2817,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)) { @@ -3203,6 +3253,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(); } @@ -3569,17 +3622,19 @@ void client_activate(ObClient *self, gboolean here, gboolean user) guint32 last_time = focus_client ? focus_client->user_time : CurrentTime; gboolean allow = FALSE; - /* if the request came from the user, or if nothing is focused, then grant - the request. - if the currently focused app doesn't set a user_time, then it can't + /* if the currently focused app doesn't set a user_time, then it can't benefit from any focus stealing prevention. + + if the timestamp is missing in the request then let it go through + even if it is source=app, because EVERY APPLICATION DOES THIS because + GTK IS VERY BUGGY AND HARDCODES source=application... WHY!? */ - if (user || !focus_client || !last_time) + if (!last_time || !event_curtime) allow = TRUE; /* otherwise, if they didn't give a time stamp or if it is too old, they don't get focus */ else - allow = event_curtime && event_time_after(event_curtime, last_time); + allow = event_time_after(event_curtime, last_time); ob_debug_type(OB_DEBUG_FOCUS, "Want to activate window 0x%x with time %u (last time %u), " @@ -3823,8 +3878,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang) if(!client_list) return -1; - a = screen_area(c->desktop); - monitor = screen_area_monitor(c->desktop, client_monitor(c)); + a = screen_area(c->desktop, &c->frame->area); + monitor = screen_area_monitor(c->desktop, client_monitor(c), + &c->frame->area); switch(dir) { case OB_DIRECTION_NORTH: @@ -3971,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(monitor); return dest; } @@ -3985,6 +4044,11 @@ ObClient* client_under_pointer() if (WINDOW_IS_CLIENT(it->data)) { ObClient *c = WINDOW_AS_CLIENT(it->data); if (c->frame->visible && + /* check the desktop, this is done during desktop + switching and windows are shown/hidden status is not + reliable */ + (c->desktop == screen_desktop || + c->desktop == DESKTOP_ALL) && /* ignore all animating windows */ !frame_iconify_animating(c->frame) && RECT_CONTAINS(c->frame->area, x, y))