1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Multi-monitor fixes

This commit is contained in:
Brian Fiete 2020-05-07 08:39:40 -07:00
parent 7f0a81b5b3
commit 26604017f8
8 changed files with 133 additions and 32 deletions

View file

@ -81,6 +81,9 @@ namespace Beefy
[StdCall, CLink] [StdCall, CLink]
static extern void BFApp_GetWorkspaceRect(out int32 x, out int32 y, out int32 width, out int32 height); static extern void BFApp_GetWorkspaceRect(out int32 x, out int32 y, out int32 width, out int32 height);
[StdCall, CLink]
static extern void BFApp_GetWorkspaceRectFrom(int32 x, int32 y, int32 width, int32 height, out int32 outX, out int32 outY, out int32 outWidth, out int32 outHeight);
[StdCall, CLink] [StdCall, CLink]
static extern void BFApp_Create(); static extern void BFApp_Create();
@ -447,6 +450,19 @@ namespace Beefy
height = heightOut; height = heightOut;
} }
public void GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fromHeight, out int outX, out int outY, out int outWidth, out int outHeight)
{
int32 xOut;
int32 yOut;
int32 widthOut;
int32 heightOut;
BFApp_GetWorkspaceRectFrom((.)fromX, (.)fromY, (.)fromWidth, (.)fromHeight, out xOut, out yOut, out widthOut, out heightOut);
outX = xOut;
outY = yOut;
outWidth = widthOut;
outHeight = heightOut;
}
public bool HasModalDialogs() public bool HasModalDialogs()
{ {
for (var window in mWindows) for (var window in mWindows)

View file

@ -51,7 +51,7 @@ namespace Beefy.theme.dark
mText = new String(text); mText = new String(text);
mAllowResize = allowResize; mAllowResize = allowResize;
BFApp.sApp.GetWorkspaceRect(var workspaceX, var workspaceY, var workspaceWidth, var workspaceHeight); BFApp.sApp.GetWorkspaceRectFrom((.)x, (.)y, 0, 0, var workspaceX, var workspaceY, var workspaceWidth, var workspaceHeight);
float maxWidth = workspaceWidth - GS!(32); float maxWidth = workspaceWidth - GS!(32);
FontMetrics fontMetrics = .(); FontMetrics fontMetrics = .();

View file

@ -178,7 +178,7 @@ namespace Beefy.widgets
base.Resize(x, y, width, height); base.Resize(x, y, width, height);
} }
public virtual void CalcContainerSize(MenuContainer menuContainer, bool allowScrollable, ref float screenX, ref float screenY, out float width, out float height) public virtual void CalcContainerSize(float x, float y, MenuContainer menuContainer, bool allowScrollable, ref float screenX, ref float screenY, out float width, out float height)
{ {
Rect menuRect = menuContainer.CalcRectFromContent(); Rect menuRect = menuContainer.CalcRectFromContent();
width = Math.Min(mMaxContainerWidth, Math.Max(mMinContainerWidth, menuRect.mWidth)); width = Math.Min(mMaxContainerWidth, Math.Max(mMinContainerWidth, menuRect.mWidth));
@ -188,7 +188,7 @@ namespace Beefy.widgets
int workspaceY; int workspaceY;
int workspaceWidth; int workspaceWidth;
int workspaceHeight; int workspaceHeight;
BFApp.sApp.GetWorkspaceRect(out workspaceX, out workspaceY, out workspaceWidth, out workspaceHeight); BFApp.sApp.GetWorkspaceRectFrom((.)x, (.)y, 0, 0, out workspaceX, out workspaceY, out workspaceWidth, out workspaceHeight);
float maxY = workspaceY + workspaceHeight; float maxY = workspaceY + workspaceHeight;
@ -250,13 +250,14 @@ namespace Beefy.widgets
float screenX; float screenX;
float screenY; float screenY;
relativeWidget.SelfToRootTranslate(0, curY, out screenX, out screenY); relativeWidget.SelfToRootTranslate(0, curY, out screenX, out screenY);
screenX += relativeWidget.mWidgetWindow.mClientX;
screenY += relativeWidget.mWidgetWindow.mClientY; screenY += relativeWidget.mWidgetWindow.mClientY;
int wsX; int wsX;
int wsY; int wsY;
int wsWidth; int wsWidth;
int wsHeight; int wsHeight;
BFApp.sApp.GetWorkspaceRect(out wsX, out wsY, out wsWidth, out wsHeight); BFApp.sApp.GetWorkspaceRectFrom((.)screenX, (.)screenY, 0, 0, out wsX, out wsY, out wsWidth, out wsHeight);
float spaceLeft = (wsY + wsHeight) - (screenY); float spaceLeft = (wsY + wsHeight) - (screenY);
if (spaceLeft < minHeight) if (spaceLeft < minHeight)
{ {
@ -299,7 +300,10 @@ namespace Beefy.widgets
float screenWidth; float screenWidth;
float screenHeight; float screenHeight;
CalcContainerSize(menuContainer, allowScrollable, ref screenX, ref screenY, out screenWidth, out screenHeight); CalcContainerSize(screenX, screenY, menuContainer, allowScrollable, ref screenX, ref screenY, out screenWidth, out screenHeight);
screenWidth = Math.Max(screenWidth, 32);
screenHeight = Math.Max(screenHeight, 32);
WidgetWindow parentWindow = (relativeWidget != null) ? relativeWidget.mWidgetWindow : null; WidgetWindow parentWindow = (relativeWidget != null) ? relativeWidget.mWidgetWindow : null;
curWidgetWindow = new WidgetWindow(parentWindow, curWidgetWindow = new WidgetWindow(parentWindow,
@ -332,7 +336,7 @@ namespace Beefy.widgets
float screenWidth; float screenWidth;
float screenHeight; float screenHeight;
CalcContainerSize(menuContainer, allowScrollable, ref screenX, ref screenY, out screenWidth, out screenHeight); CalcContainerSize(x, y, menuContainer, allowScrollable, ref screenX, ref screenY, out screenWidth, out screenHeight);
curWidgetWindow.Resize((int32)(screenX), (int32)(screenY), curWidgetWindow.Resize((int32)(screenX), (int32)(screenY),
(int32)screenWidth, (int32)screenHeight); (int32)screenWidth, (int32)screenHeight);

View file

@ -88,6 +88,7 @@ public:
virtual void SetCursor(int cursor); virtual void SetCursor(int cursor);
virtual void GetDesktopResolution(int& width, int& height) = 0; virtual void GetDesktopResolution(int& width, int& height) = 0;
virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height) = 0; virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height) = 0;
virtual void GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fromHeight, int& outX, int& outY, int& outWidth, int& outHeight) { GetWorkspaceRect(outX, outY, outWidth, outHeight); }
virtual BFWindow* CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) = 0; virtual BFWindow* CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) = 0;
virtual void RemoveWindow(BFWindow* window); virtual void RemoveWindow(BFWindow* window);

View file

@ -79,6 +79,11 @@ BF_EXPORT void BF_CALLTYPE BFApp_GetWorkspaceRect(int& x, int& y, int& width, in
gBFApp->GetWorkspaceRect(x, y, width, height); gBFApp->GetWorkspaceRect(x, y, width, height);
} }
BF_EXPORT void BF_CALLTYPE BFApp_GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fromHeight, int& outX, int& outY, int& outWidth, int& outHeight)
{
gBFApp->GetWorkspaceRectFrom(fromX, fromY, fromWidth, fromHeight, outX, outY, outWidth, outHeight);
}
BF_EXPORT void BF_CALLTYPE BFApp_Create() BF_EXPORT void BF_CALLTYPE BFApp_Create()
{ {
new PlatformBFApp(); new PlatformBFApp();

View file

@ -43,6 +43,38 @@ static BOOL CALLBACK BFEnumResNameProc(
return FALSE; return FALSE;
} }
struct AdjustedMonRect
{
int mMonCount;
int mX;
int mY;
int mWidth;
int mHeight;
};
static BOOL ClipToMonitor(HMONITOR mon, HDC hdc, LPRECT monRect, LPARAM userArg)
{
AdjustedMonRect* outRect = (AdjustedMonRect*)userArg;
MONITORINFO monitorInfo = { sizeof(MONITORINFO) };
if (::GetMonitorInfo(mon, &monitorInfo) == 0)
return TRUE;
outRect->mMonCount++;
if (outRect->mX < monitorInfo.rcWork.left)
outRect->mX = monitorInfo.rcWork.left;
else if (outRect->mX + outRect->mWidth >= monitorInfo.rcWork.right)
outRect->mX = BF_MAX((int)monitorInfo.rcWork.left, monitorInfo.rcWork.right - outRect->mWidth);
if (outRect->mY < monitorInfo.rcWork.top)
outRect->mY = monitorInfo.rcWork.top;
else if (outRect->mY + outRect->mHeight >= monitorInfo.rcWork.bottom)
outRect->mY = BF_MAX((int)monitorInfo.rcWork.top, monitorInfo.rcWork.bottom - outRect->mHeight);
return TRUE;
}
WinBFWindow::WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) WinBFWindow::WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags)
{ {
HINSTANCE hInstance = GetModuleHandle(NULL); HINSTANCE hInstance = GetModuleHandle(NULL);
@ -128,18 +160,16 @@ WinBFWindow::WinBFWindow(BFWindow* parent, const StringImpl& title, int x, int y
if (windowFlags & BFWINDOW_POPUP_POSITION) if (windowFlags & BFWINDOW_POPUP_POSITION)
{ {
RECT desktopRect; AdjustedMonRect adjustRect = { 0, x, y, width, height };
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &desktopRect, NULL); RECT wantRect = { x, y, x + width, y + height };
if (x < desktopRect.left) EnumDisplayMonitors(NULL, &wantRect, ClipToMonitor, (LPARAM)&adjustRect);
x = desktopRect.left; if (adjustRect.mMonCount == 0)
else if (x + width >= desktopRect.right) EnumDisplayMonitors(NULL, NULL, ClipToMonitor, (LPARAM)&adjustRect);
x = BF_MAX((int)desktopRect.left, desktopRect.right - width); x = adjustRect.mX;
y = adjustRect.mY;
if (y < desktopRect.top) width = adjustRect.mWidth;
y = desktopRect.top; height = adjustRect.mHeight;
else if (y + height >= desktopRect.bottom)
y = BF_MAX((int)desktopRect.top, desktopRect.bottom - height);
} }
mFlags = windowFlags; mFlags = windowFlags;
@ -1128,26 +1158,70 @@ void WinBFApp::GetDesktopResolution(int& width, int& height)
height = ::GetSystemMetrics(SM_CYSCREEN); height = ::GetSystemMetrics(SM_CYSCREEN);
} }
void WinBFApp::GetWorkspaceRect(int& x, int& y, int& width, int& height) static BOOL InflateRectToMonitor(HMONITOR mon, HDC hdc, LPRECT monRect, LPARAM userArg)
{ {
RECT desktopRect; AdjustedMonRect* inflatedRect = (AdjustedMonRect*)userArg;
if (::GetSystemMetrics(SM_CMONITORS) > 1) MONITORINFO monitorInfo = { sizeof(MONITORINFO) };
if (::GetMonitorInfo(mon, &monitorInfo) == 0)
return TRUE;
inflatedRect->mMonCount++;
if (inflatedRect->mMonCount == 1)
{ {
desktopRect.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN); inflatedRect->mX = monitorInfo.rcWork.left;
desktopRect.right = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); inflatedRect->mY = monitorInfo.rcWork.top;
desktopRect.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN); inflatedRect->mWidth = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
desktopRect.bottom = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); inflatedRect->mHeight = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
} }
else else
{ {
::SystemParametersInfo(SPI_GETWORKAREA, NULL, &desktopRect, NULL); int minLeft = BF_MIN(inflatedRect->mX, monitorInfo.rcWork.left);
int minTop = BF_MIN(inflatedRect->mY, monitorInfo.rcWork.top);
int maxRight = BF_MAX(inflatedRect->mX + inflatedRect->mWidth, monitorInfo.rcWork.right);
int maxBottom = BF_MAX(inflatedRect->mY + inflatedRect->mHeight, monitorInfo.rcWork.bottom);
inflatedRect->mX = minLeft;
inflatedRect->mY = minTop;
inflatedRect->mWidth = maxRight - minLeft;
inflatedRect->mHeight = maxBottom - minTop;
} }
x = desktopRect.left; return TRUE;
y = desktopRect.top; }
width = desktopRect.right - desktopRect.left;
height = desktopRect.bottom - desktopRect.top; void WinBFApp::GetWorkspaceRect(int& x, int& y, int& width, int& height)
{
AdjustedMonRect inflateRect = { 0 };
EnumDisplayMonitors(NULL, NULL, InflateRectToMonitor, (LPARAM)&inflateRect);
x = inflateRect.mX;
y = inflateRect.mY;
width = inflateRect.mWidth;
height = inflateRect.mHeight;
}
void WinBFApp::GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fromHeight, int & outX, int & outY, int & outWidth, int & outHeight)
{
AdjustedMonRect inflateRect = { 0 };
RECT wantRect;
wantRect.left = fromX;
wantRect.top = fromY;
wantRect.right = fromX + BF_MAX(fromWidth, 1);
wantRect.bottom = fromY + BF_MAX(fromHeight, 1);
EnumDisplayMonitors(NULL, &wantRect, InflateRectToMonitor, (LPARAM)&inflateRect);
if (inflateRect.mMonCount == 0)
{
GetWorkspaceRect(outX, outY, outWidth, outHeight);
return;
}
outX = inflateRect.mX;
outY = inflateRect.mY;
outWidth = inflateRect.mWidth;
outHeight = inflateRect.mHeight;
} }
BFWindow* WinBFApp::CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) BFWindow* WinBFApp::CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags)

View file

@ -105,8 +105,9 @@ public:
virtual void Init() override; virtual void Init() override;
virtual void Run() override; virtual void Run() override;
virtual void GetDesktopResolution(int& width, int& height); virtual void GetDesktopResolution(int& width, int& height) override;
virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height); virtual void GetWorkspaceRect(int& x, int& y, int& width, int& height) override;
virtual void GetWorkspaceRectFrom(int fromX, int fromY, int fromWidth, int fromHeight, int& outX, int& outY, int& outWidth, int& outHeight) override;
virtual BFWindow* CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) override; virtual BFWindow* CreateNewWindow(BFWindow* parent, const StringImpl& title, int x, int y, int width, int height, int windowFlags) override;
virtual DrawLayer* CreateDrawLayer(BFWindow* window); virtual DrawLayer* CreateDrawLayer(BFWindow* window);

View file

@ -10572,7 +10572,7 @@ namespace IDE
// //
{ {
BFWindow.Flags flags = .Border | .ThickFrame | .Resizable | .SysMenu | BFWindow.Flags flags = .Border | .ThickFrame | .Resizable | .SysMenu |
.Caption | .Minimize | .Maximize | .QuitOnClose | .Menu; .Caption | .Minimize | .Maximize | .QuitOnClose | .Menu | .PopupPosition;
if (mRunningTestScript) if (mRunningTestScript)
flags |= .NoActivate; flags |= .NoActivate;