forked from github_mirror/framelesshelper
win32: nitpck: don't highlight the first entry of the system menu if brought by mouse
Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
92ab78e281
commit
3525dfee58
|
@ -70,8 +70,9 @@ FRAMELESSHELPER_CORE_API void syncWmPaintWithDwm();
|
||||||
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
FRAMELESSHELPER_CORE_API void showSystemMenu(
|
||||||
const WId windowId,
|
const WId windowId,
|
||||||
const QPoint &pos,
|
const QPoint &pos,
|
||||||
const Global::Options options,
|
|
||||||
const QPoint &offset,
|
const QPoint &offset,
|
||||||
|
const bool selectFirstEntry,
|
||||||
|
const Global::Options options,
|
||||||
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
const Global::IsWindowFixedSizeCallback &isWindowFixedSize);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmColorizationColor();
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode();
|
[[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode();
|
||||||
|
|
|
@ -225,6 +225,7 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
||||||
return {windowPos.left + horizontalOffset, windowPos.top + verticalOffset};
|
return {windowPos.left + horizontalOffset, windowPos.top + verticalOffset};
|
||||||
};
|
};
|
||||||
bool shouldShowSystemMenu = false;
|
bool shouldShowSystemMenu = false;
|
||||||
|
bool broughtByKeyboard = false;
|
||||||
QPoint globalPos = {};
|
QPoint globalPos = {};
|
||||||
if (uMsg == WM_NCRBUTTONUP) {
|
if (uMsg == WM_NCRBUTTONUP) {
|
||||||
if (wParam == HTCAPTION) {
|
if (wParam == HTCAPTION) {
|
||||||
|
@ -235,6 +236,7 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
||||||
const WPARAM filteredWParam = (wParam & 0xFFF0);
|
const WPARAM filteredWParam = (wParam & 0xFFF0);
|
||||||
if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
|
if ((filteredWParam == SC_KEYMENU) && (lParam == VK_SPACE)) {
|
||||||
shouldShowSystemMenu = true;
|
shouldShowSystemMenu = true;
|
||||||
|
broughtByKeyboard = true;
|
||||||
globalPos = getGlobalPosFromKeyboard();
|
globalPos = getGlobalPosFromKeyboard();
|
||||||
}
|
}
|
||||||
} else if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) {
|
} else if ((uMsg == WM_KEYDOWN) || (uMsg == WM_SYSKEYDOWN)) {
|
||||||
|
@ -242,11 +244,13 @@ static const QString successErrorText = QStringLiteral("The operation completed
|
||||||
const bool spacePressed = ((wParam == VK_SPACE) || (GetKeyState(VK_SPACE) < 0));
|
const bool spacePressed = ((wParam == VK_SPACE) || (GetKeyState(VK_SPACE) < 0));
|
||||||
if (altPressed && spacePressed) {
|
if (altPressed && spacePressed) {
|
||||||
shouldShowSystemMenu = true;
|
shouldShowSystemMenu = true;
|
||||||
|
broughtByKeyboard = true;
|
||||||
globalPos = getGlobalPosFromKeyboard();
|
globalPos = getGlobalPosFromKeyboard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shouldShowSystemMenu) {
|
if (shouldShowSystemMenu) {
|
||||||
Utils::showSystemMenu(windowId, globalPos, data.options, data.offset, data.isWindowFixedSize);
|
Utils::showSystemMenu(windowId, globalPos, data.offset,
|
||||||
|
broughtByKeyboard, data.options, data.isWindowFixedSize);
|
||||||
// QPA's internal code will handle system menu events separately, and its
|
// QPA's internal code will handle system menu events separately, and its
|
||||||
// behavior is not what we would want to see because it doesn't know our
|
// behavior is not what we would want to see because it doesn't know our
|
||||||
// window doesn't have any window frame now, so return early here to avoid
|
// window doesn't have any window frame now, so return early here to avoid
|
||||||
|
@ -493,8 +497,9 @@ DwmColorizationArea Utils::getDwmColorizationArea()
|
||||||
return DwmColorizationArea::None;
|
return DwmColorizationArea::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const Options options,
|
void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const QPoint &offset,
|
||||||
const QPoint &offset, const IsWindowFixedSizeCallback &isWindowFixedSize)
|
const bool selectFirstEntry, const Options options,
|
||||||
|
const IsWindowFixedSizeCallback &isWindowFixedSize)
|
||||||
{
|
{
|
||||||
Q_ASSERT(windowId);
|
Q_ASSERT(windowId);
|
||||||
Q_ASSERT(isWindowFixedSize);
|
Q_ASSERT(isWindowFixedSize);
|
||||||
|
@ -502,54 +507,45 @@ void Utils::showSystemMenu(const WId windowId, const QPoint &pos, const Options
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto hWnd = reinterpret_cast<HWND>(windowId);
|
const auto hWnd = reinterpret_cast<HWND>(windowId);
|
||||||
const HMENU menu = GetSystemMenu(hWnd, FALSE);
|
const HMENU hMenu = GetSystemMenu(hWnd, FALSE);
|
||||||
if (!menu) {
|
if (!hMenu) {
|
||||||
// The corresponding window doesn't have a menu, this isn't an error,
|
// The corresponding window doesn't have a system menu, most likely due to the
|
||||||
// so just ignore it.
|
// lack of the "WS_SYSMENU" window style. This situation should not be treated
|
||||||
|
// as an error so just ignore it and return early.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MENUITEMINFOW mii;
|
|
||||||
SecureZeroMemory(&mii, sizeof(mii));
|
|
||||||
mii.cbSize = sizeof(mii);
|
|
||||||
mii.fMask = MIIM_STATE;
|
|
||||||
mii.fType = MFT_STRING;
|
|
||||||
const auto setState = [&mii, menu](const UINT item, const bool enabled, const bool highlight) -> bool {
|
|
||||||
mii.fState = ((enabled ? MFS_ENABLED : MFS_DISABLED) | (highlight ? MFS_HILITE : MFS_UNHILITE));
|
|
||||||
if (SetMenuItemInfoW(menu, item, FALSE, &mii) == FALSE) {
|
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetMenuItemInfoW"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
const bool maxOrFull = (IsMaximized(hWnd) ||
|
const bool maxOrFull = (IsMaximized(hWnd) ||
|
||||||
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(windowId)));
|
((options & Option::DontTreatFullScreenAsZoomed) ? false : isFullScreen(windowId)));
|
||||||
const bool fixedSize = isWindowFixedSize();
|
const bool fixedSize = isWindowFixedSize();
|
||||||
if (!setState(SC_RESTORE, (maxOrFull && !fixedSize), true)) {
|
EnableMenuItem(hMenu, SC_RESTORE, (MF_BYCOMMAND | ((maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
return;
|
// The first menu item should be selected by default if the menu is brought
|
||||||
}
|
// by keyboard. I don't know how to pre-select a menu item but it seems
|
||||||
if (!setState(SC_MOVE, (!maxOrFull && !(options & Option::DisableDragging)), false)) {
|
// highlight can do the job. However, there's an annoying issue if we do
|
||||||
return;
|
// this manually: the highlighted menu item is really only highlighted,
|
||||||
}
|
// not selected, so even if the mouse cursor hovers on other menu items
|
||||||
if (!setState(SC_SIZE, (!maxOrFull && !fixedSize), false)) {
|
// or the user navigates to other menu items through keyboard, the original
|
||||||
return;
|
// highlight bar will not move accordingly, the OS will generate another
|
||||||
}
|
// highlight bar to indicate the current selected menu item, which will make
|
||||||
if (!setState(SC_MINIMIZE, true, false)) {
|
// the menu look kind of weird. Currently I don't know how to fix this issue.
|
||||||
return;
|
HiliteMenuItem(hWnd, hMenu, SC_RESTORE, (MF_BYCOMMAND | (selectFirstEntry ? MFS_HILITE : MFS_UNHILITE)));
|
||||||
}
|
EnableMenuItem(hMenu, SC_MOVE, (MF_BYCOMMAND | ((!maxOrFull && !(options & Option::DisableDragging)) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
if (!setState(SC_MAXIMIZE, (!maxOrFull && !fixedSize), false)) {
|
EnableMenuItem(hMenu, SC_SIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
return;
|
EnableMenuItem(hMenu, SC_MINIMIZE, (MF_BYCOMMAND | MFS_ENABLED));
|
||||||
}
|
EnableMenuItem(hMenu, SC_MAXIMIZE, (MF_BYCOMMAND | ((!maxOrFull && !fixedSize) ? MFS_ENABLED : MFS_DISABLED)));
|
||||||
if (!setState(SC_CLOSE, true, false)) {
|
EnableMenuItem(hMenu, SC_CLOSE, (MF_BYCOMMAND | MFS_ENABLED));
|
||||||
return;
|
// The default menu item will appear in bold font. There can only be one default
|
||||||
}
|
// menu item per menu at most. Set the item ID to "UINT_MAX" (or simply "-1")
|
||||||
if (SetMenuDefaultItem(menu, SC_CLOSE, FALSE) == FALSE) {
|
// can clear the default item for the given menu.
|
||||||
qWarning() << getSystemErrorMessage(QStringLiteral("SetMenuDefaultItem"));
|
SetMenuDefaultItem(hMenu, SC_CLOSE, FALSE);
|
||||||
return;
|
// If you need to adjust the menu popup position (such as in a fully
|
||||||
}
|
// customized window frame), you should pass in the "offset" parameter.
|
||||||
|
// But it will not be needed when the window is maximized or fullscreen
|
||||||
|
// because in that case the menu should always align to the left edge
|
||||||
|
// of the screen.
|
||||||
const QPoint adjustment = (maxOrFull ? QPoint(0, 0) : offset);
|
const QPoint adjustment = (maxOrFull ? QPoint(0, 0) : offset);
|
||||||
const int xPos = (pos.x() + adjustment.x());
|
const int xPos = (pos.x() + adjustment.x());
|
||||||
const int yPos = (pos.y() + adjustment.y());
|
const int yPos = (pos.y() + adjustment.y());
|
||||||
const int ret = TrackPopupMenu(menu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
|
const int ret = TrackPopupMenu(hMenu, (TPM_RETURNCMD | (QGuiApplication::isRightToLeft()
|
||||||
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), xPos, yPos, 0, hWnd, nullptr);
|
? TPM_RIGHTALIGN : TPM_LEFTALIGN)), xPos, yPos, 0, hWnd, nullptr);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (PostMessageW(hWnd, WM_SYSCOMMAND, ret, 0) == FALSE) {
|
if (PostMessageW(hWnd, WM_SYSCOMMAND, ret, 0) == FALSE) {
|
||||||
|
|
|
@ -345,8 +345,8 @@ void FramelessQuickWindowPrivate::showSystemMenu(const QPoint &pos)
|
||||||
Q_Q(FramelessQuickWindow);
|
Q_Q(FramelessQuickWindow);
|
||||||
const QPoint globalPos = q->mapToGlobal(pos);
|
const QPoint globalPos = q->mapToGlobal(pos);
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
const QPoint nativePos = QPointF(QPointF(globalPos) * q->effectiveDevicePixelRatio()).toPoint();
|
||||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.options,
|
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.systemMenuOffset,
|
||||||
m_settings.systemMenuOffset, m_params.isWindowFixedSize);
|
false, m_settings.options, m_params.isWindowFixedSize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -690,8 +690,8 @@ void FramelessWidgetsHelper::showSystemMenu(const QPoint &pos)
|
||||||
#ifdef Q_OS_WINDOWS
|
#ifdef Q_OS_WINDOWS
|
||||||
const QPoint globalPos = q->mapToGlobal(pos);
|
const QPoint globalPos = q->mapToGlobal(pos);
|
||||||
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
const QPoint nativePos = QPointF(QPointF(globalPos) * q->devicePixelRatioF()).toPoint();
|
||||||
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.options,
|
Utils::showSystemMenu(m_params.windowId, nativePos, m_settings.systemMenuOffset,
|
||||||
m_settings.systemMenuOffset, m_params.isWindowFixedSize);
|
false, m_settings.options, m_params.isWindowFixedSize);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue