]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
use the same decision code to focus new windows as for focus cycling or focus fallbac...
[chaz/openbox] / openbox / client.c
index a17f091b317561a3832d7b1613bb1fd13693df77..c6945d231c89216bbf8ff2ae74b29504d59e180a 100644 (file)
@@ -85,6 +85,7 @@ static gboolean client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
 static void client_update_transient_tree(ObClient *self,
                                          ObGroup *oldgroup, ObGroup *newgroup,
+                                         gboolean oldgtran, gboolean newgtran,
                                          ObClient* oldparent,
                                          ObClient *newparent);
 static void client_present(ObClient *self, gboolean here, gboolean raise);
@@ -313,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;
     }
@@ -531,7 +526,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);
@@ -615,14 +619,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);
@@ -1038,7 +1042,7 @@ static void client_get_all(ObClient *self, gboolean real)
 
     client_update_wmhints(self);
     /* this may have already been called from client_update_wmhints */
-    if (self->transient_for == NULL)
+    if (!self->parents && !self->transient_for_group)
         client_update_transient_for(self);
 
     client_get_startup_id(self);
@@ -1102,42 +1106,43 @@ static void client_get_desktop(ObClient *self)
             self->desktop = d;
         ob_debug("client requested desktop 0x%x\n", self->desktop); 
     } else {
-        gboolean trdesk = FALSE;
-
-        if (self->transient_for) {
-            /* if they are all on one desktop, then open it on the
-               same desktop */
-            GSList *it;
-            gboolean first = TRUE;
-            guint all = screen_num_desktops; /* not a valid value */
+        GSList *it;
+        gboolean first = TRUE;
+        guint all = screen_num_desktops; /* not a valid value */
 
-            for (it = self->parents; it; it = g_slist_next(it)) {
-                ObClient *c = it->data;
+        /* if they are all on one desktop, then open it on the
+           same desktop */
+        for (it = self->parents; it; it = g_slist_next(it)) {
+            ObClient *c = it->data;
 
-                if (c->desktop == DESKTOP_ALL) continue;
+            if (c->desktop == DESKTOP_ALL) continue;
 
-                if (first) {
-                    all = c->desktop;
-                    first = FALSE;
-                }
-                else if (all != c->desktop)
-                    all = screen_num_desktops; /* make it invalid */
-            }
-            if (all != screen_num_desktops) {
-                self->desktop = all;
-                trdesk = TRUE;
+            if (first) {
+                all = c->desktop;
+                first = FALSE;
             }
+            else if (all != c->desktop)
+                all = screen_num_desktops; /* make it invalid */
         }
+        if (all != screen_num_desktops) {
+            self->desktop = all;
 
-        if (!trdesk) {
-            /* try get from the startup-notification protocol */
-            if (sn_get_desktop(self->startup_id, &self->desktop)) {
-                if (self->desktop >= screen_num_desktops &&
-                    self->desktop != DESKTOP_ALL)
-                    self->desktop = screen_num_desktops - 1;
-            } else
-                /* defaults to the current desktop */
-                self->desktop = screen_desktop;
+            ob_debug("client desktop set from parents: 0x%x\n",
+                     self->desktop);
+        }
+        /* try get from the startup-notification protocol */
+        else if (sn_get_desktop(self->startup_id, &self->desktop)) {
+            if (self->desktop >= screen_num_desktops &&
+                self->desktop != DESKTOP_ALL)
+                self->desktop = screen_num_desktops - 1;
+            ob_debug("client desktop set from startup-notification: 0x%x\n",
+                     self->desktop);
+        }
+        /* defaults to the current desktop */
+        else {
+            self->desktop = screen_desktop;
+            ob_debug("client desktop set to the current desktop: %d\n",
+                     self->desktop);
         }
     }
 }
@@ -1203,6 +1208,7 @@ void client_update_transient_for(ObClient *self)
 {
     Window t = None;
     ObClient *target = NULL;
+    gboolean trangroup = FALSE;
 
     if (XGetTransientForHint(ob_display, self->window, &t)) {
         if (t != self->window) { /* cant be transient to itself! */
@@ -1214,36 +1220,41 @@ void client_update_transient_for(ObClient *self)
                    a dockapp, for example */
                 target = NULL;
             }
-
-            /* Setting the transient_for to Root is actually illegal, however
-               applications from time have done this to specify transient for
-               their group */
-            if (!target && self->group) {
-                /* not transient to a client, see if it is transient for a
-                   group */
-                if (t == RootWindow(ob_display, ob_screen)) {
-                    /* window is a transient for its group! */
-                    target = OB_TRAN_GROUP;
-                }
-            }
         }
-    } else if (self->transient && self->group)
-        target = OB_TRAN_GROUP;
+
+        /* Setting the transient_for to Root is actually illegal, however
+           applications from time have done this to specify transient for
+           their group */
+        if (!target && self->group && t == RootWindow(ob_display, ob_screen))
+            trangroup = TRUE;
+    } else if (self->group && self->transient)
+        trangroup = TRUE;
 
     client_update_transient_tree(self, self->group, self->group,
-                                 self->transient_for, target);
-    self->transient_for = target;
+                                 self->transient_for_group, trangroup,
+                                 client_direct_parent(self), target);
+    self->transient_for_group = trangroup;
                           
 }
 
 static void client_update_transient_tree(ObClient *self,
                                          ObGroup *oldgroup, ObGroup *newgroup,
+                                         gboolean oldgtran, gboolean newgtran,
                                          ObClient* oldparent,
                                          ObClient *newparent)
 {
     GSList *it, *next;
     ObClient *c;
 
+    g_assert(!oldgtran || oldgroup);
+    g_assert(!newgtran || newgroup);
+    g_assert((!oldgtran && !oldparent) ||
+             (oldgtran && !oldparent) ||
+             (!oldgtran && oldparent));
+    g_assert((!newgtran && !newparent) ||
+             (newgtran && !newparent) ||
+             (!newgtran && newparent));
+
     /* * *
       Group transient windows are not allowed to have other group
       transient windows as their children.
@@ -1251,7 +1262,9 @@ static void client_update_transient_tree(ObClient *self,
 
 
     /* No change has occured */
-    if (oldgroup == newgroup && oldparent == newparent) return;
+    if (oldgroup == newgroup &&
+        oldgtran == newgtran &&
+        oldparent == newparent) return;
 
     /** Remove the client from the transient tree wherever it has changed **/
 
@@ -1263,16 +1276,13 @@ static void client_update_transient_tree(ObClient *self,
        we could have any number of direct parents above up, any of which could
        be transient for the group, and we need to remove it from our children.
     */
-    if (oldparent != newparent &&
-        newparent != NULL && newparent != OB_TRAN_GROUP &&
-        newgroup != NULL && newgroup == oldgroup && client_normal(newparent))
+    if (!oldgtran && oldparent != newparent && newparent != NULL &&
+        newgroup != NULL && newgroup == oldgroup &&
+        client_normal(newparent))
     {
-        ObClient *look = newparent;
-        do {
-            self->transients = g_slist_remove(self->transients, look);
-            look->parents = g_slist_remove(look->parents, self);
-            look = look->transient_for;
-        } while (look != NULL && look != OB_TRAN_GROUP && client_normal(look));
+        ObClient *look = client_search_top_direct_parent(newparent);
+        self->transients = g_slist_remove(self->transients, look);
+        look->parents = g_slist_remove(look->parents, self);
     }
             
 
@@ -1280,9 +1290,8 @@ static void client_update_transient_tree(ObClient *self,
        group, then we need to remove any old group transient windows
        from our children. But if we were already transient for the group, then
        other group transients are not our children. */
-    if ((oldgroup != newgroup ||
-         (newparent == OB_TRAN_GROUP && oldparent != newparent)) &&
-        oldgroup != NULL && oldparent != OB_TRAN_GROUP)
+    if ((oldgroup != newgroup || (newgtran && oldgtran != newgtran)) &&
+        oldgroup != NULL && !oldgtran)
     {
         for (it = self->transients; it; it = next) {
             next = g_slist_next(it);
@@ -1297,15 +1306,12 @@ static void client_update_transient_tree(ObClient *self,
     /* If we used to be transient for a group and now we are not, or we're
        transient for a new group, then we need to remove ourselves from all
        our ex-parents */
-    if (oldparent == OB_TRAN_GROUP && (oldgroup != newgroup ||
-                                       oldparent != newparent))
+    if (oldgtran && (oldgroup != newgroup || oldgtran != newgtran))
     {
         for (it = self->parents; it; it = next) {
             next = g_slist_next(it);
             c = it->data;
-            if ((!c->transient_for || c->transient_for != OB_TRAN_GROUP) &&
-                client_normal(c))
-            {
+            if (!c->transient_for_group && client_normal(c)) {
                 c->transients = g_slist_remove(c->transients, self);
                 self->parents = g_slist_delete_link(self->parents, it);
             }
@@ -1313,8 +1319,8 @@ static void client_update_transient_tree(ObClient *self,
     }
     /* If we used to be transient for a single window and we are no longer
        transient for it, then we need to remove ourself from its children */
-    else if (oldparent != NULL && oldparent != OB_TRAN_GROUP &&
-             oldparent != newparent && client_normal(oldparent))
+    else if (oldparent && oldparent != newparent &&
+             client_normal(oldparent))
     {
         oldparent->transients = g_slist_remove(oldparent->transients, self);
         self->parents = g_slist_remove(self->parents, oldparent);
@@ -1324,15 +1330,11 @@ static void client_update_transient_tree(ObClient *self,
 
     /* If we're now transient for a group and we weren't transient for it
        before then we need to add ourselves to all our new parents */
-    if (newparent == OB_TRAN_GROUP && (oldgroup != newgroup ||
-                                       oldparent != newparent))
+    if (newgtran && (oldgroup != newgroup || oldgtran != newgtran))
     {
         for (it = oldgroup->members; it; it = g_slist_next(it)) {
             c = it->data;
-            if (c != self &&
-                (!c->transient_for ||
-                 c->transient_for != OB_TRAN_GROUP) &&
-                client_normal(c))
+            if (c != self && !c->transient_for_group && client_normal(c))
             {
                 c->transients = g_slist_prepend(c->transients, self);
                 self->parents = g_slist_prepend(self->parents, c);
@@ -1345,8 +1347,7 @@ static void client_update_transient_tree(ObClient *self,
        WARNING: Cyclical transient ness is possible if two windows are
        transient for eachother.
     */
-    else if (newparent != NULL && newparent != OB_TRAN_GROUP &&
-             newparent != oldparent &&
+    else if (newparent && newparent != oldparent &&
              /* don't make ourself its child if it is already our child */
              !client_is_direct_child(self, newparent) &&
              client_normal(newparent))
@@ -1365,15 +1366,14 @@ static void client_update_transient_tree(ObClient *self,
        C is transient for B
        A can't be transient for C or we have a cycle
     */
-    if (oldgroup != newgroup && newgroup != NULL &&
-        newparent != OB_TRAN_GROUP)
+    if (oldgroup != newgroup && newgroup != NULL && !newgtran &&
+        client_normal(self))
     {
         for (it = newgroup->members; it; it = g_slist_next(it)) {
             c = it->data;
-            if (c != self && c->transient_for == OB_TRAN_GROUP &&
+            if (c != self && c->transient_for_group &&
                 /* Don't make it our child if it is already our parent */
-                !client_is_direct_child(c, self) &&
-                client_normal(self))
+                !client_is_direct_child(c, self))
             {
                 self->transients = g_slist_prepend(self->transients, c);
                 c->parents = g_slist_prepend(c->parents, self);
@@ -1572,7 +1572,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)
@@ -1711,12 +1720,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))
@@ -1847,8 +1852,10 @@ void client_update_wmhints(ObClient *self)
             /* Put ourselves into the new group's transient tree, and remove
                ourselves from the old group's */
             client_update_transient_tree(self, oldgroup, self->group,
-                                         self->transient_for,
-                                         self->transient_for);
+                                         self->transient_for_group,
+                                         self->transient_for_group,
+                                         client_direct_parent(self),
+                                         client_direct_parent(self));
 
             /* Lastly, being in a group, or not, can change if the window is
                transient for anything.
@@ -1858,11 +1865,11 @@ void client_update_wmhints(ObClient *self)
                transient for something, even if transient_for was NULL because
                it wasn't in a group before.
 
-               If transient_for was NULL and oldgroup was NULL we can assume
+               If parents was NULL and oldgroup was NULL we can assume
                that when we add the new group, it will become transient for
                something.
 
-               If transient_for was OB_TRAN_GROUP, then it must have already
+               If transient_for_group is TRUE, then it must have already
                had a group. If it is getting a new group, the above call to
                client_update_transient_tree has already taken care of
                everything ! If it is losing all group status then it will
@@ -1870,8 +1877,8 @@ void client_update_wmhints(ObClient *self)
                updated.
             */
             if (self->transient &&
-                ((self->transient_for == NULL && oldgroup == NULL) ||
-                 (self->transient_for == OB_TRAN_GROUP && !self->group)))
+                ((self->parents == NULL && oldgroup == NULL) ||
+                 (self->transient_for_group && !self->group)))
                 client_update_transient_for(self);
         }
 
@@ -2048,18 +2055,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);
             }
@@ -2477,6 +2485,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;
 
@@ -2554,10 +2575,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.. */
 
@@ -2666,9 +2687,61 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
        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_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);
+
     /* 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, 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) {
@@ -2700,19 +2773,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;
@@ -2722,77 +2795,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)) {
@@ -3204,6 +3231,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();
     }
@@ -3570,17 +3600,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), "
@@ -3720,7 +3752,7 @@ guint client_monitor(ObClient *self)
 ObClient *client_direct_parent(ObClient *self)
 {
     if (!self->parents) return NULL;
-    if (self->transient_for == OB_TRAN_GROUP) return NULL;
+    if (self->transient_for_group) return NULL;
     return self->parents->data;
 }                        
 
@@ -3986,6 +4018,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))
This page took 0.045354 seconds and 4 git commands to generate.