Bug#704071: unblock: openbox/3.5.0-7
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Please unblock package openbox
The only change in 3.5.0-7 are two patches taken from the upstream
repository that fix a 100% CPU hangup when disabling a RandR output
under certain circumstances (see #697571).
The debdiff is attached.
unblock openbox/3.5.0-7
diff -Nru openbox-3.5.0/debian/changelog openbox-3.5.0/debian/changelog
--- openbox-3.5.0/debian/changelog 2012-12-01 18:39:17.000000000 +0100
+++ openbox-3.5.0/debian/changelog 2013-03-27 14:53:21.000000000 +0100
@@ -1,3 +1,11 @@
+openbox (3.5.0-7) unstable; urgency=low
+
+ * QA upload.
+ * Apply upstream fix for an infinite loop when disabling RandR outputs
+ (Closes: #697571)
+
+ -- Michael Stapelberg <stapelberg@debian.org> Wed, 27 Mar 2013 14:16:10 +0100
+
openbox (3.5.0-6) unstable; urgency=low
* Add missing Breaks/Replaces for gnome-panel-control,
diff -Nru openbox-3.5.0/debian/control openbox-3.5.0/debian/control
--- openbox-3.5.0/debian/control 2012-12-01 18:38:36.000000000 +0100
+++ openbox-3.5.0/debian/control 2013-03-27 14:53:20.000000000 +0100
@@ -1,7 +1,7 @@
Source: openbox
Section: x11
Priority: optional
-Maintainer: Nico Golde <nion@debian.org>
+Maintainer: Debian QA Group <packages@qa.debian.org>
Build-Depends: debhelper (>= 8.1.0~), gettext, libstartup-notification0-dev, libxrender-dev, pkg-config, libglib2.0-dev, libxml2-dev (>= 2.6.0), perl, libxt-dev, libxinerama-dev, libxrandr-dev, libpango1.0-dev, libx11-dev, autoconf, automake1.9, python-xdg, libimlib2-dev, dh-autoreconf, autopoint
Standards-Version: 3.9.3
Homepage: http://www.openbox.org
diff -Nru openbox-3.5.0/debian/patches/clever-rectangle-picking.patch openbox-3.5.0/debian/patches/clever-rectangle-picking.patch
--- openbox-3.5.0/debian/patches/clever-rectangle-picking.patch 1970-01-01 01:00:00.000000000 +0100
+++ openbox-3.5.0/debian/patches/clever-rectangle-picking.patch 2013-03-27 14:53:20.000000000 +0100
@@ -0,0 +1,195 @@
+commit d68116c9c9b2c9a9925d872141eff8e301ef3bb3
+Author: Dana Jansens <danakj@orodu.net>
+Date: Sat Oct 15 23:04:21 2011 -0400
+
+ Pick the monitor most relevant to a rectangle more cleverly.
+
+ When monitors overlap (this happens with cloning), we were choosing a monitor
+ to associate with a window, for maximization for example, somewhat arbitrarily.
+
+ Now we have a more clever algorithm that considers the configured primary
+ monitor first, and that does not prefer monitors based on their sizes, but only
+ how much of the window is in the monitor, excluding parts that were claimed
+ by another monitor already.
+
+Index: openbox-3.5.0/openbox/geom.h
+===================================================================
+--- openbox-3.5.0.orig/openbox/geom.h 2013-03-27 13:28:06.462611462 +0100
++++ openbox-3.5.0/openbox/geom.h 2013-03-27 13:29:09.872687284 +0100
+@@ -65,6 +65,8 @@
+ #define RECT_RIGHT(r) ((r).x + (r).width - 1)
+ #define RECT_BOTTOM(r) ((r).y + (r).height - 1)
+
++#define RECT_AREA(r) ((r).width * (r).height)
++
+ #define RECT_SET_POINT(r, nx, ny) \
+ (r).x = (nx), (r).y = (ny)
+ #define RECT_SET_SIZE(r, w, h) \
+Index: openbox-3.5.0/openbox/screen.c
+===================================================================
+--- openbox-3.5.0.orig/openbox/screen.c 2013-03-27 13:28:06.462611462 +0100
++++ openbox-3.5.0/openbox/screen.c 2013-03-27 13:29:09.874687318 +0100
+@@ -1372,6 +1372,14 @@
+ b = MAX(b, (*xin_areas)[i].y + (*xin_areas)[i].height - 1);
+ }
+ RECT_SET((*xin_areas)[*nxin], l, t, r - l + 1, b - t + 1);
++
++ for (i = 0; i < *nxin; ++i)
++ ob_debug("Monitor %d @ %d,%d %dx%d\n", i,
++ (*xin_areas)[i].x, (*xin_areas)[i].y,
++ (*xin_areas)[i].width, (*xin_areas)[i].height);
++ ob_debug("Full desktop @ %d,%d %dx%d\n",
++ (*xin_areas)[i].x, (*xin_areas)[i].y,
++ (*xin_areas)[i].width, (*xin_areas)[i].height);
+ }
+
+ void screen_update_areas(void)
+@@ -1631,27 +1639,135 @@
+ return a;
+ }
+
++typedef struct {
++ Rect r;
++ gboolean subtract;
++} RectArithmetic;
++
+ guint screen_find_monitor(const Rect *search)
+ {
+ guint i;
+ guint most = screen_num_monitors;
+- guint mostv = 0;
++ guint mostpx = 0;
++ GSList *counted = NULL;
+
+- for (i = 0; i < screen_num_monitors; ++i) {
+- const Rect *area = screen_physical_area_monitor(i);
+- if (RECT_INTERSECTS_RECT(*area, *search)) {
+- Rect r;
+- guint v;
+-
+- RECT_SET_INTERSECTION(r, *area, *search);
+- v = r.width * r.height;
+-
+- if (v > mostv) {
+- mostv = v;
+- most = i;
++ /* we want to count the number of pixels search has on each monitor, but not
++ double count. so if a pixel is counted on monitor A then we should not
++ count it again on monitor B. in the end we want to return the monitor
++ that had the most pixels counted under this scheme.
++
++ this assumes that monitors earlier in the list are more desirable to be
++ considered the search area's monitor. we try the configured primary
++ monitor first, so it gets the highest preference.
++
++ if we have counted an area A, then we want to subtract the intersection
++ of A with the area on future monitors.
++ but now consider if we count an area B that intersects A. we want to
++ subtract the area B from that counted on future monitors, but not
++ subtract the intersection of A and B twice! so we would add the
++ intersection of A and B back, to account for it being subtracted both
++ for A and B.
++
++ this is the idea behind the algorithm. we always subtract the full area
++ for monitor M intersected with the search area. we'll call that AREA.
++ but then we go through the list |counted| and for each rectangle in
++ the list that is being subtracted from future monitors, we insert a
++ request to add back the intersection of the subtracted rect with AREA.
++ vice versa for a rect in |counted| that is getting added back.
++ */
++
++ if (config_primary_monitor_index < screen_num_monitors) {
++ const Rect *monitor;
++ Rect on_current_monitor;
++ glong area;
++
++ monitor = screen_physical_area_monitor(config_primary_monitor_index);
++
++ if (RECT_INTERSECTS_RECT(*monitor, *search)) {
++ RECT_SET_INTERSECTION(on_current_monitor, *monitor, *search);
++ area = RECT_AREA(on_current_monitor);
++
++ if (area > mostpx) {
++ mostpx = area;
++ most = config_primary_monitor_index;
+ }
++
++ /* add the intersection rect on the current monitor to the
++ counted list. that's easy for the first one, we just mark it for
++ subtraction */
++ {
++ RectArithmetic *ra = g_slice_new(RectArithmetic);
++ ra->r = on_current_monitor;
++ ra->subtract = TRUE;
++ counted = g_slist_prepend(counted, ra);
++ }
++ }
++ }
++
++ for (i = 0; i < screen_num_monitors; ++i) {
++ const Rect *monitor;
++ Rect on_current_monitor;
++ glong area;
++ GSList *it;
++
++ monitor = screen_physical_area_monitor(i);
++
++ if (i == config_primary_monitor_index)
++ continue; /* already did this one */
++ if (!RECT_INTERSECTS_RECT(*monitor, *search))
++ continue; /* nothing to see here */
++
++ RECT_SET_INTERSECTION(on_current_monitor, *monitor, *search);
++ area = RECT_AREA(on_current_monitor);
++
++ /* remove pixels we already counted on any previous monitors. */
++ for (it = counted; it; it = g_slist_next(it)) {
++ RectArithmetic *ra = it->data;
++ Rect intersection;
++
++ RECT_SET_INTERSECTION(intersection, ra->r, *search);
++ if (ra->subtract) area -= RECT_AREA(intersection);
++ else area += RECT_AREA(intersection);
++ }
++
++ if (area > mostpx) {
++ mostpx = area;
++ most = i;
++ }
++
++ /* add the intersection rect on the current monitor I to the counted
++ list.
++ but now we need to compensate for every rectangle R already in the
++ counted list, and add a new rect R' that is the intersection of
++ R and I, but with the reverse subtraction/addition operation.
++ */
++ for (it = counted; it; it = g_slist_next(it)) {
++ RectArithmetic *saved = it->data;
++
++ if (!RECT_INTERSECTS_RECT(saved->r, on_current_monitor))
++ continue;
++ /* we are going to subtract our rect from future monitors, but
++ part of it may already be being subtracted/added, so compensate
++ to not double add/subtract. */
++ RectArithmetic *reverse = g_slice_new(RectArithmetic);
++ RECT_SET_INTERSECTION(reverse->r, saved->r, on_current_monitor);
++ reverse->subtract = !saved->subtract;
++ /* prepend so we can continue thru the list uninterupted */
++ counted = g_slist_prepend(counted, reverse);
++ }
++ {
++ RectArithmetic *ra = g_slice_new(RectArithmetic);
++ ra->r = on_current_monitor;
++ ra->subtract = TRUE;
++ counted = g_slist_prepend(counted, ra);
+ }
+ }
++
++ while (counted) {
++ g_slice_free(RectArithmetic, counted->data);
++ counted = g_slist_delete_link(counted, counted);
++ }
++
+ return most < screen_num_monitors ? most : screen_monitor_primary(FALSE);
+ }
+
diff -Nru openbox-3.5.0/debian/patches/series openbox-3.5.0/debian/patches/series
--- openbox-3.5.0/debian/patches/series 2012-06-05 07:25:05.000000000 +0200
+++ openbox-3.5.0/debian/patches/series 2013-03-27 14:53:20.000000000 +0100
@@ -7,3 +7,5 @@
90_fix_link_obt.patch
675991_fix_crash_from_gtk3_apps.patch
666676_wrong_undecorated_window_placement.patch
+clever-rectangle-picking.patch
+use-nearest-monitor.patch
diff -Nru openbox-3.5.0/debian/patches/use-nearest-monitor.patch openbox-3.5.0/debian/patches/use-nearest-monitor.patch
--- openbox-3.5.0/debian/patches/use-nearest-monitor.patch 1970-01-01 01:00:00.000000000 +0100
+++ openbox-3.5.0/debian/patches/use-nearest-monitor.patch 2013-03-27 14:53:20.000000000 +0100
@@ -0,0 +1,116 @@
+commit 01f62ded2fe289fe245f4f05b5825f4bdcbe1dc3
+Author: Dana Jansens <danakj@orodu.net>
+Date: Sun Sep 30 20:29:45 2012 -0400
+
+ Use the nearest monitor when the search query rect does not intersect any monitor (Fix bug 5500)
+
+ Previously we would try to find the primary monitor and use that when the search
+ was outside any monitor. However, if the primary monitor is chosen by the mouse
+ position and the mouse is not inside any monitor, we enter infinite recursion
+ trying to find the primary monitor.
+
+ The nearest monitor is a better metric anyhow, and this ensures
+ screen_find_monitor() is never recursive as it always returns a value without
+ depending on other screen.c methods.
+
+diff --git a/openbox/geom.h b/openbox/geom.h
+index 8ac0e55..8e50834 100644
+--- a/openbox/geom.h
++++ b/openbox/geom.h
+@@ -104,6 +104,25 @@ typedef struct _Rect {
+ (r).height = MIN((a).y + (a).height - 1, \
+ (b).y + (b).height - 1) - (r).y + 1)
+
++/* Returns the shortest manhatten distance between two rects, or 0 if they
++ intersect. */
++static inline gint rect_manhatten_distance(Rect r, Rect o)
++{
++ if (RECT_INTERSECTS_RECT(r, o))
++ return 0;
++
++ gint min_distance = G_MAXINT;
++ if (RECT_RIGHT(o) < RECT_LEFT(r))
++ min_distance = MIN(min_distance, RECT_LEFT(r) - RECT_RIGHT(o));
++ if (RECT_LEFT(o) > RECT_RIGHT(r))
++ min_distance = MIN(min_distance, RECT_LEFT(o) - RECT_RIGHT(r));
++ if (RECT_BOTTOM(o) < RECT_TOP(r))
++ min_distance = MIN(min_distance, RECT_TOP(r) - RECT_BOTTOM(o));
++ if (RECT_TOP(o) > RECT_BOTTOM(r))
++ min_distance = MIN(min_distance, RECT_TOP(o) - RECT_BOTTOM(r));
++ return min_distance;
++}
++
+ typedef struct _Strut {
+ int left;
+ int top;
+diff --git a/openbox/screen.c b/openbox/screen.c
+index 35366be..f4031f5 100644
+--- a/openbox/screen.c
++++ b/openbox/screen.c
+@@ -1644,8 +1644,10 @@ typedef struct {
+ guint screen_find_monitor(const Rect *search)
+ {
+ guint i;
+- guint most = screen_num_monitors;
++ guint mostpx_index = screen_num_monitors;
+ guint mostpx = 0;
++ guint closest_distance_index = screen_num_monitors;
++ guint closest_distance = G_MAXUINT;
+ GSList *counted = NULL;
+
+ /* we want to count the number of pixels search has on each monitor, but not
+@@ -1686,7 +1688,7 @@ guint screen_find_monitor(const Rect *search)
+
+ if (area > mostpx) {
+ mostpx = area;
+- most = config_primary_monitor_index;
++ mostpx_index = config_primary_monitor_index;
+ }
+
+ /* add the intersection rect on the current monitor to the
+@@ -1709,10 +1711,21 @@ guint screen_find_monitor(const Rect *search)
+
+ monitor = screen_physical_area_monitor(i);
+
++ if (!RECT_INTERSECTS_RECT(*monitor, *search)) {
++ /* If we don't intersect then find the distance between the search
++ rect and the monitor. We'll use the closest monitor from this
++ metric if none of the monitors intersect. */
++ guint distance = rect_manhatten_distance(*monitor, *search);
++
++ if (distance < closest_distance) {
++ closest_distance = distance;
++ closest_distance_index = i;
++ }
++ continue;
++ }
++
+ if (i == config_primary_monitor_index)
+ continue; /* already did this one */
+- if (!RECT_INTERSECTS_RECT(*monitor, *search))
+- continue; /* nothing to see here */
+
+ RECT_SET_INTERSECTION(on_current_monitor, *monitor, *search);
+ area = RECT_AREA(on_current_monitor);
+@@ -1729,7 +1742,7 @@ guint screen_find_monitor(const Rect *search)
+
+ if (area > mostpx) {
+ mostpx = area;
+- most = i;
++ mostpx_index = i;
+ }
+
+ /* add the intersection rect on the current monitor I to the counted
+@@ -1765,7 +1778,11 @@ guint screen_find_monitor(const Rect *search)
+ counted = g_slist_delete_link(counted, counted);
+ }
+
+- return most < screen_num_monitors ? most : screen_monitor_primary(FALSE);
++ if (mostpx_index < screen_num_monitors)
++ return mostpx_index;
++
++ g_assert(closest_distance_index < screen_num_monitors);
++ return closest_distance_index;
+ }
+
+ const Rect* screen_physical_area_all_monitors(void)
Reply to: