X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=e9a2adf5cfe6df7eb83a576aea2e08babc72be73;hb=4eb9a0c59efb6bfd598e35fe692e6b4b994e499c;hp=e64fd49c2e0b4a890f852cca627f40e5fabeae85;hpb=64adc0eeba598cb1469b2140777fba30e3053f0e;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index e64fd49c..e9a2adf5 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -42,6 +42,7 @@ #include "obrender/render.h" #include "gettext.h" #include "obt/display.h" +#include "obt/xqueue.h" #include "obt/prop.h" #ifdef HAVE_UNISTD_H @@ -203,14 +204,12 @@ void client_manage(Window window, ObPrompt *prompt) ObAppSettings *settings; gboolean transient = FALSE; Rect place; - Time launch_time, map_time; + Time launch_time; guint32 user_time; gboolean obplaced; ob_debug("Managing window: 0x%lx", window); - map_time = event_get_server_time(); - /* choose the events we want to receive on the CLIENT window (ObPrompt windows can request events too) */ attrib_set.event_mask = CLIENT_EVENTMASK | @@ -272,7 +271,7 @@ void client_manage(Window window, ObPrompt *prompt) launch_time = sn_app_started(self->startup_id, self->class, self->name); if (!OBT_PROP_GET32(self->window, NET_WM_USER_TIME, CARDINAL, &user_time)) - user_time = map_time; + user_time = event_time(); /* do this after we have a frame.. it uses the frame to help determine the WM_STATE to apply. */ @@ -295,7 +294,7 @@ void client_manage(Window window, ObPrompt *prompt) /* this checks for focus=false for the window */ (!settings || settings->focus != 0) && focus_valid_target(self, self->desktop, - FALSE, FALSE, TRUE, FALSE, FALSE, + FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, settings->focus == 1)) { activate = TRUE; @@ -335,6 +334,8 @@ void client_manage(Window window, ObPrompt *prompt) /* watch for buggy apps that ask to be placed at (0,0) when there is a strut there */ if (!obplaced && place.x == 0 && place.y == 0 && + /* non-normal windows are allowed */ + client_normal(self) && /* oldschool fullscreen windows are allowed */ !client_is_oldfullscreen(self, &place)) { @@ -439,7 +440,7 @@ void client_manage(Window window, ObPrompt *prompt) ob_debug_type(OB_DEBUG_FOCUS, "Going to try activate new window? %s", activate ? "yes" : "no"); if (activate) { - activate = client_can_steal_focus(self, map_time, launch_time); + activate = client_can_steal_focus(self, event_time(), launch_time); if (!activate) { /* if the client isn't stealing focus, then hilite it so the user @@ -723,8 +724,9 @@ static gboolean client_can_steal_focus(ObClient *self, Time steal_time, if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL) && /* the timestamp is from before you changed desktops */ - launch_time && screen_desktop_user_time && - !event_time_after(launch_time, screen_desktop_user_time)) + (!launch_time || + (screen_desktop_user_time && + !event_time_after(launch_time, screen_desktop_user_time)))) { steal = FALSE; ob_debug_type(OB_DEBUG_FOCUS, @@ -1549,7 +1551,13 @@ void client_update_sync_request_counter(ObClient *self) if (OBT_PROP_GET32(self->window, NET_WM_SYNC_REQUEST_COUNTER, CARDINAL,&i)) { + XSyncValue val; + self->sync_counter = i; + + /* this must be set when managing a new window according to EWMH */ + XSyncIntToValue(&val, 0); + XSyncSetCounter(obt_display, self->sync_counter, val); } else self->sync_counter = None; } @@ -1761,9 +1769,10 @@ void client_setup_decor_and_functions(ObClient *self, gboolean reconfig) } 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 */ + /* once upon a time you couldn't resize maximized windows, that is not + the case any more though ! + + but do kill the handle on fully maxed windows */ self->decorations &= ~(OB_FRAME_DECOR_HANDLE | OB_FRAME_DECOR_GRIPS); } @@ -2040,7 +2049,7 @@ void client_update_strut(ObClient *self) if (!got && OBT_PROP_GETA32(self->window, NET_WM_STRUT, CARDINAL, &data, &num)) { if (num == 4) { - Rect const *a; + const Rect *a; got = TRUE; @@ -2465,10 +2474,10 @@ gboolean client_has_parent(ObClient *self) return self->parents != NULL; } -gboolean client_is_oldfullscreen(const ObClient const *self, - const Rect const *area) +gboolean client_is_oldfullscreen(const ObClient *self, + const Rect *area) { - Rect const *monitor, *allmonitors; + const Rect *monitor, *allmonitors; /* No decorations and fills the monitor = oldskool fullscreen. But not for maximized windows. @@ -2486,10 +2495,6 @@ gboolean client_is_oldfullscreen(const ObClient const *self, static ObStackingLayer calc_layer(ObClient *self) { ObStackingLayer l; - Rect const *monitor, *allmonitors; - - monitor = screen_physical_area_monitor(client_monitor(self)); - allmonitors = screen_physical_area_all_monitors(); if (self->type == OB_CLIENT_TYPE_DESKTOP) l = OB_STACKING_LAYER_DESKTOP; @@ -2839,7 +2844,7 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, /* set the size and position if fullscreen */ if (self->fullscreen) { - Rect const *a; + const Rect *a; guint i; i = screen_find_monitor(&desired); @@ -2885,11 +2890,11 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, through this code */ { gint basew, baseh, minw, minh; - gint incw, inch; + gint incw, inch, maxw, maxh; 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; + incw = self->size_inc.width; + inch = 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) ? @@ -2925,6 +2930,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *w -= basew; *h -= baseh; + /* the sizes to used for maximized */ + maxw = *w; + maxh = *h; + /* keep to the increments */ *w /= incw; *h /= inch; @@ -2940,6 +2949,10 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h, *w *= incw; *h *= inch; + /* if maximized/fs then don't use the size increments */ + if (self->fullscreen || self->max_horz) *w = maxw; + if (self->fullscreen || self->max_vert) *h = maxh; + *w += basew; *h += baseh; @@ -3077,16 +3090,18 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, When user = FALSE, then the request is coming from the application itself, and we are more strict about when to send a synthetic ConfigureNotify. We strictly follow the rules of the ICCCM sec 4.1.5 - in this case (if force_reply is true) + in this case (or send one if force_reply is true) When user = TRUE, then the request is coming from "us", like when we maximize a window or something. In this case we are more lenient. We used to follow the same rules as above, but _Java_ Swing can't handle this. So just to appease Swing, when user = TRUE, we always send a synthetic ConfigureNotify to give the window its root coordinates. + Lastly, if force_reply is TRUE, we always send a + ConfigureNotify, which is needed during a resize with XSYNCronization. */ if ((!user && !resized && (rootmoved || force_reply)) || - (user && final && rootmoved)) + (user && ((!resized && force_reply) || (final && rootmoved)))) { XEvent event; @@ -3127,11 +3142,16 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, /* if it moved between monitors, then this can affect the stacking layer of this window or others - for fullscreen windows. also if it changed to/from oldschool fullscreen then its layer may - change */ - if (screen_find_monitor(&self->frame->area) != - screen_find_monitor(&oldframe) || - (final && (client_is_oldfullscreen(self, &oldclient) != - client_is_oldfullscreen(self, &self->area)))) + change + + watch out tho, don't try change stacking stuff if the window is no + longer being managed ! + */ + if (self->managed && + (screen_find_monitor(&self->frame->area) != + screen_find_monitor(&oldframe) || + (final && (client_is_oldfullscreen(self, &oldclient) != + client_is_oldfullscreen(self, &self->area))))) { client_calc_layer(self); } @@ -3194,6 +3214,11 @@ void client_fullscreen(ObClient *self, gboolean fs) ob_debug("Window %s going fullscreen (%d)", self->title, self->fullscreen); + if (fs) { + /* make sure the window is on some monitor */ + client_find_onscreen(self, &x, &y, w, h, FALSE); + } + client_setup_decor_and_functions(self, FALSE); client_move_resize(self, x, y, w, h); @@ -3336,6 +3361,11 @@ void client_maximize(ObClient *self, gboolean max, gint dir) if (dir == 0 || dir == 2) /* vert */ self->max_vert = max; + if (max) { + /* make sure the window is on some monitor */ + client_find_onscreen(self, &x, &y, w, h, FALSE); + } + client_change_state(self); /* change the state hints on the client */ client_setup_decor_and_functions(self, FALSE); @@ -3396,7 +3426,7 @@ void client_close(ObClient *self) else { /* request the client to close with WM_DELETE_WINDOW */ OBT_PROP_MSG_TO(self->window, self->window, WM_PROTOCOLS, - OBT_PROP_ATOM(WM_DELETE_WINDOW), event_curtime, + OBT_PROP_ATOM(WM_DELETE_WINDOW), event_time(), 0, 0, 0, NoEventMask); /* we're trying to close the window, so see if it is responding. if it @@ -3614,36 +3644,31 @@ ObClient *client_search_modal_child(ObClient *self) return NULL; } -static gboolean client_validate_unmap(ObClient *self, int n) -{ - XEvent e; - gboolean ret = TRUE; - - if (XCheckTypedWindowEvent(obt_display, self->window, UnmapNotify, &e)) { - if (n < self->ignore_unmaps) // ignore this one, but look for more - ret = client_validate_unmap(self, n+1); - else - ret = FALSE; // the window is going to become unmanaged - - /* put them back on the event stack so they end up in the same order */ - XPutBackEvent(obt_display, &e); - } +struct ObClientFindDestroyUnmap { + Window window; + gint ignore_unmaps; +}; - return ret; +static gboolean find_destroy_unmap(XEvent *e, gpointer data) +{ + struct ObClientFindDestroyUnmap *find = data; + if (e->type == DestroyNotify) + return e->xdestroywindow.window == find->window; + if (e->type == UnmapNotify && e->xunmap.window == find->window) + /* ignore the first $find->ignore_unmaps$ many unmap events */ + return --find->ignore_unmaps < 0; + return FALSE; } gboolean client_validate(ObClient *self) { - XEvent e; + struct ObClientFindDestroyUnmap find; XSync(obt_display, FALSE); /* get all events on the server */ - if (XCheckTypedWindowEvent(obt_display, self->window, DestroyNotify, &e)) { - XPutBackEvent(obt_display, &e); - return FALSE; - } - - if (!client_validate_unmap(self, 0)) + find.window = self->window; + find.ignore_unmaps = self->ignore_unmaps; + if (xqueue_exists_local(find_destroy_unmap, &find)) return FALSE; return TRUE; @@ -3835,6 +3860,8 @@ gboolean client_can_focus(ObClient *self) gboolean client_focus(ObClient *self) { + if (!client_validate(self)) return FALSE; + /* 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); @@ -3850,7 +3877,7 @@ gboolean client_focus(ObClient *self) ob_debug_type(OB_DEBUG_FOCUS, "Focusing client \"%s\" (0x%x) at time %u", - self->title, self->window, event_curtime); + self->title, self->window, event_time()); /* if using focus_delay, stop the timer now so that focus doesn't go moving on us */ @@ -3862,7 +3889,7 @@ gboolean client_focus(ObClient *self) /* This can cause a BadMatch error with CurrentTime, or if an app passed in a bad time for _NET_WM_ACTIVE_WINDOW. */ XSetInputFocus(obt_display, self->window, RevertToPointerRoot, - event_curtime); + event_time()); } if (self->focus_notify) { @@ -3873,7 +3900,7 @@ gboolean client_focus(ObClient *self) ce.xclient.window = self->window; ce.xclient.format = 32; ce.xclient.data.l[0] = OBT_PROP_ATOM(WM_TAKE_FOCUS); - ce.xclient.data.l[1] = event_curtime; + ce.xclient.data.l[1] = event_time(); ce.xclient.data.l[2] = 0l; ce.xclient.data.l[3] = 0l; ce.xclient.data.l[4] = 0l; @@ -3921,7 +3948,7 @@ void client_activate(ObClient *self, gboolean desktop, if ((user && (desktop || self->desktop == DESKTOP_ALL || self->desktop == screen_desktop)) || - client_can_steal_focus(self, event_curtime, CurrentTime)) + client_can_steal_focus(self, event_time(), CurrentTime)) { client_present(self, here, raise, unshade); }