From b1b84675f0e854bea0a181d31b9472be4813f62d Mon Sep 17 00:00:00 2001 From: John Scipione Date: Wed, 25 Oct 2017 15:59:13 -0700 Subject: [PATCH] BWindow: Update default Zoom() to respect Deskbar Zoom() takes up all Desktop area excluding the area occupied by Deskbar. This is calculated using information from the BDeskbar class. Window zooms just as you'd expect -- it takes up fullscreen minus area taken up by Deskbar. In vertical mode the zoom area depends on the width of Deskbar, consequently Zoom() is more space efficient in horizontal mode than vertical mode because the window doesn't use the area below Deskbar. If the zoom limits are smaller than the Desktop area, the zoom area shrinks towards the center of the Desktop not covered by Deskbar. This is slightly different behavior, the window insets off-center following Deskbar. In some scenarios zooming to the non-Deskbar area was too restrictive. I made an exception that if there is enough room above or below Deskbar i.e. a short window, then Zoom() instead insets from the screen edge ignoring Deskbar. Apps which meet this criteria include DriveSetup and Expander. --- src/kits/interface/Window.cpp | 88 ++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 27 deletions(-) diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 5f3a284fea..0914b91c0d 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1690,44 +1691,77 @@ BWindow::Zoom() // The dimensions that non-virtual Zoom() passes to hook Zoom() are deduced // from the smallest of three rectangles: + // 1) the rectangle defined by SetZoomLimits() and, + // 2) the rectangle defined by SetSizeLimits() + float maxZoomWidth = std::min(fMaxZoomWidth, fMaxWidth); + float maxZoomHeight = std::min(fMaxZoomHeight, fMaxHeight); + + // 3) the screen rectangle + BRect screenFrame = (BScreen(this)).Frame(); + maxZoomWidth = std::min(maxZoomWidth, screenFrame.Width()); + maxZoomHeight = std::min(maxZoomHeight, screenFrame.Height()); + + BRect zoomArea = screenFrame; // starts at screen size + + // remove area taken up by Deskbar + BDeskbar deskbar; + BRect deskbarFrame = deskbar.Frame(); + switch (deskbar.Location()) { + case B_DESKBAR_TOP: + zoomArea.top = deskbarFrame.bottom + 2; + break; + + case B_DESKBAR_BOTTOM: + zoomArea.bottom = deskbarFrame.top - 2; + break; + + case B_DESKBAR_LEFT_TOP: + case B_DESKBAR_LEFT_BOTTOM: + zoomArea.left = deskbarFrame.right + 2; + break; + + default: + case B_DESKBAR_RIGHT_TOP: + case B_DESKBAR_RIGHT_BOTTOM: + zoomArea.right = deskbarFrame.left - 2; + break; + } + + // TODO: Broken for tab on left side windows... float borderWidth; float tabHeight; _GetDecoratorSize(&borderWidth, &tabHeight); - // 1) the rectangle defined by SetZoomLimits(), - float zoomedWidth = fMaxZoomWidth; - float zoomedHeight = fMaxZoomHeight; + // remove the area taken up by the tab and border + zoomArea.left += borderWidth; + zoomArea.top += borderWidth + tabHeight; + zoomArea.right -= borderWidth; + zoomArea.bottom -= borderWidth; - // 2) the rectangle defined by SetSizeLimits() - if (fMaxWidth < zoomedWidth) - zoomedWidth = fMaxWidth; - if (fMaxHeight < zoomedHeight) - zoomedHeight = fMaxHeight; + // inset towards center vertically first to see if there will be room + // above or below Deskbar + if (zoomArea.Height() > maxZoomHeight) + zoomArea.InsetBy(0, roundf((zoomArea.Height() - maxZoomHeight) / 2)); - // 3) the screen rectangle - BScreen screen(this); - // TODO: Broken for tab on left side windows... - float screenWidth = screen.Frame().Width() - 2 * borderWidth; - float screenHeight = screen.Frame().Height() - (2 * borderWidth + tabHeight); - if (screenWidth < zoomedWidth) - zoomedWidth = screenWidth; - if (screenHeight < zoomedHeight) - zoomedHeight = screenHeight; + if (zoomArea.top > deskbarFrame.bottom + || zoomArea.bottom < deskbarFrame.top) { + // there is room above or below Deskbar, start from screen width + // minus borders instead of desktop width minus borders + zoomArea.left = screenFrame.left + borderWidth; + zoomArea.right = screenFrame.right - borderWidth; + } - BPoint zoomedLeftTop = screen.Frame().LeftTop() + BPoint(borderWidth, - tabHeight + borderWidth); - // Center if window cannot be made full screen - if (screenWidth > zoomedWidth) - zoomedLeftTop.x += (screenWidth - zoomedWidth) / 2; - if (screenHeight > zoomedHeight) - zoomedLeftTop.y += (screenHeight - zoomedHeight) / 2; + // inset towards center + if (zoomArea.Width() > maxZoomWidth) + zoomArea.InsetBy(roundf((zoomArea.Width() - maxZoomWidth) / 2), 0); // Un-Zoom if (fPreviousFrame.IsValid() - // NOTE: don't check for fFrame.LeftTop() == zoomedLeftTop + // NOTE: don't check for fFrame.LeftTop() == zoomArea.LeftTop() // -> makes it easier on the user to get a window back into place - && fFrame.Width() == zoomedWidth && fFrame.Height() == zoomedHeight) { + && fFrame.Width() == zoomArea.Width() + && fFrame.Height() == zoomArea.Height()) { // already zoomed! Zoom(fPreviousFrame.LeftTop(), fPreviousFrame.Width(), fPreviousFrame.Height()); @@ -1739,7 +1773,7 @@ BWindow::Zoom() // remember fFrame for later "unzooming" fPreviousFrame = fFrame; - Zoom(zoomedLeftTop, zoomedWidth, zoomedHeight); + Zoom(zoomArea.LeftTop(), zoomArea.Width(), zoomArea.Height()); }