]> Dogcows Code - chaz/openbox/blobdiff - openbox/client.c
plug memory leaks from the new strut code
[chaz/openbox] / openbox / client.c
index c3e7ae6cee31e6a949a5b61b4482b6f0b9ca5663..df494a9fc1d3edb95a40894e1801389050c1e690 100644 (file)
@@ -314,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;
     }
@@ -404,21 +398,27 @@ void client_manage(Window window)
           client_normal(self) &&
           !self->session)))
     {
-        /* make a copy to modify */
-        Rect a = *screen_area_monitor(self->desktop, client_monitor(self));
+        Rect placer;
+
+        RECT_SET(placer, placex, placey, placew, placeh);
+        frame_rect_to_frame(self->frame, &placer);
+
+        Rect *a = screen_area_monitor(self->desktop, client_monitor(self),
+                                      &placer);
 
         /* shrink by the frame's area */
-        a.width -= self->frame->size.left + self->frame->size.right;
-        a.height -= self->frame->size.top + self->frame->size.bottom;
+        a->width -= self->frame->size.left + self->frame->size.right;
+        a->height -= self->frame->size.top + self->frame->size.bottom;
 
         /* fit the window inside the area */
-        if (placew > a.width || self->area.height > a.height) {
-            placew = MIN(self->area.width, a.width);
-            placeh = MIN(self->area.height, a.height);
+        if (placew > a->width || self->area.height > a->height) {
+            placew = MIN(self->area.width, a->width);
+            placeh = MIN(self->area.height, a->height);
 
             ob_debug("setting window size to %dx%d\n",
                      self->area.width, self->area.height);
         }
+        g_free(a);
     }
 
 
@@ -532,7 +532,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);
@@ -616,14 +625,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);
@@ -921,8 +930,11 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     Rect desired;
 
     RECT_SET(desired, *x, *y, w, h);
-    all_a = screen_area(self->desktop);
-    mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired));
+    frame_rect_to_frame(self->frame, &desired);
+
+    all_a = screen_area(self->desktop, &desired);
+    mon_a = screen_area_monitor(self->desktop, screen_find_monitor(&desired),
+                                &desired);
 
     /* get where the frame would be */
     frame_client_gravity(self->frame, x, y, w, h);
@@ -1008,6 +1020,9 @@ gboolean client_find_onscreen(ObClient *self, gint *x, gint *y, gint w, gint h,
     /* get where the client should be */
     frame_frame_gravity(self->frame, x, y, w, h);
 
+    g_free(all_a);
+    g_free(mon_a);
+
     return ox != *x || oy != *y;
 }
 
@@ -1569,7 +1584,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)
@@ -1708,12 +1732,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))
@@ -1973,6 +1993,7 @@ void client_update_strut(ObClient *self)
                               a->x, a->x + a->width - 1,
                               a->y, a->y + a->height - 1,
                               a->x, a->x + a->width - 1);
+            g_free(a);
         }
         g_free(data);
     }
@@ -2373,6 +2394,9 @@ gboolean client_has_parent(ObClient *self)
 static ObStackingLayer calc_layer(ObClient *self)
 {
     ObStackingLayer l;
+    Rect *monitor;
+
+    monitor = screen_physical_area_monitor(client_monitor(self));
 
     if (self->type == OB_CLIENT_TYPE_DESKTOP)
         l = OB_STACKING_LAYER_DESKTOP;
@@ -2386,15 +2410,15 @@ static ObStackingLayer calc_layer(ObClient *self)
               */
               (self->decorations == 0 &&
                !(self->max_horz && self->max_vert) &&
-               RECT_EQUAL(self->area,
-                          *screen_physical_area_monitor
-                          (client_monitor(self))))) &&
+               RECT_EQUAL(self->area, *monitor))) &&
              (client_focused(self) || client_search_focus_tree(self)))
         l = OB_STACKING_LAYER_FULLSCREEN;
     else if (self->above) l = OB_STACKING_LAYER_ABOVE;
     else if (self->below) l = OB_STACKING_LAYER_BELOW;
     else l = OB_STACKING_LAYER_NORMAL;
 
+    g_free(monitor);
+
     return l;
 }
 
@@ -2477,6 +2501,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 +2591,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.. */
 
@@ -2659,16 +2696,74 @@ void client_try_configure(ObClient *self, gint *x, gint *y, gint *w, gint *h,
                           gint *logicalw, gint *logicalh,
                           gboolean user)
 {
-    Rect desired_area = {*x, *y, *w, *h};
+    Rect desired = {*x, *y, *w, *h};
+    frame_rect_to_frame(self->frame, &desired);
 
     /* 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, 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);
+        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 */
+
+        g_free(a);
+    } else if (self->max_horz || self->max_vert) {
+        Rect *a;
+        guint i;
+
+        i = screen_find_monitor(&desired);
+        a = screen_area_monitor(self->desktop, i, &desired);
+
+        /* 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 */
+
+        g_free(a);
+    }
+
+    /* 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;
+        gfloat 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 +2795,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 +2817,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 +3253,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 +3622,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), "
@@ -3824,8 +3878,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
     if(!client_list)
         return -1;
 
-    a = screen_area(c->desktop);
-    monitor = screen_area_monitor(c->desktop, client_monitor(c));
+    a = screen_area(c->desktop, &c->frame->area);
+    monitor = screen_area_monitor(c->desktop, client_monitor(c),
+                                  &c->frame->area);
 
     switch(dir) {
     case OB_DIRECTION_NORTH:
@@ -3972,6 +4027,9 @@ gint client_directional_edge_search(ObClient *c, ObDirection dir, gboolean hang)
         g_assert_not_reached();
         dest = 0; /* suppress warning */
     }
+
+    g_free(a);
+    g_free(monitor);
     return dest;
 }
 
@@ -3986,6 +4044,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.035169 seconds and 4 git commands to generate.