From 76d12a3db2a9e6ef9462670ff0d237463b7ae445 Mon Sep 17 00:00:00 2001 From: Matej Svec Date: Mon, 2 Jul 2018 23:24:19 +0200 Subject: [PATCH] Add monitor override --- DATA/DSfix.ini | 6 +++ Settings.cpp | 2 + Settings.def | 1 + WindowManager.cpp | 99 +++++++++++++++++++++++++++++++---------------- WindowManager.h | 2 + 5 files changed, 76 insertions(+), 34 deletions(-) diff --git a/DATA/DSfix.ini b/DATA/DSfix.ini index 5d1bd8d..bd57d23 100644 --- a/DATA/DSfix.ini +++ b/DATA/DSfix.ini @@ -150,6 +150,12 @@ hudBottomRightOpacity 0.5f # 1 = enable borderlessFullscreen 0 +# Monitor override +# -1 = no override (the main/nearest screen) +# N = use monitor N (starts with 0, -1 is used if it is not found) +# This setting is for multiple monitors, everyone else should leave it at -1. +monitorOverride -1 + # disable cursor at startup # 0 = no change # 1 = off at start diff --git a/Settings.cpp b/Settings.cpp index 7c6772a..43f529c 100644 --- a/Settings.cpp +++ b/Settings.cpp @@ -52,6 +52,8 @@ void Settings::report() { void Settings::init() { if(!inited) { + auto const monitor_id = getMonitorOverride(); + WindowManager::get().overrideMonitor(monitor_id); if(getDisableCursor()) WindowManager::get().toggleCursorVisibility(); if(getCaptureCursor()) WindowManager::get().toggleCursorCapture(); if(getBorderlessFullscreen()) WindowManager::get().toggleBorderlessFullscreen(); diff --git a/Settings.def b/Settings.def index ff0b35b..6791a34 100644 --- a/Settings.def +++ b/Settings.def @@ -66,6 +66,7 @@ SETTING(float, HudBottomRightOpacity, "hudBottomRightOpacity", 1.0f) // Screen Options SETTING(bool, BorderlessFullscreen, "borderlessFullscreen", false); +SETTING(int, MonitorOverride, "monitorOverride", -1); SETTING(bool, ForceFullscreen, "forceFullscreen", false); SETTING(bool, ForceWindowed, "forceWindowed", false); SETTING(unsigned, PresentWidth, "presentWidth", 0); diff --git a/WindowManager.cpp b/WindowManager.cpp index 196cdc4..d2e1ac6 100644 --- a/WindowManager.cpp +++ b/WindowManager.cpp @@ -1,17 +1,18 @@ #include "WindowManager.h" +#include WindowManager WindowManager::instance; -void WindowManager::applyCursorCapture() { - if(captureCursor) { - RECT clientrect; - HWND hwnd = ::GetActiveWindow(); - ::GetClientRect(hwnd, &clientrect); +void WindowManager::applyCursorCapture() { + if(captureCursor) { + RECT clientrect; + HWND hwnd = ::GetActiveWindow(); + ::GetClientRect(hwnd, &clientrect); ::ClientToScreen(hwnd, (LPPOINT)&clientrect.left); - ::ClientToScreen(hwnd, (LPPOINT)&clientrect.right); - ::ClipCursor(&clientrect); - } else { - ::ClipCursor(NULL); + ::ClientToScreen(hwnd, (LPPOINT)&clientrect.right); + ::ClipCursor(&clientrect); + } else { + ::ClipCursor(NULL); } } @@ -19,18 +20,18 @@ void WindowManager::toggleCursorCapture() { captureCursor = !captureCursor; } -void WindowManager::toggleCursorVisibility() { - cursorVisible = !cursorVisible; +void WindowManager::toggleCursorVisibility() { + cursorVisible = !cursorVisible; ::ShowCursor(cursorVisible); } -void WindowManager::toggleBorderlessFullscreen() { - borderlessFullscreen = !borderlessFullscreen; - HWND hwnd = ::GetActiveWindow(); - if(borderlessFullscreen) { - // store previous rect - ::GetClientRect(hwnd, &prevWindowRect); - // set styles +void WindowManager::toggleBorderlessFullscreen() { + borderlessFullscreen = !borderlessFullscreen; + HWND hwnd = ::GetActiveWindow(); + if(borderlessFullscreen) { + // store previous rect + ::GetClientRect(hwnd, &prevWindowRect); + // set styles LONG lStyle = ::GetWindowLong(hwnd, GWL_STYLE); prevStyle = lStyle; lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU); @@ -40,13 +41,9 @@ void WindowManager::toggleBorderlessFullscreen() { lExStyle &= ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE); ::SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle); // adjust size & position - HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(monitor, &info); - int monitorWidth = info.rcMonitor.right - info.rcMonitor.left; - int monitorHeight = info.rcMonitor.bottom - info.rcMonitor.top; - ::SetWindowPos(hwnd, NULL, info.rcMonitor.left, info.rcMonitor.top, monitorWidth, monitorHeight, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER); + int monitorWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; + int monitorHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; + ::SetWindowPos(hwnd, NULL, monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top, monitorWidth, monitorHeight, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER); } else { // restore previous window ::SetWindowLong(hwnd, GWL_STYLE, prevStyle); @@ -63,23 +60,57 @@ void WindowManager::resize(unsigned clientW, unsigned clientH) { // Store current window rect ::GetClientRect(hwnd, &prevWindowRect); // Get monitor size - HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - MONITORINFO info; - info.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(monitor, &info); - int monitorWidth = info.rcMonitor.right - info.rcMonitor.left; - int monitorHeight = info.rcMonitor.bottom - info.rcMonitor.top; + int monitorWidth = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left; + int monitorHeight = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top; // How much do we overlap or are smaller than the actual screen size int widthDiff = monitorWidth - (clientW ? clientW : prevWindowRect.right); int heightDiff = monitorHeight - (clientH ? clientH : prevWindowRect.bottom); RECT desiredRect; - desiredRect.left = widthDiff / 2; - desiredRect.top = heightDiff / 2; + desiredRect.left = monitorInfo.rcMonitor.left + widthDiff / 2; + desiredRect.top = monitorInfo.rcMonitor.top + heightDiff / 2; desiredRect.right = monitorWidth - (widthDiff / 2); - desiredRect.bottom = monitorHeight - (heightDiff / 2); + desiredRect.bottom = monitorHeight - (heightDiff / 2); LONG lStyle = ::GetWindowLong(hwnd, GWL_STYLE); ::AdjustWindowRect(&desiredRect, lStyle, false); ::SetWindowPos(hwnd, NULL, desiredRect.left, desiredRect.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE); } + +BOOL CALLBACK monitorEnumProc( + HMONITOR hMonitor, + HDC hdcMonitor, + LPRECT lprcMonitor, + LPARAM dwData +) { + static int i = 0; + + const auto data = reinterpret_cast*>(dwData); + if (i++ == data->second) + { + data->first->cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hMonitor, data->first); + return FALSE; + } + return TRUE; +} + +void WindowManager::overrideMonitor(int monitor_id) { + // If there is a monitor given, tries to find it + if (monitor_id != -1) + { + monitorInfo.cbSize = 0; + std::pair data{ &monitorInfo, monitor_id }; + EnumDisplayMonitors(nullptr, nullptr, monitorEnumProc, reinterpret_cast(&data)); + if (monitorInfo.cbSize != 0) + { + return; + } + } + + // If there is no override, uses the 'nearest' monitor to the current window + HWND hwnd = ::GetActiveWindow(); + HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitor, &monitorInfo); +} diff --git a/WindowManager.h b/WindowManager.h index 0d57ca4..cc07417 100644 --- a/WindowManager.h +++ b/WindowManager.h @@ -10,6 +10,7 @@ class WindowManager { bool borderlessFullscreen; RECT prevWindowRect; long prevStyle, prevExStyle; + MONITORINFO monitorInfo; public: static WindowManager& get() { @@ -22,4 +23,5 @@ class WindowManager { void toggleCursorVisibility(); void toggleBorderlessFullscreen(); void resize(unsigned clientW, unsigned clientH); + void overrideMonitor(int monitor_id); };