X-Git-Url: https://git.brokenzipper.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=3456c5f8928e3f105feb74b383ae4c7a87f5cd97;hb=98bc768a710169e2e53cb42098d7e90e927d9d6b;hp=ffbcd5cae8c7074f08d3e99ea3a762e23246558a;hpb=16ae58681e43649069933d08029e03b799073d8e;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index ffbcd5ca..3456c5f8 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); @@ -278,7 +277,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 +321,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; @@ -377,7 +373,7 @@ void client_manage(Window window) (!self->positioned ? "no" : (self->positioned == PPosition ? "program specified" : (self->positioned == USPosition ? "user specified" : - (self->positioned == PPosition | USPosition ? + (self->positioned == (PPosition | USPosition) ? "program + user specified" : "BADNESS !?")))), self->area.x, self->area.y); @@ -385,7 +381,7 @@ void client_manage(Window window) (!self->sized ? "no" : (self->sized == PSize ? "program specified" : (self->sized == USSize ? "user specified" : - (self->sized == PSize | USSize ? + (self->sized == (PSize | USSize) ? "program + user specified" : "BADNESS !?")))), self->area.width, self->area.height); @@ -404,15 +400,17 @@ void client_manage(Window window) 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); + if (self->area.width > a.width || self->area.height > a.height) { + 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); + 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); + /* 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. */ @@ -429,8 +427,7 @@ void client_manage(Window window) it is up to the placement routines to avoid the xinerama divides) */ transient || - (((self->positioned & PPosition) && - !(self->positioned & USPosition)) && + (!(self->positioned & USPosition) && client_normal(self) && !self->session)); } @@ -444,7 +441,6 @@ void client_manage(Window window) /* 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); @@ -460,6 +456,7 @@ void client_manage(Window window) */ client_configure(self, placex, placey, self->area.width, self->area.height, + self->border_width, FALSE, TRUE); @@ -500,7 +497,7 @@ void client_manage(Window window) 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 && + else if (client_has_parent(self) && (!last_time || self->user_time == last_time)) { activate = FALSE; @@ -601,7 +598,7 @@ 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); @@ -701,9 +698,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) @@ -1037,71 +1031,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 */ @@ -1179,8 +1108,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) @@ -1192,13 +1121,16 @@ 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 */ @@ -1604,7 +1536,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) @@ -1654,9 +1595,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 = @@ -1812,6 +1751,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) @@ -1871,11 +1813,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, + self->border_width, FALSE, TRUE); } void client_update_wmhints(ObClient *self) @@ -2415,27 +2355,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; @@ -2540,8 +2497,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); @@ -2852,7 +2808,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, } -void client_configure(ObClient *self, gint x, gint y, gint w, gint h, +void client_configure(ObClient *self, gint x, gint y, gint w, gint h, gint b, gboolean user, gboolean final) { gint oldw, oldh; @@ -2873,11 +2829,13 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* 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; + resized = w != self->area.width || h != self->area.height || + b != self->border_width; oldw = self->area.width; oldh = self->area.height; RECT_SET(self->area, x, y, w, h); + self->border_width = b; /* for app-requested resizes, always resize if 'resized' is true. for user-requested ones, only resize if final is true, or when @@ -2888,8 +2846,15 @@ 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)); + XWindowChanges changes; + changes.x = -self->border_width; + changes.y = -self->border_width; + changes.width = MAX(w, oldw); + changes.height = MAX(h, oldh); + changes.border_width = self->border_width; + XConfigureWindow(ob_display, self->window, + CWX|CWY|CWWidth|CWHeight|CWBorderWidth, + &changes); /* resize the plate to show the client padding color underneath */ frame_adjust_client_area(self->frame); } @@ -2913,6 +2878,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, @@ -2932,20 +2899,29 @@ 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 (send_resize_client && (w <= oldw || h <= oldh)) { + 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); + if (send_resize_client) { + XWindowChanges changes; + changes.x = -self->border_width; + changes.y = -self->border_width; + changes.width = w; + changes.height = h; + changes.border_width = self->border_width; + XConfigureWindow(ob_display, self->window, + CWX|CWY|CWWidth|CWHeight|CWBorderWidth, + &changes); + } } XFlush(ob_display); @@ -2991,8 +2967,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, @@ -3136,8 +3111,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); } @@ -3504,6 +3478,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); @@ -3516,8 +3494,8 @@ gboolean client_focus(ObClient *self) } 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 @@ -3526,8 +3504,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; @@ -3556,6 +3533,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; } @@ -3623,15 +3601,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); @@ -3640,7 +3621,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) @@ -3729,8 +3715,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 */ } }