]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
not much.. some debugs and a nicer if statement
[chaz/openbox] / openbox / client.c
index 6b8635be8eaa9d69c40930f6dca485ce4cf18e01..23ebf31c8c0ba116abacdea289c73e55f19fcd2b 100644 (file)
@@ -347,8 +347,8 @@ void client_manage(Window window)
 
         /* make sure the window is visible. */
         client_find_onscreen(self, &newx, &newy,
-                             self->frame->area.width,
-                             self->frame->area.height,
+                             self->area.width,
+                             self->area.height,
                              /* non-normal clients has less rules, and
                                 windows that are being restored from a
                                 session do also. we can assume you want
@@ -381,8 +381,10 @@ void client_manage(Window window)
             focus_client->user_time : CurrentTime;
 
         /* This is focus stealing prevention */
-        ob_debug("Want to focus new window 0x%x with time %u (last time %u)\n",
-                 self->window, self->user_time, last_time);
+        ob_debug_type(OB_DEBUG_FOCUS,
+                      "Want to focus new window 0x%x with time %u "
+                      "(last time %u)\n",
+                      self->window, self->user_time, last_time);
 
         /* if it's on another desktop */
         if (!(self->desktop == screen_desktop || self->desktop == DESKTOP_ALL)
@@ -391,31 +393,38 @@ void client_manage(Window window)
             !event_time_after(self->user_time, screen_desktop_user_time))
         {
             activate = FALSE;
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Not focusing the window because its on another "
+                          "desktop\n");
         }
-        /* If nothing is focused, or a parent was focused, then focus this
-           always
-        */
-        else if (!focus_client || client_search_focus_parent(self) != NULL)
-            activate = TRUE;
-        else
+        /* If something is focused, and it's not our parent... */
+        else if (focus_client && client_search_focus_parent(self) == NULL)
         {
             /* If time stamp is old, don't steal focus */
             if (self->user_time && last_time &&
                 !event_time_after(self->user_time, last_time))
             {
                 activate = FALSE;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because the time is "
+                              "too old\n");
             }
             /* 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;
+                ob_debug_type(OB_DEBUG_FOCUS,
+                              "Not focusing the window because a globally "
+                              "active client has focus\n");
+            }
         }
 
         if (!activate) {
-            ob_debug("Focus stealing prevention activated for %s with time %u "
-                     "(last time %u)\n",
-                     self->title, self->user_time, last_time);
+            ob_debug_type(OB_DEBUG_FOCUS,
+                          "Focus stealing prevention activated for %s with "
+                          "time %u (last time %u)\n",
+                          self->title, self->user_time, last_time);
             /* if the client isn't focused, then hilite it so the user
                knows it is there */
             client_hilite(self, TRUE);
@@ -742,8 +751,8 @@ void client_move_onscreen(ObClient *self, gboolean rude)
     gint x = self->area.x;
     gint y = self->area.y;
     if (client_find_onscreen(self, &x, &y,
-                             self->frame->area.width,
-                             self->frame->area.height, rude)) {
+                             self->area.width,
+                             self->area.height, rude)) {
         client_move(self, x, y);
     }
 }
@@ -751,59 +760,94 @@ void client_move_onscreen(ObClient *self, gboolean rude)
 gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
                               gboolean rude)
 {
-    Rect *a;
+    Rect *mon_a, *all_a;
     gint ox = *x, oy = *y;
+    gboolean rudel = rude, ruder = rude, rudet = rude, rudeb = rude;
+    gint fw, fh;
 
-    /* XXX figure out if it is on screen now, and be rude if it is */
+    all_a = screen_area(self->desktop);
+    mon_a = screen_area_monitor(self->desktop, client_monitor(self));
 
     /* get where the frame would be */
     frame_client_gravity(self->frame, x, y, w, h);
 
-    /* XXX watch for xinerama dead areas */
+    /* get the requested size of the window with decorations */
+    fw = self->frame->size.left + w + self->frame->size.right;
+    fh = self->frame->size.top + h + self->frame->size.bottom;
+
     /* This makes sure windows aren't entirely outside of the screen so you
        can't see them at all.
        It makes sure 10% of the window is on the screen at least. At don't let
        it move itself off the top of the screen, which would hide the titlebar
        on you. (The user can still do this if they want too, it's only limiting
        the application.
+
+       XXX watch for xinerama dead areas...
     */
     if (client_normal(self)) {
-        a = screen_area(self->desktop);
-        if (!self->strut.right &&
-            *x + self->frame->area.width/10 >= a->x + a->width - 1)
-            *x = a->x + a->width - self->frame->area.width/10;
-        if (!self->strut.bottom &&
-            *y + self->frame->area.height/10 >= a->y + a->height - 1)
-            *y = a->y + a->height - self->frame->area.height/10;
-        if (!self->strut.left && *x + self->frame->area.width*9/10 - 1 < a->x)
-            *x = a->x - self->frame->area.width*9/10;
-        if (!self->strut.top && *y + self->frame->area.height*9/10 - 1 < a->y)
-            *y = a->y - self->frame->area.width*9/10;
-    }
-
-    /* This here doesn't let windows even a pixel outside the screen,
-     * when called from client_manage, programs placing themselves are
+        if (!self->strut.right && *x + fw/10 >= all_a->x + all_a->width - 1)
+            *x = all_a->x + all_a->width - fw/10;
+        if (!self->strut.bottom && *y + fh/10 >= all_a->y + all_a->height - 1)
+            *y = all_a->y + all_a->height - fh/10;
+        if (!self->strut.left && *x + fw*9/10 - 1 < all_a->x)
+            *x = all_a->x - fw*9/10;
+        if (!self->strut.top && *y + fh*9/10 - 1 < all_a->y)
+            *y = all_a->y - fw*9/10;
+    }
+
+    /* If rudeness wasn't requested, then figure out of the client is currently
+       entirely on the screen. If it is, and the position isn't changing by
+       request, and it is enlarging, then be rude even though it wasn't
+       requested */
+    if (!rude) {
+        Point oldtl, oldtr, oldbl, oldbr;
+        Point newtl, newtr, newbl, newbr;
+        gboolean stationary;
+
+        POINT_SET(oldtl, self->frame->area.x, self->frame->area.y);
+        POINT_SET(oldbr, self->frame->area.x + self->frame->area.width - 1,
+                  self->frame->area.y + self->frame->area.height - 1);
+        POINT_SET(oldtr, oldbr.x, oldtl.y);
+        POINT_SET(oldbl, oldtl.x, oldbr.y);
+
+        POINT_SET(newtl, *x, *y);
+        POINT_SET(newbr, *x + fw - 1, *y + fh - 1);
+        POINT_SET(newtr, newbr.x, newtl.y);
+        POINT_SET(newbl, newtl.x, newbr.y);
+
+        /* is it moving or just resizing from some corner? */
+        stationary = (POINT_EQUAL(oldtl, newtl) || POINT_EQUAL(oldtr, newtr) ||
+                      POINT_EQUAL(oldbl, newbl) || POINT_EQUAL(oldbr, newbr));
+
+        /* if left edge is growing */
+        if (stationary && newtl.x < oldtl.x)
+            rudel = TRUE;
+        /* if right edge is growing */
+        if (stationary && newtr.x > oldtr.x)
+            ruder = TRUE;
+        /* if top edge is growing */
+        if (stationary && newtl.y < oldtl.y)
+            rudet = TRUE;
+        /* if bottom edge is growing */
+        if (stationary && newbl.y > oldbl.y)
+            rudeb = TRUE;
+    }
+
+    /* This here doesn't let windows even a pixel outside the struts/screen.
+     * When called from client_manage, programs placing themselves are
      * forced completely onscreen, while things like
      * xterm -geometry resolution-width/2 will work fine. Trying to
      * place it completely offscreen will be handled in the above code.
      * Sorry for this confused comment, i am tired. */
-    if (rude) {
-        /* avoid the xinerama monitor divide while we're at it,
-         * remember to fix the placement stuff to avoid it also and
-         * then remove this XXX */
-        a = screen_area_monitor(self->desktop, client_monitor(self));
-        /* dont let windows map into the strut unless they
-           are bigger than the available area */
-        if (w <= a->width) {
-            if (!self->strut.left && *x < a->x) *x = a->x;
-            if (!self->strut.right && *x + w > a->x + a->width)
-                *x = a->x + a->width - w;
-        }
-        if (h <= a->height) {
-            if (!self->strut.top && *y < a->y) *y = a->y;
-            if (!self->strut.bottom && *y + h > a->y + a->height)
-                *y = a->y + a->height - h;
-        }
+    if (fw <= mon_a->width) {
+        if (rudel && !self->strut.left && *x < mon_a->x) *x = mon_a->x;
+        if (ruder && !self->strut.right && *x + fw > mon_a->x + mon_a->width)
+            *x = mon_a->x + mon_a->width - fw;
+    }
+    if (fh <= mon_a->height) {
+        if (rudet && !self->strut.top && *y < mon_a->y) *y = mon_a->y;
+        if (rudeb && !self->strut.bottom && *y + fh > mon_a->y + mon_a->height)
+            *y = mon_a->y + mon_a->height - fh;
     }
 
     /* get where the client should be */
@@ -1587,6 +1631,8 @@ void client_update_wmhints(ObClient *self)
     self->can_focus = TRUE;
   
     if ((hints = XGetWMHints(ob_display, self->window)) != NULL) {
+        gboolean ur;
+
         if (hints->flags & InputHint)
             self->can_focus = hints->input;
 
@@ -1596,6 +1642,13 @@ void client_update_wmhints(ObClient *self)
             if (hints->flags & StateHint)
                 self->iconic = hints->initial_state == IconicState;
 
+        ur = self->urgent;
+        self->urgent = (hints->flags & XUrgencyHint);
+        if (self->urgent && !ur)
+            client_hilite(self, TRUE);
+        else if (!self->urgent && ur && self->demands_attention)
+            client_hilite(self, FALSE);
+
         if (!(hints->flags & WindowGroupHint))
             hints->window_group = None;
 
@@ -2154,6 +2207,12 @@ gboolean client_normal(ObClient *self) {
               self->type == OB_CLIENT_TYPE_SPLASH);
 }
 
+gboolean client_application(ObClient *self)
+{
+    return (self->type == OB_CLIENT_TYPE_NORMAL ||
+            self->type == OB_CLIENT_TYPE_DIALOG);
+}
+
 static void client_apply_startup_state(ObClient *self, gint x, gint y)
 {
     gboolean pos = FALSE; /* has the window's position been configured? */
@@ -2430,8 +2489,11 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
                                     (resized && config_resize_redraw))));
 
     /* if the client is enlarging, then resize the client before the frame */
-    if (send_resize_client && user && (w > oldw || h > oldh))
+    if (send_resize_client && user && (w > oldw || h > oldh)) {
         XResizeWindow(ob_display, self->window, MAX(w, oldw), MAX(h, oldh));
+        /* resize the plate to show the client padding color underneath */
+        frame_adjust_client_area(self->frame);
+    }
 
     /* find the frame's dimensions and move/resize it */
     if (self->decorations != fdecor || self->max_horz != fhorz)
@@ -2477,8 +2539,12 @@ void client_configure_full(ObClient *self, gint x, gint y, gint w, gint h,
     }
 
     /* if the client is shrinking, then resize the frame before the client */
-    if (send_resize_client && (!user || (w <= oldw || h <= oldh)))
+    if (send_resize_client && (!user || (w <= oldw || h <= oldh))) {
+        /* resize the plate to show the client padding color underneath */
+        frame_adjust_client_area(self->frame);
+
         XResizeWindow(ob_display, self->window, w, h);
+    }
 
     XFlush(ob_display);
 }
@@ -2582,10 +2648,11 @@ static void client_iconify_recursive(ObClient *self,
             screen_update_areas();
     }
 
-    /* iconify all direct transients */
+    /* iconify all direct transients, and deiconify all transients
+       (non-direct too) */
     for (it = self->transients; it; it = g_slist_next(it))
         if (it->data != self)
-            if (client_is_direct_child(self, it->data))
+            if (client_is_direct_child(self, it->data) || !iconic)
                 client_iconify_recursive(it->data, iconic, curdesk);
 }
 
@@ -2733,11 +2800,13 @@ void client_hilite(ObClient *self, gboolean hilite)
 
     /* don't allow focused windows to hilite */
     self->demands_attention = hilite && !client_focused(self);
-    if (self->demands_attention)
-        frame_flash_start(self->frame);
-    else
-        frame_flash_stop(self->frame);
-    client_change_state(self);
+    if (self->frame != NULL) { /* if we're mapping, just set the state */
+        if (self->demands_attention)
+            frame_flash_start(self->frame);
+        else
+            frame_flash_stop(self->frame);
+        client_change_state(self);
+    }
 }
 
 void client_set_desktop_recursive(ObClient *self,
@@ -3579,3 +3648,17 @@ gboolean client_has_group_siblings(ObClient *self)
 {
     return self->group && self->group->members->next;
 }
+
+gboolean client_has_application_group_siblings(ObClient *self)
+{
+    GSList *it;
+
+    if (!self->group) return FALSE;
+
+    for (it = self->group->members; it; it = g_slist_next(it)) {
+        ObClient *c = it->data;
+        if (c != self && client_application(c))
+            return TRUE;
+    }
+    return FALSE;
+}
This page took 0.030267 seconds and 4 git commands to generate.