]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
remove debug prints
[chaz/openbox] / openbox / client.c
index 80773f6c45ed8af890dc9b003cee215dccbab291..8b008e9b2a424bba780a76adb3377b6eca6b25dd 100644 (file)
 #define CLIENT_NOPROPAGATEMASK (ButtonPressMask | ButtonReleaseMask | \
                                ButtonMotionMask)
 
+typedef struct
+{
+    ObClientDestructor func;
+    gpointer data;
+} Destructor;
+
 GList      *client_list        = NULL;
 GSList     *client_destructors = NULL;
 
@@ -81,14 +87,26 @@ void client_shutdown(gboolean reconfig)
 {
 }
 
-void client_add_destructor(GDestroyNotify func)
+void client_add_destructor(ObClientDestructor func, gpointer data)
 {
-    client_destructors = g_slist_prepend(client_destructors, (gpointer)func);
+    Destructor *d = g_new(Destructor, 1);
+    d->func = func;
+    d->data = data;
+    client_destructors = g_slist_prepend(client_destructors, d);
 }
 
-void client_remove_destructor(GDestroyNotify func)
+void client_remove_destructor(ObClientDestructor func)
 {
-    client_destructors = g_slist_remove(client_destructors, (gpointer)func);
+    GSList *it;
+
+    for (it = client_destructors; it; it = g_slist_next(it)) {
+        Destructor *d = it->data;
+        if (d->func == func) {
+            g_free(d);
+            client_destructors = g_slist_delete_link(client_destructors, it);
+            break;
+        }
+    }
 }
 
 void client_set_list()
@@ -277,9 +295,7 @@ void client_manage(Window window)
 
     /* focus the new window? */
     if (ob_state() != OB_STATE_STARTING &&
-        (config_focus_new || (self->transient_for &&
-                              self->transient_for != OB_TRAN_GROUP &&
-                              client_focused(self->transient_for))) &&
+        (config_focus_new || client_search_focus_parent(self)) &&
         /* note the check against Type_Normal/Dialog, not client_normal(self),
            which would also include other types. in this case we want more
            strict rules for focus */
@@ -403,6 +419,25 @@ void client_unmanage(ObClient *self)
        influence */
     screen_update_areas();
 
+    for (it = client_destructors; it; it = g_slist_next(it)) {
+        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 */
         GSList *it;
@@ -412,8 +447,8 @@ void client_unmanage(ObClient *self)
                 ((ObClient*)it->data)->transients =
                     g_slist_remove(((ObClient*)it->data)->transients, self);
     } else if (self->transient_for) {        /* transient of window */
-       self->transient_for->transients =
-           g_slist_remove(self->transient_for->transients, self);
+        self->transient_for->transients =
+            g_slist_remove(self->transient_for->transients, self);
     }
 
     /* tell our transients that we're gone */
@@ -424,20 +459,6 @@ void client_unmanage(ObClient *self)
         }
     }
 
-    for (it = client_destructors; it; it = g_slist_next(it)) {
-        GDestroyNotify func = (GDestroyNotify) it->data;
-        func(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));
-        client_unfocus(self);
-    }
-
     /* remove from its group */
     if (self->group) {
         group_remove(self->group, self);
@@ -470,9 +491,9 @@ void client_unmanage(ObClient *self)
     /* free all data allocated in the client struct */
     g_slist_free(self->transients);
     for (j = 0; j < self->nicons; ++j)
-       g_free(self->icons[j].data);
+        g_free(self->icons[j].data);
     if (self->nicons > 0)
-       g_free(self->icons);
+        g_free(self->icons);
     g_free(self->title);
     g_free(self->icon_title);
     g_free(self->name);
@@ -826,7 +847,7 @@ void client_update_transient_for(ObClient *self)
     ObClient *target = NULL;
 
     if (XGetTransientForHint(ob_display, self->window, &t)) {
-       self->transient = TRUE;
+        self->transient = TRUE;
         if (t != self->window) { /* cant be transient to itself! */
             target = g_hash_table_lookup(window_map, &t);
             /* if this happens then we need to check for it*/
@@ -842,14 +863,15 @@ void client_update_transient_for(ObClient *self)
                    group */
                 if (t == self->group->leader ||
                     t == None ||
-                    t == RootWindow(ob_display, ob_screen)) {
+                    t == RootWindow(ob_display, ob_screen))
+                {
                     /* window is a transient for its group! */
                     target = OB_TRAN_GROUP;
                 }
             }
         }
     } else
-       self->transient = FALSE;
+        self->transient = FALSE;
 
     /* if anything has changed... */
     if (target != self->transient_for) {
@@ -1280,6 +1302,18 @@ void client_update_wmhints(ObClient *self)
                 for (it = self->group->members; it; it = it->next)
                     self->transients = g_slist_remove(self->transients,
                                                       it->data);
+
+                /* remove myself from parents in the group */
+                if (self->transient_for == OB_TRAN_GROUP) {
+                    for (it = self->group->members; it; it = it->next) {
+                        ObClient *c = it->data;
+
+                        if (c != self && !c->transient_for)
+                            c->transients = g_slist_remove(c->transients,
+                                                           self);
+                    }
+                }
+
                 group_remove(self->group, self);
                 self->group = NULL;
             }
@@ -1310,16 +1344,14 @@ void client_update_wmhints(ObClient *self)
         /* the WM_HINTS can contain an icon */
         client_update_icons(self);
 
-       XFree(hints);
+        XFree(hints);
     }
 
     if (ur != self->urgent) {
-       self->urgent = ur;
-       ob_debug("Urgent Hint for 0x%lx: %s\n", self->window,
-                 ur ? "ON" : "OFF");
-       /* fire the urgent callback if we're mapped, otherwise, wait until
-          after we're mapped */
-       if (self->frame)
+        self->urgent = ur;
+        /* fire the urgent callback if we're mapped, otherwise, wait until
+           after we're mapped */
+        if (self->frame)
             client_urgent_notify(self);
     }
 }
@@ -1484,35 +1516,35 @@ void client_update_icons(ObClient *self)
     guint w, h, i, j;
 
     for (i = 0; i < self->nicons; ++i)
-       g_free(self->icons[i].data);
+        g_free(self->icons[i].data);
     if (self->nicons > 0)
-       g_free(self->icons);
+        g_free(self->icons);
     self->nicons = 0;
 
     if (PROP_GETA32(self->window, net_wm_icon, cardinal, &data, &num)) {
-       /* figure out how many valid icons are in here */
-       i = 0;
-       while (num - i > 2) {
-           w = data[i++];
-           h = data[i++];
-           i += w * h;
-           if (i > num || w*h == 0) break;
-           ++self->nicons;
-       }
+        /* figure out how many valid icons are in here */
+        i = 0;
+        while (num - i > 2) {
+            w = data[i++];
+            h = data[i++];
+            i += w * h;
+            if (i > num || w*h == 0) break;
+            ++self->nicons;
+        }
 
-       self->icons = g_new(ObClientIcon, self->nicons);
+        self->icons = g_new(ObClientIcon, self->nicons);
     
-       /* store the icons */
-       i = 0;
-       for (j = 0; j < self->nicons; ++j) {
+        /* store the icons */
+        i = 0;
+        for (j = 0; j < self->nicons; ++j) {
             guint x, y, t;
 
-           w = self->icons[j].width = data[i++];
-           h = self->icons[j].height = data[i++];
+            w = self->icons[j].width = data[i++];
+            h = self->icons[j].height = data[i++];
 
             if (w*h == 0) continue;
 
-           self->icons[j].data = g_new(RrPixel32, w * h);
+            self->icons[j].data = g_new(RrPixel32, w * h);
             for (x = 0, y = 0, t = 0; t < w * h; ++t, ++x, ++i) {
                 if (x >= w) {
                     x = 0;
@@ -1524,10 +1556,10 @@ void client_update_icons(ObClient *self)
                     (((data[i] >> 8) & 0xff) << RrDefaultGreenOffset) +
                     (((data[i] >> 0) & 0xff) << RrDefaultBlueOffset);
             }
-           g_assert(i <= num);
-       }
+            g_assert(i <= num);
+        }
 
-       g_free(data);
+        g_free(data);
     } else if (PROP_GETA32(self->window, kwm_win_icon,
                            kwm_win_icon, &data, &num)) {
         if (num == 2) {
@@ -1569,18 +1601,8 @@ void client_update_icons(ObClient *self)
         }
     }
 
-    if (!self->nicons) {
-        self->nicons++;
-        self->icons = g_new(ObClientIcon, self->nicons);
-        self->icons[self->nicons-1].width = 48;
-        self->icons[self->nicons-1].height = 48;
-        self->icons[self->nicons-1].data = g_memdup(ob_rr_theme->def_win_icon,
-                                                    sizeof(RrPixel32)
-                                                    * 48 * 48);
-    }
-
     if (self->frame)
-       frame_adjust_icon(self->frame);
+        frame_adjust_icon(self->frame);
 }
 
 static void client_change_state(ObClient *self)
@@ -1668,7 +1690,9 @@ static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
 
-    if (self->fullscreen) l = OB_STACKING_LAYER_FULLSCREEN;
+    if (self->fullscreen &&
+        (client_focused(self) || client_search_focus_tree(self)))
+        l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
     else if (self->type == OB_CLIENT_TYPE_DOCK) {
@@ -1929,27 +1953,46 @@ void client_configure_full(ObClient *self, ObCorner anchor,
         h -= self->base_size.height;
 
         if (self->min_ratio)
-            if (h * self->min_ratio > w) h = (int)(w / self->min_ratio);
+            if (h * self->min_ratio > w) {
+                h = (int)(w / self->min_ratio);
+
+                /* you cannot resize to nothing */
+                if (h < 1) {
+                    h = 1;
+                    w = (int)(h * self->min_ratio);
+                }
+            }
         if (self->max_ratio)
-            if (h * self->max_ratio < w) h = (int)(w / self->max_ratio);
+            if (h * self->max_ratio < w) {
+                h = (int)(w / self->max_ratio);
+
+                /* you cannot resize to nothing */
+                if (h < 1) {
+                    h = 1;
+                    w = (int)(h * self->min_ratio);
+                }
+            }
 
         w += self->base_size.width;
         h += self->base_size.height;
     }
 
+    g_assert(w > 0);
+    g_assert(h > 0);
+
     switch (anchor) {
     case OB_CORNER_TOPLEFT:
-       break;
+        break;
     case OB_CORNER_TOPRIGHT:
-       x -= w - self->area.width;
-       break;
+        x -= w - self->area.width;
+        break;
     case OB_CORNER_BOTTOMLEFT:
-       y -= h - self->area.height;
-       break;
+        y -= h - self->area.height;
+        break;
     case OB_CORNER_BOTTOMRIGHT:
-       x -= w - self->area.width;
-       y -= h - self->area.height;
-       break;
+        x -= w - self->area.width;
+        y -= h - self->area.height;
+        break;
     }
 
     moved = x != self->area.x || y != self->area.y;
@@ -2185,7 +2228,7 @@ void client_maximize(ObClient *self, gboolean max, int dir, gboolean savearea)
             }
         }
         if ((dir == 0 || dir == 2) && self->max_vert) { /* vert */
-            if (self->pre_max_area.width > 0) {
+            if (self->pre_max_area.height > 0) {
                 y = self->pre_max_area.y;
                 h = self->pre_max_area.height;
 
@@ -2291,7 +2334,7 @@ void client_set_desktop_recursive(ObClient *self,
             client_showhide(self);
         /* raise if it was not already on the desktop */
         if (old != DESKTOP_ALL)
-            stacking_raise(CLIENT_AS_WINDOW(self));
+            client_raise(self);
         screen_update_areas();
 
         /* add to the new desktop(s) */
@@ -2494,7 +2537,7 @@ ObClient *client_focus_target(ObClient *self)
     ObClient *child;
      
     /* if we have a modal child, then focus it, not us */
-    child = client_search_modal_child(self);
+    child = client_search_modal_child(client_search_top_transient(self));
     if (child) return child;
     return self;
 }
@@ -2513,24 +2556,24 @@ gboolean client_can_focus(ObClient *self)
           (self->desktop == screen_desktop ||
            self->desktop == DESKTOP_ALL) &&
           !self->iconic))
-       return FALSE;
+        return FALSE;
 
     /* do a check to see if the window has already been unmapped or destroyed
        do this intelligently while watching out for unmaps we've generated
        (ignore_unmaps > 0) */
     if (XCheckTypedWindowEvent(ob_display, self->window,
-                              DestroyNotify, &ev)) {
-       XPutBackEvent(ob_display, &ev);
-       return FALSE;
+                               DestroyNotify, &ev)) {
+        XPutBackEvent(ob_display, &ev);
+        return FALSE;
     }
     while (XCheckTypedWindowEvent(ob_display, self->window,
-                                 UnmapNotify, &ev)) {
-       if (self->ignore_unmaps) {
-           self->ignore_unmaps--;
-       } else {
-           XPutBackEvent(ob_display, &ev);
-           return FALSE;
-       }
+                                  UnmapNotify, &ev)) {
+        if (self->ignore_unmaps) {
+            self->ignore_unmaps--;
+        } else {
+            XPutBackEvent(ob_display, &ev);
+            return FALSE;
+        }
     }
 
     return TRUE;
@@ -2604,7 +2647,7 @@ void client_activate(ObClient *self, gboolean here)
     if (client_normal(self) && screen_showing_desktop)
         screen_show_desktop(FALSE);
     if (self->iconic)
-        client_iconify(self, FALSE, FALSE);
+        client_iconify(self, FALSE, here);
     if (self->desktop != DESKTOP_ALL &&
         self->desktop != screen_desktop) {
         if (here)
@@ -2617,8 +2660,25 @@ void client_activate(ObClient *self, gboolean here)
         return;
     if (self->shaded)
         client_shade(self, FALSE);
+
     client_focus(self);
-    stacking_raise(CLIENT_AS_WINDOW(self));
+
+    /* we do this an action here. this is rather important. this is because
+       we want the results from the focus change to take place BEFORE we go
+       about raising the window. when a fullscreen window loses focus, we need
+       this or else the raise wont be able to raise above the to-lose-focus
+       fullscreen window. */
+    client_raise(self);
+}
+
+void client_raise(ObClient *self)
+{
+    action_run_string("Raise", self);
+}
+
+void client_lower(ObClient *self)
+{
+    action_run_string("Raise", self);
 }
 
 gboolean client_focused(ObClient *self)
@@ -2626,13 +2686,34 @@ gboolean client_focused(ObClient *self)
     return self == focus_client;
 }
 
-ObClientIcon *client_icon(ObClient *self, int w, int h)
+static ObClientIcon* client_icon_recursive(ObClient *self, int w, int h)
 {
     guint i;
     /* si is the smallest image >= req */
     /* li is the largest image < req */
     unsigned long size, smallest = 0xffffffff, largest = 0, si = 0, li = 0;
 
+    if (!self->nicons) {
+        ObClientIcon *parent = NULL;
+
+        if (self->transient_for) {
+            if (self->transient_for != OB_TRAN_GROUP)
+                parent = client_icon_recursive(self->transient_for, w, h);
+            else {
+                GSList *it;
+                for (it = self->group->members; it; it = g_slist_next(it)) {
+                    ObClient *c = it->data;
+                    if (c != self && !c->transient_for) {
+                        if ((parent = client_icon_recursive(c, w, h)))
+                            break;
+                    }
+                }
+            }
+        }
+        
+        return parent;
+    }
+
     for (i = 0; i < self->nicons; ++i) {
         size = self->icons[i].width * self->icons[i].height;
         if (size < smallest && size >= (unsigned)(w * h)) {
@@ -2649,6 +2730,19 @@ ObClientIcon *client_icon(ObClient *self, int w, int h)
     return &self->icons[li];
 }
 
+const ObClientIcon* client_icon(ObClient *self, int w, int h)
+{
+    ObClientIcon *ret;
+    static ObClientIcon deficon;
+
+    if (!(ret = client_icon_recursive(self, w, h))) {
+        deficon.width = deficon.height = 48;
+        deficon.data = ob_rr_theme->def_win_icon;
+        ret = &deficon;
+    }
+    return ret;
+}
+
 /* this be mostly ripped from fvwm */
 ObClient *client_find_directional(ObClient *c, ObDirection dir) 
 {
@@ -2794,6 +2888,8 @@ ObClient *client_search_top_transient(ObClient *self)
         } else {
             GSList *it;
 
+            g_assert(self->group);
+
             for (it = self->group->members; it; it = it->next) {
                 ObClient *c = it->data;
 
@@ -2809,6 +2905,52 @@ ObClient *client_search_top_transient(ObClient *self)
     return self;
 }
 
+ObClient *client_search_focus_parent(ObClient *self)
+{
+    if (self->transient_for) {
+        if (self->transient_for != OB_TRAN_GROUP) {
+            if (client_focused(self->transient_for))
+                return self->transient_for;
+        } else {
+            GSList *it;
+
+            for (it = self->group->members; it; it = it->next) {
+                ObClient *c = it->data;
+
+                /* checking transient_for prevents infinate loops! */
+                if (c != self && !c->transient_for)
+                    if (client_focused(c))
+                        return c;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+ObClient *client_search_parent(ObClient *self, ObClient *search)
+{
+    if (self->transient_for) {
+        if (self->transient_for != OB_TRAN_GROUP) {
+            if (self->transient_for == search)
+                return search;
+        } else {
+            GSList *it;
+
+            for (it = self->group->members; it; it = it->next) {
+                ObClient *c = it->data;
+
+                /* checking transient_for prevents infinate loops! */
+                if (c != self && !c->transient_for)
+                    if (c == search)
+                        return search;
+            }
+        }
+    }
+
+    return NULL;
+}
+
 ObClient *client_search_transient(ObClient *self, ObClient *search)
 {
     GSList *sit;
@@ -3033,7 +3175,7 @@ ObClient* client_under_pointer()
         for (it = stacking_list; it != NULL; it = it->next) {
             if (WINDOW_IS_CLIENT(it->data)) {
                 ObClient *c = WINDOW_AS_CLIENT(it->data);
-                if (c->desktop == screen_desktop &&
+                if (c->frame->visible &&
                     RECT_CONTAINS(c->frame->area, x, y)) {
                     ret = c;
                     break;
This page took 0.038316 seconds and 4 git commands to generate.