]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
save the focus_client when falling back, so we don't actually refocus it when we...
[chaz/openbox] / openbox / client.c
index dc61deba21e7f332834faf15dddbdd908550f944..b49d3ff8654e111027b9cd31e5a1dc5b1d999007 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)
 {
@@ -268,7 +269,7 @@ void client_manage(Window window)
 
     /* non-zero defaults */
     self->title_count = 1;
-    self->wmstate = NormalState;
+    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 */
@@ -498,29 +499,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 +545,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 */
@@ -639,7 +641,7 @@ static ObAppSettings *client_get_settings_state(ObClient *self)
     GSList *it;
 
     for (it = config_per_app_settings; it; it = g_slist_next(it)) {
-        ObAppSettings *app;
+        ObAppSettings *app = it->data;
         
         if ((app->name && !app->class && !strcmp(app->name, self->name))
             || (app->class && !app->name && !strcmp(app->class, self->class))
@@ -1956,8 +1958,6 @@ static void client_change_state(ObClient *self)
     gulong netstate[11];
     guint num;
 
-    client_change_wm_state(self);
-
     num = 0;
     if (self->modal)
         netstate[num++] = prop_atoms.net_wm_state_modal;
@@ -2118,10 +2118,9 @@ void client_showhide(ObClient *self)
 {
 
     if (client_should_show(self)) {
-        if (!self->frame->visible)
-            frame_show(self->frame);
+        frame_show(self->frame);
     }
-    else if (self->frame->visible) {
+    else {
         frame_hide(self->frame);
 
         /* Fall back focus since we're disappearing */
@@ -2208,17 +2207,12 @@ 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
@@ -2226,7 +2220,7 @@ void client_configure_full(ObClient *self, ObCorner anchor,
     frame_adjust_area(self->frame, TRUE, TRUE, TRUE);
 
     /* gets the frame's position */
-    frame_client_gravity(self->frame, &x, &y);
+    frame_client_gravity(self->frame, x, y);
 
     /* these positions are frame positions, not client positions */
 
@@ -2238,10 +2232,10 @@ void client_configure_full(ObClient *self, ObCorner anchor,
         i = screen_find_monitor(&desired_area);
         a = screen_physical_area_monitor(i);
 
-        x = a->x;
-        y = a->y;
-        w = a->width;
-        h = a->height;
+        *x = a->x;
+        *y = a->y;
+        *w = a->width;
+        *h = a->height;
 
         user = FALSE; /* ignore that increment etc shit when in fullscreen */
     } else {
@@ -2253,31 +2247,31 @@ void client_configure_full(ObClient *self, ObCorner anchor,
 
         /* 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;
+            *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;
+            *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);
+    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;
+            *x = self->area.x;
+            *y = self->area.y;
         }
         if (!(self->functions & OB_CLIENT_FUNC_RESIZE)) {
-            w = self->area.width;
-            h = self->area.height;
+            *w = self->area.width;
+            *h = self->area.height;
         }
     }
 
-    if (!(w == self->area.width && h == self->area.height)) {
+    if (!(*w == self->area.width && *h == self->area.height)) {
         gint basew, baseh, minw, minh;
 
         /* base size is substituted with min size if not specified */
@@ -2301,83 +2295,104 @@ 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;
     }
 
-    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;
+    gboolean send_resize_client;
+    gboolean moved = FALSE, resized = 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 */
+    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;
 
@@ -2501,10 +2516,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'. */
@@ -2513,6 +2528,8 @@ static void client_iconify_recursive(ObClient *self,
                 changed = TRUE;
             }
         } else {
+            self->iconic = iconic;
+
             if (curdesk)
                 client_set_desktop(self, screen_desktop, FALSE);
 
@@ -2633,6 +2650,7 @@ void client_shade(ObClient *self, gboolean shade)
 
     self->shaded = shade;
     client_change_state(self);
+    client_change_wm_state(self); /* the window is being hidden/shown */
     /* resize the frame to just the titlebar */
     frame_adjust_area(self->frame, FALSE, FALSE, FALSE);
 }
@@ -3016,14 +3034,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);
     }
 
@@ -3058,13 +3069,13 @@ 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);
     }
 }
 
This page took 0.032519 seconds and 4 git commands to generate.