X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fclient.c;h=ae97606d5e3fe82f5a3fd4b662f9b87be7edc341;hb=b9b0284e3e4651618039e9a25aa7056f9596cb01;hp=e64fd49c2e0b4a890f852cca627f40e5fabeae85;hpb=64adc0eeba598cb1469b2140777fba30e3053f0e;p=chaz%2Fopenbox diff --git a/openbox/client.c b/openbox/client.c index e64fd49c..ae97606d 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; } @@ -2040,7 +2048,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 +2473,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 +2494,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 +2843,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); @@ -3084,9 +3088,11 @@ void client_configure(ObClient *self, gint x, gint y, gint w, gint h, 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 +3133,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 +3205,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 +3352,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 +3417,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 +3635,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 +struct ObClientFindDestroyUnmap { + Window window; + gint ignore_unmaps; +}; - /* put them back on the event stack so they end up in the same order */ - XPutBackEvent(obt_display, &e); - } - - 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 +3851,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 +3868,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 +3880,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 +3891,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 +3939,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); }