]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
better synthetic configurenotify handling. in particular..
[chaz/openbox] / openbox / client.c
index 3abbb7b5f18793fa0e86b04bfe8a3d94553cbe6d..43a283cdd27926cb22e80ec7c13ed70be85e1fde 100644 (file)
@@ -78,6 +78,7 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y);
 static void client_restore_session_state(ObClient *self);
 static void client_restore_session_stacking(ObClient *self);
 static ObAppSettings *client_get_settings_state(ObClient *self);
+static void client_unfocus(ObClient *self);
 
 void client_startup(gboolean reconfig)
 {
@@ -219,13 +220,14 @@ void client_manage(Window window)
 
     grab_server(TRUE);
 
-    /* check if it has already been unmapped by the time we started mapping
+    /* check if it has already been unmapped by the time we started mapping.
        the grab does a sync so we don't have to here */
     if (XCheckTypedWindowEvent(ob_display, window, DestroyNotify, &e) ||
         XCheckTypedWindowEvent(ob_display, window, UnmapNotify, &e))
     {
         XPutBackEvent(ob_display, &e);
 
+        ob_debug("Trying to manage unmapped window. Aborting that.\n");
         grab_server(FALSE);
         return; /* don't manage it */
     }
@@ -267,11 +269,10 @@ void client_manage(Window window)
     self->window = window;
 
     /* non-zero defaults */
-    self->title_count = 1;
     self->wmstate = WithdrawnState; /* make sure it gets updated first time */
     self->layer = -1;
     self->desktop = screen_num_desktops; /* always an invalid value */
-    self->user_time = ~0; /* maximum value, always newer than the real time */
+    self->user_time = client_last_user_time;
 
     client_get_all(self);
     client_restore_session_state(self);
@@ -393,6 +394,8 @@ void client_manage(Window window)
        won't be all wacko!!
        also, this moves the window to the position where it has been placed
     */
+    ob_debug("placing window 0x%x at %d, %d with size %d x %d\n",
+             self->window, newx, newy, self->area.width, self->area.height);
     client_apply_startup_state(self, newx, newy);
 
     keyboard_grab_for_client(self, TRUE);
@@ -411,12 +414,15 @@ void client_manage(Window window)
         else
         {
             /* If time stamp is old, don't steal focus */
-            if (self->user_time && self->user_time < client_last_user_time)
+            if (self->user_time &&
+                !event_time_after(self->user_time, client_last_user_time))
+            {
                 activate = FALSE;
+            }
             /* Don't steal focus from globally active clients.
                I stole this idea from KWin. It seems nice.
              */
-            if (!focus_client->can_focus && focus_client->focus_notify)
+            if (!(focus_client->can_focus || focus_client->focus_notify))
                 activate = FALSE;
         }
 
@@ -449,7 +455,7 @@ 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_showhide(self);
+    client_show(self);
 
     /* use client_focus instead of client_activate cuz client_activate does
        stuff like switch desktops etc and I'm not interested in all that when
@@ -498,29 +504,44 @@ void client_unmanage(ObClient *self)
 
     g_assert(self != NULL);
 
-    keyboard_grab_for_client(self, FALSE);
-    mouse_grab_for_client(self, FALSE);
+    /* update the focus lists */
+    focus_order_remove(self);
+
+    if (focus_client == self) {
+        XEvent e;
+
+        /* focus the last focused window on the desktop, and ignore enter
+           events from the unmap so it doesnt mess with the focus */
+        while (XCheckTypedEvent(ob_display, EnterNotify, &e));
+        /* remove these flags so we don't end up getting focused in the
+           fallback! */
+        self->can_focus = FALSE;
+        self->focus_notify = FALSE;
+        self->modal = FALSE;
+        client_unfocus(self);
+    }
 
     /* potentially fix focusLast */
     if (config_focus_last)
         grab_pointer(TRUE, OB_CURSOR_NONE);
 
+    frame_hide(self->frame);
+    XFlush(ob_display);
+
+    keyboard_grab_for_client(self, FALSE);
+    mouse_grab_for_client(self, FALSE);
+
     /* remove the window from our save set */
     XChangeSaveSet(ob_display, self->window, SetModeDelete);
 
     /* we dont want events no more */
     XSelectInput(ob_display, self->window, NoEventMask);
 
-    frame_hide(self->frame);
-
     client_list = g_list_remove(client_list, self);
     stacking_remove(self);
     g_hash_table_remove(window_map, &self->window);
 
-    /* update the focus lists */
-    focus_order_remove(self);
-
-    /* once the client is out of the list, update the struts to remove it's
+    /* once the client is out of the list, update the struts to remove its
        influence */
     if (STRUT_EXISTS(self->strut))
         screen_update_areas();
@@ -529,20 +550,6 @@ void client_unmanage(ObClient *self)
         Destructor *d = it->data;
         d->func(self, d->data);
     }
-        
-    if (focus_client == self) {
-        XEvent e;
-
-        /* focus the last focused window on the desktop, and ignore enter
-           events from the unmap so it doesnt mess with the focus */
-        while (XCheckTypedEvent(ob_display, EnterNotify, &e));
-        /* remove these flags so we don't end up getting focused in the
-           fallback! */
-        self->can_focus = FALSE;
-        self->focus_notify = FALSE;
-        self->modal = FALSE;
-        client_unfocus(self);
-    }
 
     /* tell our parent(s) that we're gone */
     if (self->transient_for == OB_TRAN_GROUP) { /* transient of group */
@@ -569,34 +576,36 @@ void client_unmanage(ObClient *self)
         self->group = NULL;
     }
 
-    /* give the client its border back */
-    client_toggle_border(self, TRUE);
+    /* restore the window's original geometry so it is not lost */
+    {
+        Rect a = self->area;
+
+        if (self->fullscreen)
+            a = self->pre_fullscreen_area;
+        else if (self->max_horz || self->max_vert) {
+            if (self->max_horz) {
+                a.x = self->pre_max_area.x;
+                a.width = self->pre_max_area.width;
+            }
+            if (self->max_vert) {
+                a.y = self->pre_max_area.y;
+                a.height = self->pre_max_area.height;
+            }
+        }
+
+        /* give the client its border back */
+        client_toggle_border(self, TRUE);
+
+        self->fullscreen = self->max_horz = self->max_vert = FALSE;
+        self->decorations = 0; /* unmanaged windows have no decor */
+
+        client_move_resize(self, a.x, a.y, a.width, a.height);
+    }
 
     /* reparent the window out of the frame, and free the frame */
     frame_release_client(self->frame, self);
     self->frame = NULL;
 
-    /* restore the window's original geometry so it is not lost */
-    if (self->fullscreen)
-        XMoveResizeWindow(ob_display, self->window,
-                          self->pre_fullscreen_area.x,
-                          self->pre_fullscreen_area.y,
-                          self->pre_fullscreen_area.width,
-                          self->pre_fullscreen_area.height);
-    else if (self->max_horz || self->max_vert) {
-        Rect a = self->area;
-        if (self->max_horz) {
-            a.x = self->pre_max_area.x;
-            a.width = self->pre_max_area.width;
-        }
-        if (self->max_vert) {
-            a.y = self->pre_max_area.y;
-            a.height = self->pre_max_area.height;
-        }
-        XMoveResizeWindow(ob_display, self->window,
-                          a.x, a.y, a.width, a.height);
-    }
-     
     if (ob_state() != OB_STATE_EXITING) {
         /* these values should not be persisted across a window
            unmapping/mapping */
@@ -609,7 +618,6 @@ void client_unmanage(ObClient *self)
         XMapWindow(ob_display, self->window);
     }
 
-
     ob_debug("Unmanaged window 0x%lx\n", self->window);
 
     /* free all data allocated in the client struct */
@@ -886,10 +894,9 @@ static void client_toggle_border(ObClient *self, gboolean show)
     if (show) {
         XSetWindowBorderWidth(ob_display, self->window, self->border_width);
 
-        /* move the client so it is back it the right spot _with_ its
-           border! */
-        if (x != oldx || y != oldy)
-            XMoveWindow(ob_display, self->window, x, y);
+        /* 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);
 }
@@ -961,6 +968,7 @@ static void client_get_area(ObClient *self)
     g_assert(ret != BadWindow);
 
     RECT_SET(self->area, wattrib.x, wattrib.y, wattrib.width, wattrib.height);
+    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,
@@ -1642,108 +1650,44 @@ void client_update_wmhints(ObClient *self)
 
 void client_update_title(ObClient *self)
 {
-    GList *it;
-    guint32 nums;
-    guint i;
     gchar *data = NULL;
-    gboolean read_title;
-    gchar *old_title;
 
-    old_title = self->title;
+    g_free(self->title);
      
     /* try netwm */
     if (!PROP_GETS(self->window, net_wm_name, utf8, &data)) {
         /* try old x stuff */
         if (!(PROP_GETS(self->window, wm_name, locale, &data)
               || PROP_GETS(self->window, wm_name, utf8, &data))) {
-            // http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
             if (self->transient) {
+                /*
+                  GNOME alert windows are not given titles:
+                  http://developer.gnome.org/projects/gup/hig/draft_hig_new/windows-alert.html
+                */
                 data = g_strdup("");
-                goto no_number;
             } else
                 data = g_strdup("Unnamed Window");
         }
     }
 
-    if (config_title_number) {
-
-        /* did the title change? then reset the title_count */
-        if (old_title && 0 != strncmp(old_title, data, strlen(data)))
-            self->title_count = 1;
-
-        /* look for duplicates and append a number */
-        nums = 0;
-        for (it = client_list; it; it = g_list_next(it))
-            if (it->data != self) {
-                ObClient *c = it->data;
-
-                if (c->title_count == 1) {
-                    if (!strcmp(c->title, data))
-                        nums |= 1 << c->title_count;
-                } else {
-                    size_t len;
-                    gchar *end;
-
-                    /* find the beginning of our " - [%u]", this relies on
-                     that syntax being used */
-                    end = strrchr(c->title, '-') - 1; 
-                    len = end - c->title;
-                    if (!strncmp(c->title, data, len))
-                        nums |= 1 << c->title_count;
-                }
-            }
-        /* find first free number */
-        for (i = 1; i <= 32; ++i)
-            if (!(nums & (1 << i))) {
-                if (self->title_count == 1 || i == 1)
-                    self->title_count = i;
-                break;
-            }
-        /* dont display the number for the first window */
-        if (self->title_count > 1) {
-            gchar *ndata;
-            ndata = g_strdup_printf("%s - [%u]", data, self->title_count);
-            g_free(data);
-            data = ndata;
-        }
-    } else
-        self->title_count = 1;
-
-no_number:
     PROP_SETS(self->window, net_wm_visible_name, data);
     self->title = data;
 
     if (self->frame)
         frame_adjust_title(self->frame);
 
-    g_free(old_title);
-
     /* update the icon title */
     data = NULL;
     g_free(self->icon_title);
 
-    read_title = TRUE;
     /* try netwm */
     if (!PROP_GETS(self->window, net_wm_icon_name, utf8, &data))
         /* try old x stuff */
-        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data)
-              || PROP_GETS(self->window, wm_icon_name, utf8, &data))) {
+        if (!(PROP_GETS(self->window, wm_icon_name, locale, &data) ||
+              PROP_GETS(self->window, wm_icon_name, utf8, &data)))
             data = g_strdup(self->title);
-            read_title = FALSE;
-        }
-
-    /* append the title count, dont display the number for the first window.
-     * We don't need to check for config_title_number here since title_count
-     * is not set above 1 then. */
-    if (read_title && self->title_count > 1) {
-        gchar *newdata;
-        newdata = g_strdup_printf("%s - [%u]", data, self->title_count);
-        g_free(data);
-        data = newdata;
-    }
 
     PROP_SETS(self->window, net_wm_visible_icon_name, data);
-
     self->icon_title = data;
 }
 
@@ -1925,7 +1869,10 @@ void client_update_user_time(ObClient *self, gboolean new_event)
         if (new_event)
             client_last_user_time = time;
 
-        /*ob_debug("window 0x%x user time %u\n", self->window, time);*/
+        /*
+        ob_debug("window %s user time %u\n", self->title, time);
+        ob_debug("last user time %u\n", client_last_user_time);
+        */
     }
 }
 
@@ -2112,19 +2059,41 @@ gboolean client_should_show(ObClient *self)
     return FALSE;
 }
 
-void client_showhide(ObClient *self)
+void client_show(ObClient *self)
 {
 
     if (client_should_show(self)) {
-        if (!self->frame->visible)
-            frame_show(self->frame);
+        frame_show(self->frame);
     }
-    else if (self->frame->visible) {
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
+void client_hide(ObClient *self)
+{
+    if (!client_should_show(self)) {
         frame_hide(self->frame);
+    }
+
+    /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
+       needs to be in IconicState. This includes when it is on another
+       desktop!
+    */
+    client_change_wm_state(self);
+}
+
+void client_showhide(ObClient *self)
+{
 
-        /* Fall back focus since we're disappearing */
-        if (focus_client == self)
-            client_unfocus(self);
+    if (client_should_show(self)) {
+        frame_show(self->frame);
+    }
+    else {
+        frame_hide(self->frame);
     }
 
     /* According to the ICCCM (sec 4.1.3.1) when a window is not visible, it
@@ -2189,8 +2158,12 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
         pos = TRUE;
     }
 
-    /* if the client didn't get positioned yet, then do so now */
-    if (!pos && (ox != x || oy != y)) {
+    /* if the client didn't get positioned yet, then do so now
+       call client_move even if the window is not being moved anywhere, because
+       when we reparent it and decorate it, it is getting moved and we need to
+       be telling it so with a ConfigureNotify event.
+    */
+    if (!pos) {
         /* use the saved position */
         self->area.x = ox;
         self->area.y = oy;
@@ -2206,76 +2179,20 @@ static void client_apply_startup_state(ObClient *self, gint x, gint y)
     */
 }
 
-void client_configure_full(ObClient *self, ObCorner anchor,
-                           gint x, gint y, gint w, gint h,
-                           gboolean user, gboolean final,
-                           gboolean force_reply)
+void client_try_configure(ObClient *self, ObCorner anchor,
+                          gint *x, gint *y, gint *w, gint *h,
+                          gint *logicalw, gint *logicalh,
+                          gboolean user)
 {
-    gint oldw, oldh;
-    gboolean send_resize_client;
-    gboolean moved = FALSE, resized = FALSE;
-    guint fdecor = self->frame->decorations;
-    gboolean fhorz = self->frame->max_horz;
-    Rect desired_area = {x, y, w, h};
+    Rect desired_area = {*x, *y, *w, *h};
 
     /* 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, TRUE, TRUE, TRUE);
 
-    /* gets the frame's position */
-    frame_client_gravity(self->frame, &x, &y);
-
-    /* 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 that increment etc shit when in fullscreen */
-    } else {
-        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;
-        }
-    }
-
-    /* gets the client's position */
-    frame_frame_gravity(self->frame, &x, &y);
-
-    /* these override the above states! if you cant move you can't move! */
-    if (user) {
-        if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
-            x = self->area.x;
-            y = self->area.y;
-        }
-        if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
-            w = self->area.width;
-            h = self->area.height;
-        }
-    }
-
-    if (!(w == self->area.width && h == self->area.height)) {
+    /* work within the prefered sizes given by the window */
+    if (!(*w == self->area.width && *h == self->area.height)) {
         gint basew, baseh, minw, minh;
 
         /* base size is substituted with min size if not specified */
@@ -2299,83 +2216,161 @@ void client_configure_full(ObClient *self, ObCorner anchor,
            sizes */
 
         /* smaller than min size or bigger than max size? */
-        if (w > self->max_size.width) w = self->max_size.width;
-        if (w < minw) w = minw;
-        if (h > self->max_size.height) h = self->max_size.height;
-        if (h < minh) h = minh;
+        if (*w > self->max_size.width) *w = self->max_size.width;
+        if (*w < minw) *w = minw;
+        if (*h > self->max_size.height) *h = self->max_size.height;
+        if (*h < minh) *h = minh;
 
-        w -= basew;
-        h -= baseh;
+        *w -= basew;
+        *h -= baseh;
 
         /* keep to the increments */
-        w /= self->size_inc.width;
-        h /= self->size_inc.height;
+        *w /= self->size_inc.width;
+        *h /= self->size_inc.height;
 
         /* you cannot resize to nothing */
-        if (basew + w < 1) w = 1 - basew;
-        if (baseh + h < 1) h = 1 - baseh;
+        if (basew + *w < 1) *w = 1 - basew;
+        if (baseh + *h < 1) *h = 1 - baseh;
   
-        /* store the logical size */
-        SIZE_SET(self->logical_size,
-                 self->size_inc.width > 1 ? w : w + basew,
-                 self->size_inc.height > 1 ? h : h + baseh);
+        /* save the logical size */
+        *logicalw = self->size_inc.width > 1 ? *w : *w + basew;
+        *logicalh = self->size_inc.height > 1 ? *h : *h + baseh;
 
-        w *= self->size_inc.width;
-        h *= self->size_inc.height;
+        *w *= self->size_inc.width;
+        *h *= self->size_inc.height;
 
-        w += basew;
-        h += baseh;
+        *w += basew;
+        *h += baseh;
 
         /* adjust the height to match the width for the aspect ratios.
            for this, min size is not substituted for base size ever. */
-        w -= self->base_size.width;
-        h -= self->base_size.height;
+        *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 (*h * self->min_ratio > *w) {
+                    *h = (gint)(*w / self->min_ratio);
 
                     /* you cannot resize to nothing */
-                    if (h < 1) {
-                        h = 1;
-                        w = (gint)(h * self->min_ratio);
+                    if (*h < 1) {
+                        *h = 1;
+                        *w = (gint)(*h * self->min_ratio);
                     }
                 }
             if (self->max_ratio)
-                if (h * self->max_ratio < w) {
-                    h = (gint)(w / 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 (*h < 1) {
+                        *h = 1;
+                        *w = (gint)(*h * self->min_ratio);
                     }
                 }
         }
 
-        w += self->base_size.width;
-        h += self->base_size.height;
+        *w += self->base_size.width;
+        *h += self->base_size.height;
+    }
+
+    /* gets the frame's position */
+    frame_client_gravity(self->frame, x, y);
+
+    /* 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 entering fullscreen */
+    } 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;
+        }
+
+        /* maximizing is not allowed if the user can't move+resize the window
+         */
+    }
+
+    /* gets the client's position */
+    frame_frame_gravity(self->frame, x, y);
+
+    /* these override the above states! if you cant move you can't move! */
+    if (user) {
+        if (!(self->functions & OB_CLIENT_FUNC_MOVE)) {
+            *x = self->area.x;
+            *y = self->area.y;
+        }
+        if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
+            *w = self->area.width;
+            *h = self->area.height;
+        }
     }
 
-    g_assert(w > 0);
-    g_assert(h > 0);
+    g_assert(*w > 0);
+    g_assert(*h > 0);
 
     switch (anchor) {
     case OB_CORNER_TOPLEFT:
         break;
     case OB_CORNER_TOPRIGHT:
-        x -= w - self->area.width;
+        *x -= *w - self->area.width;
         break;
     case OB_CORNER_BOTTOMLEFT:
-        y -= h - self->area.height;
+        *y -= *h - self->area.height;
         break;
     case OB_CORNER_BOTTOMRIGHT:
-        x -= w - self->area.width;
-        y -= h - self->area.height;
+        *x -= *w - self->area.width;
+        *y -= *h - self->area.height;
         break;
     }
+}
+
 
+void client_configure_full(ObClient *self, ObCorner anchor,
+                           gint x, gint y, gint w, gint h,
+                           gboolean user, gboolean final,
+                           gboolean force_reply)
+{
+    gint oldw, oldh, oldrx, oldry;
+    gboolean send_resize_client;
+    gboolean moved = FALSE, resized = FALSE, rootmoved = FALSE;
+    guint fdecor = self->frame->decorations;
+    gboolean fhorz = self->frame->max_horz;
+    gint logicalw, logicalh;
+
+    /* find the new x, y, width, and height (and logical size) */
+    client_try_configure(self, anchor, &x, &y, &w, &h,
+                         &logicalw, &logicalh, user);
+
+    /* set the logical size if things changed */
+    if (!(w == self->area.width && h == self->area.height))
+        SIZE_SET(self->logical_size, logicalw, logicalh);
+
+    /* 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;
 
@@ -2394,35 +2389,45 @@ void client_configure_full(ObClient *self, ObCorner anchor,
     if (send_resize_client && user && (w > oldw || h > oldh))
         XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh));
 
-    /* move/resize the frame to match the request */
-    if (self->frame) {
-        if (self->decorations != fdecor || self->max_horz != fhorz)
-            moved = resized = TRUE;
-
-        if (moved || resized)
-            frame_adjust_area(self->frame, moved, resized, FALSE);
-
-        if (!resized && (force_reply || ((!user && moved) || (user && final))))
-        {
-            XEvent event;
-            event.type = ConfigureNotify;
-            event.xconfigure.display = ob_display;
-            event.xconfigure.event = self->window;
-            event.xconfigure.window = self->window;
-
-            /* root window real coords */
-            event.xconfigure.x = self->frame->area.x + self->frame->size.left -
-                self->border_width;
-            event.xconfigure.y = self->frame->area.y + self->frame->size.top -
-                self->border_width;
-            event.xconfigure.width = w;
-            event.xconfigure.height = h;
-            event.xconfigure.border_width = 0;
-            event.xconfigure.above = self->frame->plate;
-            event.xconfigure.override_redirect = FALSE;
-            XSendEvent(event.xconfigure.display, event.xconfigure.window,
-                       FALSE, StructureNotifyMask, &event);
-        }
+    /* find the frame's dimensions and move/resize it */
+    if (self->decorations != fdecor || self->max_horz != fhorz)
+        moved = resized = TRUE;
+    if (moved || resized)
+        frame_adjust_area(self->frame, moved, resized, FALSE);
+
+    /* find the client's position relative to the root window */
+    oldrx = self->root_pos.x;
+    oldry = self->root_pos.y;
+    rootmoved = (oldrx != (self->frame->area.x + self->frame->size.left -
+                           self->border_width) ||
+                 oldry != (self->frame->area.y + self->frame->size.top -
+                           self->border_width));
+
+    if (force_reply || ((!user || (user && final)) && rootmoved))
+    {
+        XEvent event;
+
+        POINT_SET(self->root_pos,
+                  self->frame->area.x + self->frame->size.left -
+                  self->border_width,
+                  self->frame->area.y + self->frame->size.top -
+                  self->border_width);
+
+        event.type = ConfigureNotify;
+        event.xconfigure.display = ob_display;
+        event.xconfigure.event = self->window;
+        event.xconfigure.window = self->window;
+
+        /* root window real coords */
+        event.xconfigure.x = self->root_pos.x;
+        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.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 */
@@ -2499,10 +2504,10 @@ static void client_iconify_recursive(ObClient *self,
         ob_debug("%sconifying window: 0x%lx\n", (iconic ? "I" : "Uni"),
                  self->window);
 
-        self->iconic = iconic;
-
         if (iconic) {
             if (self->functions & OB_CLIENT_FUNC_ICONIFY) {
+                self->iconic = iconic;
+
                 /* update the focus lists.. iconic windows go to the bottom of
                    the list, put the new iconic window at the 'top of the
                    bottom'. */
@@ -2511,6 +2516,8 @@ static void client_iconify_recursive(ObClient *self,
                 changed = TRUE;
             }
         } else {
+            self->iconic = iconic;
+
             if (curdesk)
                 client_set_desktop(self, screen_desktop, FALSE);
 
@@ -2999,11 +3006,6 @@ gboolean client_focus(ObClient *self)
     /* choose the correct target */
     self = client_focus_target(self);
 
-#if 0
-    if (!client_validate(self))
-        return FALSE;
-#endif
-
     if (!client_can_focus(self)) {
         if (!self->frame->visible) {
             /* update the focus lists */
@@ -3015,14 +3017,7 @@ gboolean client_focus(ObClient *self)
     ob_debug("Focusing client \"%s\" at time %u\n", self->title, event_curtime);
 
     if (self->can_focus) {
-        /* RevertToPointerRoot causes much more headache than RevertToNone, so
-           I choose to use it always, hopefully to find errors quicker, if any
-           are left. (I hate X. I hate focus events.)
-           
-           Update: Changing this to RevertToNone fixed a bug with mozilla (bug
-           #799. So now it is RevertToNone again.
-        */
-        XSetInputFocus(ob_display, self->window, RevertToNone,
+        XSetInputFocus(ob_display, self->window, RevertToPointerRoot,
                        event_curtime);
     }
 
@@ -3057,17 +3052,17 @@ gboolean client_focus(ObClient *self)
 /* Used when the current client is closed or otherwise hidden, focus_last will
    then prevent focus from going to the mouse pointer
 */
-void client_unfocus(ObClient *self)
+static void client_unfocus(ObClient *self)
 {
     if (focus_client == self) {
 #ifdef DEBUG_FOCUS
         ob_debug("client_unfocus for %lx\n", self->window);
 #endif
-        focus_fallback(OB_FOCUS_FALLBACK_CLOSED);
+        focus_fallback(FALSE);
     }
 }
 
-void client_activate(ObClient *self, gboolean here, gboolean user, Time time)
+void client_activate(ObClient *self, gboolean here, gboolean user)
 {
     /* XXX do some stuff here if user is false to determine if we really want
        to activate it or not (a parent or group member is currently
@@ -3075,11 +3070,13 @@ void client_activate(ObClient *self, gboolean here, gboolean user, Time time)
     */
     ob_debug("Want to activate window 0x%x with time %u (last time %u), "
              "source=%s\n",
-             self->window, time, client_last_user_time,
+             self->window, event_curtime, client_last_user_time,
              (user ? "user" : "application"));
-    if (!user && time && time < client_last_user_time)
+    if (!user && event_curtime &&
+        !event_time_after(event_curtime, client_last_user_time))
+    {
         client_hilite(self, TRUE);
-    else {
+    else {
         if (client_normal(self) && screen_showing_desktop)
             screen_show_desktop(FALSE);
         if (self->iconic)
This page took 0.048405 seconds and 4 git commands to generate.