Refine new editor shell host and embedded icons
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "BorderlessWindowChrome.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <dwmapi.h>
|
||||
|
||||
namespace XCEngine::UI::Editor::Host {
|
||||
@@ -12,6 +13,12 @@ using ::XCEngine::UI::UIDrawList;
|
||||
using ::XCEngine::UI::UIPoint;
|
||||
using ::XCEngine::UI::UIRect;
|
||||
|
||||
constexpr UIColor kTransparentColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
float ResolveGlyphBoxSize(const UIRect& rect, float ratio, float minSize) {
|
||||
return (std::max)(minSize, static_cast<float>(std::round(rect.height * ratio)));
|
||||
}
|
||||
|
||||
bool IsPointInsideRect(const UIRect& rect, const UIPoint& point) {
|
||||
return rect.width > 0.0f &&
|
||||
rect.height > 0.0f &&
|
||||
@@ -28,8 +35,8 @@ void AppendMinimizeGlyph(
|
||||
float thickness) {
|
||||
const float centerX = rect.x + rect.width * 0.5f;
|
||||
const float centerY = rect.y + rect.height * 0.5f;
|
||||
const float halfWidth = (std::max)(4.0f, rect.height * 0.22f);
|
||||
const float y = centerY + rect.height * 0.12f;
|
||||
const float halfWidth = ResolveGlyphBoxSize(rect, 0.38f, 10.0f) * 0.5f;
|
||||
const float y = centerY;
|
||||
drawList.AddLine(
|
||||
UIPoint(centerX - halfWidth, y),
|
||||
UIPoint(centerX + halfWidth, y),
|
||||
@@ -44,15 +51,16 @@ void AppendMaximizeGlyph(
|
||||
float thickness) {
|
||||
const float centerX = rect.x + rect.width * 0.5f;
|
||||
const float centerY = rect.y + rect.height * 0.5f;
|
||||
const float halfExtent = (std::max)(4.0f, rect.height * 0.20f);
|
||||
drawList.AddRectOutline(
|
||||
UIRect(
|
||||
centerX - halfExtent,
|
||||
centerY - halfExtent,
|
||||
halfExtent * 2.0f,
|
||||
halfExtent * 2.0f),
|
||||
color,
|
||||
thickness);
|
||||
const float boxSize = ResolveGlyphBoxSize(rect, 0.32f, 9.0f);
|
||||
const float halfExtent = boxSize * 0.5f;
|
||||
const float left = centerX - halfExtent;
|
||||
const float top = centerY - halfExtent;
|
||||
const float right = left + boxSize;
|
||||
const float bottom = top + boxSize;
|
||||
drawList.AddLine(UIPoint(left, top), UIPoint(right, top), color, thickness);
|
||||
drawList.AddLine(UIPoint(left, top), UIPoint(left, bottom), color, thickness);
|
||||
drawList.AddLine(UIPoint(right, top), UIPoint(right, bottom), color, thickness);
|
||||
drawList.AddLine(UIPoint(left, bottom), UIPoint(right, bottom), color, thickness);
|
||||
}
|
||||
|
||||
void AppendRestoreGlyph(
|
||||
@@ -62,24 +70,30 @@ void AppendRestoreGlyph(
|
||||
float thickness) {
|
||||
const float centerX = rect.x + rect.width * 0.5f;
|
||||
const float centerY = rect.y + rect.height * 0.5f;
|
||||
const float halfExtent = (std::max)(4.0f, rect.height * 0.18f);
|
||||
const float offset = 2.0f;
|
||||
drawList.AddRectOutline(
|
||||
UIRect(
|
||||
centerX - halfExtent + offset,
|
||||
centerY - halfExtent - offset,
|
||||
halfExtent * 2.0f,
|
||||
halfExtent * 2.0f),
|
||||
color,
|
||||
thickness);
|
||||
drawList.AddRectOutline(
|
||||
UIRect(
|
||||
centerX - halfExtent - offset,
|
||||
centerY - halfExtent + offset,
|
||||
halfExtent * 2.0f,
|
||||
halfExtent * 2.0f),
|
||||
color,
|
||||
thickness);
|
||||
const float boxSize = ResolveGlyphBoxSize(rect, 0.29f, 8.0f);
|
||||
const float halfExtent = boxSize * 0.5f;
|
||||
const float offset = 1.0f;
|
||||
|
||||
const float backLeft = centerX - halfExtent + offset;
|
||||
const float backTop = centerY - halfExtent - offset;
|
||||
const float backRight = backLeft + boxSize;
|
||||
const float backBottom = backTop + boxSize;
|
||||
|
||||
const float frontLeft = centerX - halfExtent - offset;
|
||||
const float frontTop = centerY - halfExtent + offset;
|
||||
const float frontRight = frontLeft + boxSize;
|
||||
const float frontBottom = frontTop + boxSize;
|
||||
|
||||
// Only draw the exposed segments of the back window.
|
||||
drawList.AddLine(UIPoint(backLeft, backTop), UIPoint(backRight, backTop), color, thickness);
|
||||
drawList.AddLine(UIPoint(backLeft, backTop), UIPoint(backLeft, frontTop), color, thickness);
|
||||
drawList.AddLine(UIPoint(backRight, backTop), UIPoint(backRight, backBottom), color, thickness);
|
||||
drawList.AddLine(UIPoint(frontRight, backBottom), UIPoint(backRight, backBottom), color, thickness);
|
||||
|
||||
drawList.AddLine(UIPoint(frontLeft, frontTop), UIPoint(frontRight, frontTop), color, thickness);
|
||||
drawList.AddLine(UIPoint(frontLeft, frontTop), UIPoint(frontLeft, frontBottom), color, thickness);
|
||||
drawList.AddLine(UIPoint(frontRight, frontTop), UIPoint(frontRight, frontBottom), color, thickness);
|
||||
drawList.AddLine(UIPoint(frontLeft, frontBottom), UIPoint(frontRight, frontBottom), color, thickness);
|
||||
}
|
||||
|
||||
void AppendCloseGlyph(
|
||||
@@ -89,7 +103,7 @@ void AppendCloseGlyph(
|
||||
float thickness) {
|
||||
const float centerX = rect.x + rect.width * 0.5f;
|
||||
const float centerY = rect.y + rect.height * 0.5f;
|
||||
const float halfWidth = (std::max)(4.0f, rect.height * 0.20f);
|
||||
const float halfWidth = ResolveGlyphBoxSize(rect, 0.29f, 8.0f) * 0.5f;
|
||||
const float halfHeight = halfWidth;
|
||||
drawList.AddLine(
|
||||
UIPoint(centerX - halfWidth, centerY - halfHeight),
|
||||
@@ -116,7 +130,7 @@ void AppendCloseGlyph(
|
||||
if (hovered) {
|
||||
return palette.closeButtonHoverColor;
|
||||
}
|
||||
return {};
|
||||
return kTransparentColor;
|
||||
}
|
||||
|
||||
if (pressed) {
|
||||
@@ -125,7 +139,7 @@ void AppendCloseGlyph(
|
||||
if (hovered) {
|
||||
return palette.buttonHoverColor;
|
||||
}
|
||||
return {};
|
||||
return kTransparentColor;
|
||||
}
|
||||
|
||||
::XCEngine::UI::UIColor ResolveIconColor(
|
||||
@@ -207,6 +221,54 @@ void ApplyDwmBoolWindowAttribute(HWND hwnd, DWORD attribute, BOOL value) {
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyDwmColorWindowAttribute(HWND hwnd, DWORD attribute, COLORREF value) {
|
||||
if (hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD);
|
||||
static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn {
|
||||
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
|
||||
if (dwmapi == nullptr) {
|
||||
dwmapi = LoadLibraryW(L"dwmapi.dll");
|
||||
}
|
||||
if (dwmapi == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<DwmSetWindowAttributeFn>(
|
||||
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
|
||||
}();
|
||||
|
||||
if (setWindowAttribute != nullptr) {
|
||||
setWindowAttribute(hwnd, attribute, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyDwmIntWindowAttribute(HWND hwnd, DWORD attribute, int value) {
|
||||
if (hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
using DwmSetWindowAttributeFn = HRESULT(WINAPI*)(HWND, DWORD, LPCVOID, DWORD);
|
||||
static const auto setWindowAttribute = []() -> DwmSetWindowAttributeFn {
|
||||
HMODULE dwmapi = GetModuleHandleW(L"dwmapi.dll");
|
||||
if (dwmapi == nullptr) {
|
||||
dwmapi = LoadLibraryW(L"dwmapi.dll");
|
||||
}
|
||||
if (dwmapi == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return reinterpret_cast<DwmSetWindowAttributeFn>(
|
||||
GetProcAddress(dwmapi, "DwmSetWindowAttribute"));
|
||||
}();
|
||||
|
||||
if (setWindowAttribute != nullptr) {
|
||||
setWindowAttribute(hwnd, attribute, &value, sizeof(value));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
BorderlessWindowChromeLayout BuildBorderlessWindowChromeLayout(
|
||||
@@ -353,7 +415,13 @@ void RefreshBorderlessWindowDwmDecorations(HWND hwnd) {
|
||||
// Borderless host cannot participate in compositor-driven minimize/maximize
|
||||
// transitions without Windows stretching the last presented client frame.
|
||||
// Disable those transitions for this window, then refresh the shadow state.
|
||||
ApplyDwmIntWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, DWMNCRP_DISABLED);
|
||||
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_ALLOW_NCPAINT, FALSE);
|
||||
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, TRUE);
|
||||
ApplyDwmBoolWindowAttribute(hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, TRUE);
|
||||
ApplyDwmColorWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, RGB(26, 26, 26));
|
||||
ApplyDwmColorWindowAttribute(hwnd, DWMWA_TEXT_COLOR, RGB(235, 235, 235));
|
||||
ApplyDwmColorWindowAttribute(hwnd, DWMWA_BORDER_COLOR, RGB(26, 26, 26));
|
||||
EnableBorderlessWindowShadow(hwnd);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user