[PATCH] explorer: modify rects passed to SHAppBarMessage to not interfere with existing appbars

Vincent Povirk vincent at codeweavers.com
Tue Sep 2 16:06:42 CDT 2008


---
 dlls/shell32/tests/appbar.c |   28 +++++++++++-----------
 programs/explorer/appbar.c  |   53 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 17 deletions(-)

diff --git a/dlls/shell32/tests/appbar.c b/dlls/shell32/tests/appbar.c
index 872c962..e1c8fa7 100644
--- a/dlls/shell32/tests/appbar.c
+++ b/dlls/shell32/tests/appbar.c
@@ -194,7 +194,7 @@ static void test_setpos(void)
     do_events();
     
     /* the windows are adjusted to they don't overlap */
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -203,7 +203,7 @@ static void test_setpos(void)
     window1_info.desired_rect.top = screen_height - 20;
     testwindow_setpos(window1);
     do_events();
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -229,15 +229,15 @@ static void test_setpos(void)
     testwindow_setpos(window3);
     do_events();
 
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -251,15 +251,15 @@ static void test_setpos(void)
     testwindow_setpos(window3);
     do_events();
 
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -277,11 +277,11 @@ static void test_setpos(void)
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -295,15 +295,15 @@ static void test_setpos(void)
     testwindow_setpos(window2);
     do_events();
 
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window1_info.allocated_rect, &window3_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window1_info.allocated_rect.left, window1_info.allocated_rect.top, window1_info.allocated_rect.right, window1_info.allocated_rect.bottom,
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom);
-    todo_wine ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
@@ -320,7 +320,7 @@ static void test_setpos(void)
     
     ok(window2_info.allocated_rect.bottom = expected, "window2's bottom is %i, expected %i\n", window2_info.allocated_rect.bottom, expected);
 
-    todo_wine ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
+    ok(!IntersectRect(&rc, &window3_info.allocated_rect, &window2_info.allocated_rect),
         "rectangles intersect (%i,%i,%i,%i)/(%i,%i,%i,%i)\n",
         window3_info.allocated_rect.left, window3_info.allocated_rect.top, window3_info.allocated_rect.right, window3_info.allocated_rect.bottom,
         window2_info.allocated_rect.left, window2_info.allocated_rect.top, window2_info.allocated_rect.right, window2_info.allocated_rect.bottom);
diff --git a/programs/explorer/appbar.c b/programs/explorer/appbar.c
index 71b7ea2..8370e99 100644
--- a/programs/explorer/appbar.c
+++ b/programs/explorer/appbar.c
@@ -16,6 +16,15 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ *
+ * TODO: freedesktop _NET_WM_STRUT integration
+ *
+ * TODO: find when a fullscreen app is in the foreground and send FULLSCREENAPP
+ *  notifications
+ *
+ * TODO: detect changes in the screen size and send ABN_POSCHANGED ?
+ *
+ * TODO: multiple monitor support
  */
 
 #include "wine/unicode.h"
@@ -82,10 +91,43 @@ static void send_poschanged(HWND hwnd)
     }
 }
 
-static UINT_PTR handle_appbarmessage(DWORD msg, PAPPBARDATA abd)
+/* appbar_cliprect: cut out parts of the rectangle that interfere with existing appbars */
+static void appbar_cliprect(PAPPBARDATA abd)
 {
     struct appbar_data* data;
+    LIST_FOR_EACH_ENTRY(data, &appbars, struct appbar_data, entry)
+    {
+        if (data->hwnd == abd->hWnd)
+        {
+            /* we only care about appbars that were added before this one */
+            return;
+        }
+        if (data->space_reserved)
+        {
+            /* move in the side that corresponds to the other appbar's edge */
+            switch (data->edge)
+            {
+            case ABE_BOTTOM:
+                abd->rc.bottom = min(abd->rc.bottom, data->rc.top);
+                break;
+            case ABE_LEFT:
+                abd->rc.left = max(abd->rc.left, data->rc.right);
+                break;
+            case ABE_RIGHT:
+                abd->rc.right = min(abd->rc.right, data->rc.left);
+                break;
+            case ABE_TOP:
+                abd->rc.top = max(abd->rc.top, data->rc.bottom);
+                break;
+            }
+        }
+    }
+}
 
+static UINT_PTR handle_appbarmessage(DWORD msg, PAPPBARDATA abd)
+{
+    struct appbar_data* data;
+    
     switch (msg)
     {
     case ABM_NEW:
@@ -120,10 +162,11 @@ static UINT_PTR handle_appbarmessage(DWORD msg, PAPPBARDATA abd)
             WINE_WARN("removing hwnd %p not on the list\n", abd->hWnd);
         return TRUE;
     case ABM_QUERYPOS:
-        WINE_FIXME("SHAppBarMessage(ABM_QUERYPOS, hwnd=%p, edge=%x, rc=%s): stub\n", abd->hWnd, abd->uEdge, wine_dbgstr_rect(&abd->rc));
+        if (abd->uEdge > ABE_BOTTOM)
+            WINE_WARN("invalid edge %i for %p\n", abd->uEdge, abd->hWnd);
+        appbar_cliprect(abd);
         return TRUE;
     case ABM_SETPOS:
-        WINE_FIXME("SHAppBarMessage(ABM_SETPOS, hwnd=%p, edge=%x, rc=%s): stub\n", abd->hWnd, abd->uEdge, wine_dbgstr_rect(&abd->rc));
         if (abd->uEdge > ABE_BOTTOM)
         {
             WINE_WARN("invalid edge %i for %p\n", abd->uEdge, abd->hWnd);
@@ -131,9 +174,13 @@ static UINT_PTR handle_appbarmessage(DWORD msg, PAPPBARDATA abd)
         }
         if ((data = get_appbar(abd->hWnd)))
         {
+            /* calculate acceptable space */
+            appbar_cliprect(abd);
+            
             if (!EqualRect(&abd->rc, &data->rc))
                 send_poschanged(abd->hWnd);
             
+            /* reserve that space for this appbar */
             data->edge = abd->uEdge;
             data->rc = abd->rc;
             data->space_reserved = TRUE;
-- 
1.5.4.3


--=-axwnCKJeCz1ywAN1yPsM--




More information about the wine-patches mailing list