mirror of
https://github.com/ONLYOFFICE/desktop-apps.git
synced 2026-02-10 18:05:16 +08:00
[win-linux] add feature: thin window frame
This commit is contained in:
@ -298,8 +298,6 @@ core_windows {
|
||||
|
||||
build_xp {
|
||||
DEFINES += __OS_WIN_XP
|
||||
} else {
|
||||
LIBS += -ldwmapi
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1018,6 +1018,25 @@ namespace WindowHelper {
|
||||
::AttachThreadInput(frgID, appID, FALSE);
|
||||
}
|
||||
|
||||
auto getColorizationColor(bool isActive) -> QColor
|
||||
{
|
||||
QColor color = GetColorByRole(ecrWindowBorder);
|
||||
QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\DWM", QSettings::NativeFormat);
|
||||
if (isActive && reg.value("ColorPrevalence", 0).toInt() != 0) {
|
||||
DWORD dwcolor = 0;
|
||||
BOOL opaque = TRUE;
|
||||
static HRESULT(WINAPI *DwmGetColorizationColor)(DWORD*, BOOL*) = NULL;
|
||||
if (!DwmGetColorizationColor) {
|
||||
if (HMODULE module = GetModuleHandleA("dwmapi"))
|
||||
*(FARPROC*)&DwmGetColorizationColor = GetProcAddress(module, "DwmGetColorizationColor");
|
||||
}
|
||||
if (DwmGetColorizationColor && SUCCEEDED(DwmGetColorizationColor(&dwcolor, &opaque))) {
|
||||
color = QColor((dwcolor & 0xff0000) >> 16, (dwcolor & 0xff00) >> 8, dwcolor & 0xff);
|
||||
}
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
auto toggleLayoutDirection(HWND hwnd) -> void
|
||||
{
|
||||
LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
|
||||
@ -162,6 +162,7 @@ namespace WindowHelper {
|
||||
auto correctModalOrder(HWND windowhandle, HWND modalhandle) -> void;
|
||||
auto adjustWindowRect(HWND, double, LPRECT) -> void;
|
||||
auto bringToTop(HWND) -> void;
|
||||
auto getColorizationColor(bool isActive = true) -> QColor;
|
||||
auto toggleLayoutDirection(HWND hwnd) -> void;
|
||||
#endif
|
||||
|
||||
|
||||
@ -459,7 +459,7 @@ public:
|
||||
border = GetColorValueByRole(ecrWindowBorder);
|
||||
}
|
||||
|
||||
window->setWindowColors(QColor(QString::fromStdWString(background)), QColor(QString::fromStdWString(border)));
|
||||
window->setWindowColors(QColor(QString::fromStdWString(background)), QColor(QString::fromStdWString(border)), window->isActiveWindow());
|
||||
}
|
||||
|
||||
void changeTheme(const std::wstring& theme)
|
||||
|
||||
@ -73,6 +73,9 @@ CWindowBase::CWindowBase(const QRect& rect)
|
||||
{
|
||||
setWindowIcon(Utils::appIcon());
|
||||
m_window_rect = startRect(rect, m_dpiRatio);
|
||||
#ifdef __linux__
|
||||
setGeometry(m_window_rect); // for Windows is set in CWindowPlatform
|
||||
#endif
|
||||
}
|
||||
|
||||
CWindowBase::~CWindowBase()
|
||||
@ -95,7 +98,11 @@ QSize CWindowBase::expectedContentSize(const QRect &rc, bool extended)
|
||||
{
|
||||
double dpi = 1.0;
|
||||
QRect win_rc = startRect(rc, dpi);
|
||||
#ifdef _WIN32
|
||||
int brd = Utils::getWinVersion() < Utils::WinVer::Win10 ? MAIN_WINDOW_BORDER_WIDTH * dpi : 0;
|
||||
#else
|
||||
int brd = MAIN_WINDOW_BORDER_WIDTH * dpi;
|
||||
#endif
|
||||
return win_rc.adjusted(brd, extended ? brd : TITLE_HEIGHT * dpi + brd, -brd, -brd).size();
|
||||
}
|
||||
|
||||
@ -118,15 +125,30 @@ void CWindowBase::updateScaling(bool resize)
|
||||
}
|
||||
}
|
||||
|
||||
void CWindowBase::setWindowColors(const QColor& background, const QColor& border)
|
||||
void CWindowBase::setWindowColors(const QColor& background, const QColor& border, bool isActive)
|
||||
{
|
||||
m_brdColor = border;
|
||||
setStyleSheet(QString("QMainWindow{border:1px solid %1;"
|
||||
m_bkgColor = background;
|
||||
#ifdef _WIN32
|
||||
"border-bottom:2px solid %1;"
|
||||
QString css;
|
||||
if (Utils::getWinVersion() <= Utils::WinVer::Win7) {
|
||||
css = QString("QMainWindow{background-color: %1;}").arg(background.name());
|
||||
} else
|
||||
if (Utils::getWinVersion() < Utils::WinVer::Win10) {
|
||||
css = QString("QMainWindow{border:1px solid %1; background-color: %2;}").arg(border.name(), background.name());
|
||||
} else
|
||||
if (Utils::getWinVersion() == Utils::WinVer::Win10) {
|
||||
int brdWidth = 0;
|
||||
SystemParametersInfo(SPI_GETBORDER, 0, &brdWidth, 0);
|
||||
QColor brdColor = WindowHelper::getColorizationColor(isActive);
|
||||
css = QString("QMainWindow{border-top: %1px solid %2; background-color: %3;}").arg(QString::number(brdWidth), brdColor.name(), background.name());
|
||||
} else {
|
||||
css = QString("QMainWindow{background-color: %1;}").arg(background.name());
|
||||
}
|
||||
#else
|
||||
QString css = QString("QMainWindow{border:1px solid %1; background-color: %2;}").arg(border.name(), background.name());
|
||||
#endif
|
||||
"background-color: %2;"
|
||||
"}").arg(border.name(), background.name()));
|
||||
setStyleSheet(css);
|
||||
}
|
||||
|
||||
void CWindowBase::applyTheme(const std::wstring& theme)
|
||||
@ -134,7 +156,7 @@ void CWindowBase::applyTheme(const std::wstring& theme)
|
||||
Q_UNUSED(theme)
|
||||
QColor background = GetColorByRole(ecrWindowBackground);
|
||||
QColor border = GetColorByRole(ecrWindowBorder);
|
||||
setWindowColors(background, border);
|
||||
setWindowColors(background, border, isActiveWindow());
|
||||
}
|
||||
|
||||
/** Protected **/
|
||||
@ -298,7 +320,6 @@ void CWindowBase::showEvent(QShowEvent *event)
|
||||
QMainWindow::showEvent(event);
|
||||
if (!m_windowActivated) {
|
||||
m_windowActivated = true;
|
||||
setGeometry(m_window_rect);
|
||||
adjustGeometry();
|
||||
applyTheme(GetCurrentTheme().id());
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
#define EDITOR_WINDOW_MIN_WIDTH 920
|
||||
|
||||
#define BUTTON_MAIN_WIDTH 112
|
||||
#define MAIN_WINDOW_BORDER_WIDTH 4
|
||||
#define MAIN_WINDOW_BORDER_WIDTH 3
|
||||
#define WINDOW_TITLE_MIN_WIDTH 200
|
||||
#define TOOLBTN_HEIGHT 28
|
||||
#define TOOLBTN_WIDTH 40
|
||||
@ -58,12 +58,6 @@
|
||||
#include <memory>
|
||||
#include "components/celipsislabel.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# include <windowsx.h>
|
||||
# include <dwmapi.h>
|
||||
#endif
|
||||
|
||||
|
||||
class CWindowBase : public QMainWindow
|
||||
{
|
||||
@ -77,7 +71,7 @@ public:
|
||||
bool isCustomWindowStyle();
|
||||
void updateScaling(bool resize = true);
|
||||
virtual void adjustGeometry() = 0;
|
||||
virtual void setWindowColors(const QColor&, const QColor& border = QColor());
|
||||
virtual void setWindowColors(const QColor&, const QColor& border = QColor(), bool isActive = false);
|
||||
virtual void applyTheme(const std::wstring&);
|
||||
|
||||
protected:
|
||||
@ -105,14 +99,15 @@ protected:
|
||||
*m_boxTitleBtns = nullptr,
|
||||
*m_pMainView = nullptr;
|
||||
double m_dpiRatio;
|
||||
QColor m_brdColor;
|
||||
QColor m_brdColor,
|
||||
m_bkgColor;
|
||||
QRect m_window_rect;
|
||||
|
||||
virtual void showEvent(QShowEvent *);
|
||||
|
||||
private:
|
||||
class CWindowBasePrivate;
|
||||
std::unique_ptr<CWindowBasePrivate> pimpl;
|
||||
QRect m_window_rect;
|
||||
bool m_windowActivated;
|
||||
};
|
||||
|
||||
|
||||
@ -91,11 +91,11 @@ void CWindowPlatform::show(bool maximized)
|
||||
}
|
||||
}
|
||||
|
||||
void CWindowPlatform::setWindowColors(const QColor& background, const QColor& border)
|
||||
void CWindowPlatform::setWindowColors(const QColor& background, const QColor& border, bool isActive)
|
||||
{
|
||||
Q_UNUSED(border)
|
||||
if (!CX11Decoration::isDecorated()) {
|
||||
CWindowBase::setWindowColors(background, border);
|
||||
CWindowBase::setWindowColors(background, border, isActive);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ public:
|
||||
|
||||
void bringToTop();
|
||||
void show(bool);
|
||||
virtual void setWindowColors(const QColor&, const QColor& border = QColor()) final;
|
||||
virtual void setWindowColors(const QColor&, const QColor& border = QColor(), bool isActive = false) final;
|
||||
virtual void adjustGeometry() final;
|
||||
|
||||
protected:
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
*/
|
||||
|
||||
#include "cx11decoration.h"
|
||||
#include "windows/cwindowbase.h"
|
||||
#include "utils.h"
|
||||
#include <QX11Info>
|
||||
#include <QTimer>
|
||||
@ -40,7 +41,7 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include "platform_linux/xcbutils.h"
|
||||
|
||||
#define CUSTOM_BORDER_WIDTH 4
|
||||
#define CUSTOM_BORDER_WIDTH MAIN_WINDOW_BORDER_WIDTH
|
||||
#define MOTION_TIMER_MS 250
|
||||
|
||||
const int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;
|
||||
|
||||
@ -42,6 +42,8 @@
|
||||
#include <QCoreApplication>
|
||||
#include "utils.h"
|
||||
|
||||
#define RESIZE_AREA_PART 0.14
|
||||
|
||||
|
||||
class Caption: public QWidget
|
||||
{
|
||||
@ -63,6 +65,14 @@ private:
|
||||
return (arranging == TRUE);
|
||||
}
|
||||
|
||||
bool isResizingAvailable() {
|
||||
return Utils::getWinVersion() >= Utils::WinVer::Win10 && !IsZoomed(hwnd_root);
|
||||
}
|
||||
|
||||
bool isPointInResizeArea(int posY) {
|
||||
return posY <= RESIZE_AREA_PART * height();
|
||||
}
|
||||
|
||||
QPoint cursorPos() {
|
||||
POINT pt;
|
||||
::GetCursorPos(&pt);
|
||||
@ -85,7 +95,7 @@ private:
|
||||
QPoint pos = mapFromGlobal(QPoint(int(pt.x), int(pt.y)));
|
||||
if (!buttonAtPos(pos)) {
|
||||
::ReleaseCapture();
|
||||
::PostMessage(hwnd_root, cmd, HTCAPTION, POINTTOPOINTS(pt));
|
||||
::PostMessage(hwnd_root, cmd, isResizingAvailable() && isPointInResizeArea(pos.y()) ? HTTOP : HTCAPTION, POINTTOPOINTS(pt));
|
||||
QCoreApplication::postEvent(parent(), new QEvent(QEvent::MouseButtonPress));
|
||||
return true;
|
||||
}
|
||||
@ -112,6 +122,13 @@ private:
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
case WM_MOUSEMOVE: {
|
||||
if (isResizingAvailable()) {
|
||||
int y = GET_Y_LPARAM(msg->lParam);
|
||||
setCursor(!buttonAtPos(QPoint(GET_X_LPARAM(msg->lParam), y)) && isPointInResizeArea(y) ? Qt::SizeVerCursor : Qt::ArrowCursor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_NCLBUTTONDOWN: {
|
||||
if (Utils::getWinVersion() < Utils::WinVer::Win11)
|
||||
break;
|
||||
|
||||
@ -39,11 +39,91 @@
|
||||
#include <QWindow>
|
||||
#include <QScreen>
|
||||
#include <QJsonObject>
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
//#define UM_SNAPPING 0x02
|
||||
#define DCX_USESTYLE 0x00010000
|
||||
#define NC_AREA_WIDTH 3
|
||||
#define SKIP_EVENTS_QUEUE(callback) QTimer::singleShot(0, this, callback)
|
||||
|
||||
using WinVer = Utils::WinVer;
|
||||
|
||||
|
||||
static double GetLogicalDpi(QWidget *wgt)
|
||||
{
|
||||
#ifdef __OS_WIN_XP
|
||||
HDC hdc = GetDC(NULL);
|
||||
double dpi = (double)GetDeviceCaps(hdc, LOGPIXELSX)/96;
|
||||
ReleaseDC(NULL, hdc);
|
||||
return dpi;
|
||||
#else
|
||||
auto scr = wgt->windowHandle()->screen();
|
||||
return scr ? scr->logicalDotsPerInch()/96 : 1.0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void GetFrameMetricsForDpi(FRAME &frame, double dpi, bool maximized = false)
|
||||
{
|
||||
WinVer ver = Utils::getWinVersion();
|
||||
int row = ver == WinVer::WinXP ? 0 :
|
||||
ver <= WinVer::Win7 ? 1 :
|
||||
ver <= WinVer::Win8_1 ? 2 :
|
||||
ver <= WinVer::Win10 ? 3 : 4;
|
||||
|
||||
int column = dpi <= 1.0 ? 0 :
|
||||
dpi <= 1.25 ? 1 :
|
||||
dpi <= 1.5 ? 2 :
|
||||
dpi <= 1.75 ? 3 :
|
||||
dpi <= 2.0 ? 4 :
|
||||
dpi <= 2.25 ? 5 :
|
||||
dpi <= 2.5 ? 6 :
|
||||
dpi <= 3.0 ? 7 :
|
||||
dpi <= 3.5 ? 8 :
|
||||
dpi <= 4.0 ? 9 :
|
||||
dpi <= 4.5 ? 10 :
|
||||
dpi <= 5.0 ? 11 : 12;
|
||||
|
||||
const int left[5][13] = { // Left margin for scales 100-500%
|
||||
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
|
||||
{4, 5, 7, 8, 9, 10, 12, 14, 17, 19, 22, 24, 29}, // WinVista - Win7: for NC width 3px
|
||||
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
|
||||
};
|
||||
frame.left = left[row][column];
|
||||
|
||||
const int top[5][13] = { // Top margin for scales 100-500%
|
||||
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
|
||||
{4, 5, 7, 8, 9, 10, 12, 14, 17, 19, 22, 24, 29}, // WinVista - Win7: for NC width 3px
|
||||
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
|
||||
{31, 38, 45, 52, 58, 65, 72, 85, 99, 112, 126, 139, 167}, // Win10
|
||||
{30, 37, 43, 50, 56, 63, 69, 82, 95, 108, 121, 134, 161} // Win11
|
||||
};
|
||||
frame.top = top[row][column];
|
||||
|
||||
if (!maximized)
|
||||
return;
|
||||
|
||||
const int left_ofs[5][13] = { // Left offset for scales 100-500%
|
||||
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinXp
|
||||
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinVista - Win7
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
|
||||
};
|
||||
frame.left -= left_ofs[row][column];
|
||||
|
||||
const int top_ofs[5][13] = { // Top offset for scales 100-500%
|
||||
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinXp
|
||||
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinVista - Win7
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
|
||||
{8, 9, 11, 12, 13, 14, 16, 18, 21, 24, 27, 30, 36}, // Win10
|
||||
{7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 21, 23, 28} // Win11
|
||||
};
|
||||
frame.top -= top_ofs[row][column];
|
||||
}
|
||||
|
||||
static bool isTaskbarAutoHideOn()
|
||||
{
|
||||
APPBARDATA ABData;
|
||||
@ -51,8 +131,19 @@ static bool isTaskbarAutoHideOn()
|
||||
return (SHAppBarMessage(ABM_GETSTATE, &ABData) & ABS_AUTOHIDE) != 0;
|
||||
}
|
||||
|
||||
static bool isThemeActive()
|
||||
{
|
||||
static BOOL(WINAPI *IsThemeActive)() = NULL;
|
||||
if (!IsThemeActive) {
|
||||
if (HMODULE module = GetModuleHandleA("uxtheme"))
|
||||
*(FARPROC*)&IsThemeActive = GetProcAddress(module, "IsThemeActive");
|
||||
}
|
||||
return IsThemeActive ? (bool)IsThemeActive() : true;
|
||||
}
|
||||
|
||||
CWindowPlatform::CWindowPlatform(const QRect &rect) :
|
||||
CWindowBase(rect),
|
||||
m_dpi(1.0),
|
||||
m_hWnd(nullptr),
|
||||
m_resAreaWidth(MAIN_WINDOW_BORDER_WIDTH),
|
||||
m_borderless(true),
|
||||
@ -60,21 +151,17 @@ CWindowPlatform::CWindowPlatform(const QRect &rect) :
|
||||
m_isResizeable(true)
|
||||
// m_allowMaximize(true)
|
||||
{
|
||||
m_isThemeActive = isThemeActive();
|
||||
m_isTaskbarAutoHideOn = isTaskbarAutoHideOn();
|
||||
m_borderless = isCustomWindowStyle();
|
||||
if (AscAppManager::isRtlEnabled())
|
||||
setLayoutDirection(Qt::RightToLeft);
|
||||
setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint
|
||||
| Qt::WindowSystemMenuHint | Qt::WindowMaximizeButtonHint
|
||||
|Qt::WindowMinimizeButtonHint | Qt::MSWindowsFixedSizeDialogHint);
|
||||
m_borderless = isCustomWindowStyle();
|
||||
setGeometry(m_window_rect);
|
||||
m_hWnd = (HWND)winId();
|
||||
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE);
|
||||
style &= ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
|
||||
style |= (WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
|
||||
style |= (Utils::getWinVersion() > Utils::WinVer::Win7) ? WS_OVERLAPPEDWINDOW : WS_POPUP;
|
||||
::SetWindowLong(m_hWnd, GWL_STYLE, style);
|
||||
connect(this->window()->windowHandle(), &QWindow::screenChanged, this, [=]() {
|
||||
SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
|
||||
});
|
||||
if (m_borderless && Utils::getWinVersion() < WinVer::Win10) {
|
||||
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_CAPTION;
|
||||
::SetWindowLong(m_hWnd, GWL_STYLE, style);
|
||||
}
|
||||
|
||||
setProperty("stabilized", true);
|
||||
m_propertyTimer = new QTimer(this);
|
||||
@ -83,6 +170,11 @@ CWindowPlatform::CWindowPlatform(const QRect &rect) :
|
||||
connect(m_propertyTimer, &QTimer::timeout, this, [=]() {
|
||||
setProperty("stabilized", true);
|
||||
});
|
||||
|
||||
m_isMaximized = IsZoomed(m_hWnd);
|
||||
m_dpi = GetLogicalDpi(this);
|
||||
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
|
||||
SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
CWindowPlatform::~CWindowPlatform()
|
||||
@ -120,36 +212,36 @@ void CWindowPlatform::show(bool maximized)
|
||||
|
||||
void CWindowPlatform::adjustGeometry()
|
||||
{
|
||||
if (windowState().testFlag(Qt::WindowMinimized) || windowState().testFlag(Qt::WindowNoState)) {
|
||||
const int border = int(MAIN_WINDOW_BORDER_WIDTH * m_dpiRatio);
|
||||
setContentsMargins(border, border, border, border+1);
|
||||
m_resAreaWidth = border;
|
||||
} else
|
||||
if (windowState().testFlag(Qt::WindowMaximized)) {
|
||||
QTimer::singleShot(25, this, [=]() {
|
||||
auto rc = QApplication::desktop()->availableGeometry(this);
|
||||
const QSize offset(0, !isTaskbarAutoHideOn() ? 0 : 2);
|
||||
SetWindowPos(m_hWnd, NULL, rc.x(), rc.y(), rc.width(), rc.height() - offset.height(),
|
||||
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
|
||||
|
||||
#ifdef __OS_WIN_XP
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
#else
|
||||
int border = 0;
|
||||
if (!isTaskbarAutoHideOn() && Utils::getWinVersion() > Utils::WinVer::Win7) {
|
||||
double dpi = qApp->screenAt(geometry().center())->logicalDotsPerInch()/96;
|
||||
border = (dpi <= 1.0) ? 8 :
|
||||
(dpi == 1.25) ? 9 :
|
||||
(dpi == 1.5) ? 11 :
|
||||
(dpi == 1.75) ? 12 :
|
||||
(dpi == 2.0) ? 13 :
|
||||
(dpi == 2.25) ? 14 :
|
||||
(dpi == 2.5) ? 16 : 6 * dpi;
|
||||
}
|
||||
setContentsMargins(border, border, border, border);
|
||||
#endif
|
||||
});
|
||||
QMargins mrg;
|
||||
if (!m_borderless) {
|
||||
setContentsMargins(mrg);
|
||||
return;
|
||||
}
|
||||
if (isMaximized()) {
|
||||
if (Utils::getWinVersion() < WinVer::Win10) {
|
||||
QTimer::singleShot(25, this, [=]() {
|
||||
auto rc = QApplication::desktop()->availableGeometry(this);
|
||||
int offset = 0;
|
||||
if (Utils::getWinVersion() > WinVer::WinXP && isTaskbarAutoHideOn())
|
||||
offset += 2;
|
||||
SetWindowPos(m_hWnd, NULL, rc.x(), rc.y(), rc.width(), rc.height() - offset, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (Utils::getWinVersion() < WinVer::Win10) {
|
||||
int border = qRound(MAIN_WINDOW_BORDER_WIDTH * m_dpiRatio);
|
||||
if (Utils::getWinVersion() <= WinVer::Win7)
|
||||
border -= NC_AREA_WIDTH;
|
||||
mrg = QMargins(border, border, border, border);
|
||||
} else
|
||||
if (Utils::getWinVersion() == WinVer::Win10) {
|
||||
int brdWidth = 0;
|
||||
SystemParametersInfo(SPI_GETBORDER, 0, &brdWidth, 0);
|
||||
mrg = QMargins(0, brdWidth, 0, 0);
|
||||
}
|
||||
m_resAreaWidth = mrg.top();
|
||||
}
|
||||
setContentsMargins(mrg);
|
||||
}
|
||||
|
||||
/** Protected **/
|
||||
@ -193,40 +285,15 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_ACTIVATE: {
|
||||
#ifndef __OS_WIN_XP
|
||||
MARGINS mrg = {4, 4, 29, 4};
|
||||
if (Utils::getWinVersion() > Utils::WinVer::Win10) {
|
||||
mrg.cxLeftWidth = 1;
|
||||
mrg.cxRightWidth = 0;
|
||||
mrg.cyBottomHeight = 0;
|
||||
mrg.cyTopHeight = 0;
|
||||
}
|
||||
DwmExtendFrameIntoClientArea(m_hWnd, &mrg);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DPICHANGED: {
|
||||
setMinimumSize(0,0);
|
||||
if (AscAppManager::IsUseSystemScaling()) {
|
||||
if (WindowHelper::isLeftButtonPressed() || (m_scaleChanged && !isMaximized())) {
|
||||
RECT *prefRect = (RECT*)msg->lParam;
|
||||
setGeometry(prefRect->left, prefRect->top, prefRect->right - prefRect->left, prefRect->bottom - prefRect->top);
|
||||
}
|
||||
SKIP_EVENTS_QUEUE([=]() {
|
||||
updateScaling(false);
|
||||
});
|
||||
} else
|
||||
if (m_scaleChanged && !isMaximized()) {
|
||||
RECT *prefRect = (RECT*)msg->lParam;
|
||||
setGeometry(prefRect->left, prefRect->top, prefRect->right - prefRect->left, prefRect->bottom - prefRect->top);
|
||||
}
|
||||
m_scaleChanged = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_DISPLAYCHANGE: {
|
||||
m_scaleChanged = true;
|
||||
m_dpi = (double)HIWORD(msg->wParam)/96;
|
||||
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
|
||||
if (AscAppManager::IsUseSystemScaling())
|
||||
updateScaling(false);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -243,8 +310,17 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
|
||||
if (!m_borderless || !msg->wParam)
|
||||
break;
|
||||
NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS*)msg->lParam;
|
||||
params->rgrc[0].bottom += 1;
|
||||
*result = WVR_ALIGNLEFT | WVR_ALIGNTOP | WVR_REDRAW;
|
||||
if (!m_isThemeActive) {
|
||||
*result = m_isMaximized ? 0 : DefWindowProc(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
|
||||
return true;
|
||||
}
|
||||
*result = DefWindowProc(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
|
||||
params->rgrc[0].left -= m_frame.left;
|
||||
params->rgrc[0].top -= m_frame.top;
|
||||
params->rgrc[0].right += m_frame.left;
|
||||
params->rgrc[0].bottom += m_frame.left;
|
||||
if (m_isMaximized && m_isTaskbarAutoHideOn && (Utils::getWinVersion() >= WinVer::Win10))
|
||||
params->rgrc[0].bottom -= 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -311,9 +387,9 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
|
||||
SystemParametersInfoW(SPI_GETWORKAREA, 0, &workArea, 0);
|
||||
if (!EqualRect(&oldWorkArea, &workArea)) {
|
||||
oldWorkArea = workArea;
|
||||
QTimer::singleShot(200, this, [=]() {
|
||||
m_isTaskbarAutoHideOn = isTaskbarAutoHideOn();
|
||||
if (Utils::getWinVersion() < WinVer::Win10)
|
||||
adjustGeometry();
|
||||
});
|
||||
}
|
||||
} else if (msg->wParam == 0) {
|
||||
const std::wstring param{(wchar_t*)msg->lParam};
|
||||
@ -401,20 +477,72 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
|
||||
// m_allowMaximize = false;
|
||||
// break;
|
||||
|
||||
case WM_SIZING:
|
||||
if (m_borderless)
|
||||
RedrawWindow(msg->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
return false;
|
||||
|
||||
case WM_NCPAINT: {
|
||||
if (Utils::getWinVersion() > WinVer::Win7 || !m_borderless)
|
||||
break;
|
||||
if (HDC hdc = ::GetDCEx(msg->hwnd, 0, DCX_WINDOW | DCX_USESTYLE)) {
|
||||
RECT rcc, rcw;
|
||||
::GetClientRect(msg->hwnd, &rcc);
|
||||
::GetWindowRect(msg->hwnd, &rcw);
|
||||
POINT pt;
|
||||
pt.x = rcw.left;
|
||||
pt.y = rcw.top;
|
||||
::MapWindowPoints(0, msg->hwnd, (LPPOINT)&rcw, (sizeof(RECT)/sizeof(POINT)));
|
||||
::OffsetRect(&rcc, -rcw.left, -rcw.top);
|
||||
::OffsetRect(&rcw, -rcw.left, -rcw.top);
|
||||
HRGN rgntemp = NULL;
|
||||
if (msg->wParam == NULLREGION || msg->wParam == ERROR) {
|
||||
::ExcludeClipRect(hdc, rcc.left, rcc.top, rcc.right, rcc.bottom);
|
||||
} else {
|
||||
rgntemp = ::CreateRectRgn(rcc.left + pt.x, rcc.top + pt.y, rcc.right + pt.x, rcc.bottom + pt.y);
|
||||
if (::CombineRgn(rgntemp, (HRGN)msg->wParam, rgntemp, RGN_DIFF) == NULLREGION) {
|
||||
// nothing to paint
|
||||
}
|
||||
::OffsetRgn(rgntemp, -pt.x, -pt.y);
|
||||
::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
|
||||
}
|
||||
HBRUSH hbrushBkg = ::CreateSolidBrush(RGB(m_bkgColor.red(), m_bkgColor.green(), m_bkgColor.blue()));
|
||||
::FillRect(hdc, &rcw, hbrushBkg);
|
||||
::DeleteObject(hbrushBkg);
|
||||
|
||||
// HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
|
||||
// GetWindowRgn(msg->hwnd, hrgn);
|
||||
HBRUSH hbrushBrd = ::CreateSolidBrush(RGB(m_brdColor.red(), m_brdColor.green(), m_brdColor.blue()));
|
||||
::FrameRect(hdc, &rcw, hbrushBrd); // Drawing NC border when using ~WS_CAPTION
|
||||
// ::FrameRgn(hdc, hrgn, hbrushBrd, 1, 1); // Drawing NC border when using WS_CAPTION
|
||||
::DeleteObject(hbrushBrd);
|
||||
// ::DeleteObject(hrgn);
|
||||
|
||||
::ReleaseDC(msg->hwnd, hdc);
|
||||
if (rgntemp != 0)
|
||||
::DeleteObject(rgntemp);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_ERASEBKGND:
|
||||
return true;
|
||||
|
||||
case WM_NCACTIVATE: {
|
||||
// Prevent the title bar from being drawn when the window is restored or maximized
|
||||
if (m_borderless) {
|
||||
if (!LOWORD(msg->wParam)) {
|
||||
*result = TRUE;
|
||||
break;
|
||||
if (Utils::getWinVersion() > WinVer::WinXP && Utils::getWinVersion() < WinVer::Win10) {
|
||||
// Prevent drawing of inactive system frame (needs ~WS_CAPTION or temporary ~WS_VISIBLE to work)
|
||||
*result = DefWindowProc(msg->hwnd, WM_NCACTIVATE, msg->wParam, -1);
|
||||
return true;
|
||||
} else
|
||||
if (Utils::getWinVersion() == WinVer::Win10) {
|
||||
CWindowBase::setWindowColors(m_bkgColor, m_brdColor, LOWORD(msg->wParam));
|
||||
repaint();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -431,6 +559,22 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_GETMINMAXINFO: {
|
||||
bool isMaximized = (bool)IsZoomed(msg->hwnd);
|
||||
if (m_isMaximized != isMaximized) {
|
||||
m_isMaximized = isMaximized;
|
||||
GetFrameMetricsForDpi(m_frame, m_dpi, isMaximized);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_THEMECHANGED: {
|
||||
bool _isThemeActive = isThemeActive();
|
||||
if (m_isThemeActive != _isThemeActive)
|
||||
m_isThemeActive = _isThemeActive;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -37,6 +37,16 @@
|
||||
#include <QtWidgets/QApplication>
|
||||
|
||||
|
||||
struct FRAME {
|
||||
FRAME() : left(0), top(0)
|
||||
{}
|
||||
FRAME(FRAME &frame) {
|
||||
left = frame.left;
|
||||
top = frame.top;
|
||||
}
|
||||
int left, top;
|
||||
};
|
||||
|
||||
class CWindowPlatform : public CWindowBase
|
||||
{
|
||||
public:
|
||||
@ -59,12 +69,17 @@ private:
|
||||
virtual bool nativeEvent(const QByteArray&, void*, long*) final;
|
||||
|
||||
QTimer *m_propertyTimer;
|
||||
double m_dpi;
|
||||
HWND m_hWnd;
|
||||
int m_resAreaWidth;
|
||||
FRAME m_frame;
|
||||
bool m_borderless,
|
||||
m_closed,
|
||||
m_isResizeable,
|
||||
// m_allowMaximize,
|
||||
m_isMaximized = false,
|
||||
m_isThemeActive = true,
|
||||
m_isTaskbarAutoHideOn = false,
|
||||
m_scaleChanged = false,
|
||||
m_isSessionInProgress = true;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user