mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
[FancyZones] Zone title bar pager and buttons styles
This commit is contained in:
@@ -86,7 +86,7 @@ void FancyZonesApp::InitHooks()
|
||||
}
|
||||
}
|
||||
|
||||
std::array<DWORD, 13> events_to_subscribe = {
|
||||
std::array<DWORD, 12> events_to_subscribe = {
|
||||
EVENT_SYSTEM_MOVESIZESTART,
|
||||
EVENT_SYSTEM_MOVESIZEEND,
|
||||
EVENT_OBJECT_NAMECHANGE,
|
||||
@@ -98,8 +98,7 @@ void FancyZonesApp::InitHooks()
|
||||
EVENT_SYSTEM_MINIMIZEEND,
|
||||
EVENT_OBJECT_HIDE,
|
||||
EVENT_OBJECT_DESTROY,
|
||||
EVENT_SYSTEM_FOREGROUND,
|
||||
EVENT_OBJECT_FOCUS
|
||||
EVENT_OBJECT_REORDER
|
||||
};
|
||||
for (const auto event : events_to_subscribe)
|
||||
{
|
||||
@@ -179,8 +178,7 @@ void FancyZonesApp::HandleWinHookEvent(WinHookEvent* data) noexcept
|
||||
case EVENT_SYSTEM_MINIMIZEEND:
|
||||
case EVENT_OBJECT_HIDE:
|
||||
case EVENT_OBJECT_DESTROY:
|
||||
case EVENT_SYSTEM_FOREGROUND:
|
||||
case EVENT_OBJECT_FOCUS:
|
||||
case EVENT_OBJECT_REORDER:
|
||||
{
|
||||
fzCallback->HandleWinHookEvent(data);
|
||||
}
|
||||
|
||||
@@ -15,17 +15,7 @@ void CompositionDrawing::Init(HWND window)
|
||||
}
|
||||
|
||||
// Create devices
|
||||
D2D1_FACTORY_OPTIONS options = {
|
||||
#ifdef _DEBUG
|
||||
D2D1_DEBUG_LEVEL_INFORMATION
|
||||
#endif
|
||||
};
|
||||
|
||||
D2D1CreateFactory(
|
||||
D2D1_FACTORY_TYPE_MULTI_THREADED,
|
||||
__uuidof(m_d2dFactory),
|
||||
&options,
|
||||
m_d2dFactory.put_void());
|
||||
m_d2dFactory.copy_from(GetD2DFactory());
|
||||
if (!m_d2dFactory)
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -19,11 +19,17 @@ D2D1_COLOR_F Drawing::ConvertColor(winrt::Windows::UI::Color color)
|
||||
color.A / 255.f);
|
||||
}
|
||||
|
||||
ID2D1Factory* Drawing::GetD2DFactory()
|
||||
ID2D1Factory6* Drawing::GetD2DFactory()
|
||||
{
|
||||
static auto pD2DFactory = [] {
|
||||
ID2D1Factory* res = nullptr;
|
||||
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, &res);
|
||||
D2D1_FACTORY_OPTIONS options = {
|
||||
#ifdef _DEBUG
|
||||
D2D1_DEBUG_LEVEL_INFORMATION
|
||||
#endif
|
||||
};
|
||||
ID2D1Factory6* res = nullptr;
|
||||
|
||||
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &res);
|
||||
return res;
|
||||
}();
|
||||
return pD2DFactory;
|
||||
@@ -140,6 +146,28 @@ winrt::com_ptr<ID2D1SolidColorBrush> Drawing::CreateBrush(D2D1_COLOR_F color) co
|
||||
return brush;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1StrokeStyle1> Drawing::CreateStroke(float stokeWidht) const
|
||||
{
|
||||
if (!*this)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1StrokeStyle1> stroke = nullptr;
|
||||
|
||||
auto properties = D2D1::StrokeStyleProperties1(
|
||||
D2D1_CAP_STYLE_ROUND,
|
||||
D2D1_CAP_STYLE_ROUND,
|
||||
D2D1_CAP_STYLE_ROUND,
|
||||
D2D1_LINE_JOIN_ROUND,
|
||||
0.0f,
|
||||
D2D1_DASH_STYLE_SOLID,
|
||||
0.0f);
|
||||
GetD2DFactory()->CreateStrokeStyle(properties, nullptr, 0, stroke.put());
|
||||
|
||||
return stroke;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1Bitmap> Drawing::CreateIcon(HICON icon) const
|
||||
{
|
||||
if (!*this)
|
||||
@@ -179,6 +207,49 @@ winrt::com_ptr<ID2D1Bitmap> Drawing::CreateIcon(HICON icon) const
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1PathGeometry> Drawing::CreateTriangle(const D2D1_TRIANGLE& triangle) const
|
||||
{
|
||||
if (!*this)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1PathGeometry> geometry = nullptr;
|
||||
|
||||
GetD2DFactory()->CreatePathGeometry(geometry.put());
|
||||
|
||||
if (!geometry)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1GeometrySink> tessellationSink = nullptr;
|
||||
|
||||
geometry->Open(tessellationSink.put());
|
||||
|
||||
if (!tessellationSink)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tessellationSink->BeginFigure(triangle.point1, D2D1_FIGURE_BEGIN_FILLED);
|
||||
|
||||
tessellationSink->AddLine(triangle.point2);
|
||||
|
||||
tessellationSink->AddLine(triangle.point3);
|
||||
|
||||
tessellationSink->EndFigure(D2D1_FIGURE_END_CLOSED);
|
||||
|
||||
auto hr = tessellationSink->Close();
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return geometry;
|
||||
}
|
||||
|
||||
void Drawing::FillRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color)
|
||||
{
|
||||
if (!*this)
|
||||
@@ -193,7 +264,7 @@ void Drawing::FillRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color)
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color)
|
||||
void Drawing::FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color, float radiusFactor)
|
||||
{
|
||||
if (!*this)
|
||||
{
|
||||
@@ -205,8 +276,8 @@ void Drawing::FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color)
|
||||
{
|
||||
D2D1_ROUNDED_RECT roundedRect;
|
||||
roundedRect.rect = rect;
|
||||
roundedRect.radiusX = (rect.right - rect.left) * .1f;
|
||||
roundedRect.radiusY = (rect.bottom - rect.top) * .1f;
|
||||
roundedRect.radiusX = (rect.right - rect.left) * radiusFactor;
|
||||
roundedRect.radiusY = (rect.bottom - rect.top) * radiusFactor;
|
||||
|
||||
auto radius = min(roundedRect.radiusX, roundedRect.radiusY);
|
||||
roundedRect.radiusX = radius;
|
||||
@@ -216,6 +287,40 @@ void Drawing::FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color)
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::FillEllipse(const D2D1_ELLIPSE& ellipse, D2D1_COLOR_F color)
|
||||
{
|
||||
if (!*this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto brush = CreateBrush(color);
|
||||
if (brush)
|
||||
{
|
||||
m_renderTarget->FillEllipse(ellipse, brush.get());
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::FillGeometry(ID2D1PathGeometry* geometry, D2D1_COLOR_F color, float strokeWidth)
|
||||
{
|
||||
if (!*this)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto brush = CreateBrush(color);
|
||||
auto stroke = CreateStroke(strokeWidth);
|
||||
if (brush)
|
||||
{
|
||||
m_renderTarget->FillGeometry(geometry, brush.get());
|
||||
|
||||
if (stroke)
|
||||
{
|
||||
m_renderTarget->DrawGeometry(geometry, brush.get(), strokeWidth, stroke.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Drawing::DrawRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color, float strokeWidth)
|
||||
{
|
||||
if (!*this)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "util.h"
|
||||
|
||||
#include <d2d1.h>
|
||||
#include <d2d1_1.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <dwrite.h>
|
||||
#include <wincodec.h>
|
||||
#include <winrt/Windows.UI.ViewManagement.h>
|
||||
@@ -21,10 +21,14 @@ public:
|
||||
|
||||
winrt::com_ptr<IDWriteTextFormat> CreateTextFormat(LPCWSTR fontFamilyName, FLOAT fontSize, DWRITE_FONT_WEIGHT fontWeight = DWRITE_FONT_WEIGHT_NORMAL) const;
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> CreateBrush(D2D1_COLOR_F color) const;
|
||||
winrt::com_ptr<ID2D1StrokeStyle1> CreateStroke(float stokeWidht) const;
|
||||
winrt::com_ptr<ID2D1Bitmap> CreateIcon(HICON icon) const;
|
||||
winrt::com_ptr<ID2D1PathGeometry> CreateTriangle(const D2D1_TRIANGLE& triangle) const;
|
||||
|
||||
void FillRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color);
|
||||
void FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color);
|
||||
void FillRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color, float radiusFactor = .1f);
|
||||
void FillEllipse(const D2D1_ELLIPSE& ellipse, D2D1_COLOR_F color);
|
||||
void FillGeometry(ID2D1PathGeometry* geometry, D2D1_COLOR_F color, float strokeWidth = 1.f);
|
||||
void DrawRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color, float strokeWidth = 1.f);
|
||||
void DrawRoundedRectangle(const D2D1_RECT_F& rect, D2D1_COLOR_F color, float strokeWidth = 1.f);
|
||||
void DrawTextW(std::wstring text, IDWriteTextFormat* format, const D2D1_RECT_F& rect, D2D1_COLOR_F color);
|
||||
@@ -34,7 +38,7 @@ public:
|
||||
void EndDraw();
|
||||
|
||||
protected:
|
||||
static ID2D1Factory* GetD2DFactory();
|
||||
static ID2D1Factory6* GetD2DFactory();
|
||||
static IDWriteFactory* GetWriteFactory();
|
||||
static IWICImagingFactory2* GetImageFactory();
|
||||
|
||||
|
||||
@@ -158,8 +158,7 @@ public:
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_SYSTEM_FOREGROUND:
|
||||
case EVENT_OBJECT_FOCUS:
|
||||
case EVENT_OBJECT_REORDER:
|
||||
PostMessageW(m_window, WM_PRIV_WINDOWREORDER, wparam, lparam);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,11 @@ enum struct ZoneTitleBarStyle : int
|
||||
AutoHideTabs = 7,
|
||||
Labels = 8,
|
||||
AutoHideLabels = 9,
|
||||
EnumElements = 10, // number of elements in the enum, not counting this
|
||||
Pager = 10,
|
||||
AutoHidePager = 11,
|
||||
Buttons = 12,
|
||||
AutoHideButtons = 13,
|
||||
EnumElements = 14, // number of elements in the enum, not counting this
|
||||
};
|
||||
|
||||
// in reality, this file needs to be kept in sync currently with src/settings-ui/Settings.UI.Library/FZConfigProperties.cs
|
||||
|
||||
@@ -7,10 +7,16 @@ namespace NonLocalizable
|
||||
const wchar_t WindowClassName[] = L"FancyZones_Window";
|
||||
}
|
||||
|
||||
Window::Window(HINSTANCE hinstance, WndProc proc, DWORD style, DWORD extendedStyle, FancyZonesUtils::Rect position, LPCWSTR windowName, HWND parent, HMENU menu, int showCommand) noexcept :
|
||||
Window::Window() noexcept :
|
||||
m_window(NULL),
|
||||
m_proc(proc)
|
||||
m_proc(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void Window::Init(HINSTANCE hinstance, WndProc proc, DWORD style, DWORD extendedStyle, FancyZonesUtils::Rect position, LPCWSTR windowName, HWND parent, HMENU menu, int showCommand) noexcept
|
||||
{
|
||||
m_proc = proc;
|
||||
|
||||
static ATOM windowClass = INVALID_ATOM;
|
||||
if (windowClass == INVALID_ATOM)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ using WndProc = std::function<LRESULT(HWND window, UINT message, WPARAM wparam,
|
||||
class Window
|
||||
{
|
||||
public:
|
||||
Window(HINSTANCE hinstance, WndProc proc, DWORD style, DWORD extendedStyle, FancyZonesUtils::Rect position, LPCWSTR windowName = NULL, HWND parent = NULL, HMENU menu = NULL, int show = SW_SHOWNOACTIVATE) noexcept;
|
||||
Window() noexcept;
|
||||
~Window();
|
||||
|
||||
Window(const Window&) = delete;
|
||||
@@ -15,6 +15,8 @@ public:
|
||||
|
||||
operator HWND() const { return m_window; }
|
||||
|
||||
void Init(HINSTANCE hinstance, WndProc proc, DWORD style, DWORD extendedStyle, FancyZonesUtils::Rect position, LPCWSTR windowName = NULL, HWND parent = NULL, HMENU menu = NULL, int show = SW_SHOWNOACTIVATE) noexcept;
|
||||
|
||||
private:
|
||||
static LRESULT CALLBACK s_WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) noexcept;
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ static bool ShouldSuppressMove(HWND window, RECT zoneRect, bool suppressMove)
|
||||
if (GetWindowRect(window, &windowRect))
|
||||
{
|
||||
// Check if window is already in rect except for the zone title bar
|
||||
if (zoneRect.left == windowRect.left &&
|
||||
if (zoneRect.left <= windowRect.left &&
|
||||
zoneRect.right == windowRect.right &&
|
||||
zoneRect.bottom == windowRect.bottom &&
|
||||
zoneRect.top <= windowRect.top)
|
||||
@@ -374,7 +374,7 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
if (!sizeEmpty)
|
||||
{
|
||||
auto zoneTitleBar = m_zoneTitleBarByIndexSets.find(indexSet);
|
||||
auto zoneTitleBarHeight = 0;
|
||||
FancyZonesUtils::Rect zoneTitleBarInlineFrame;
|
||||
|
||||
// Are we are not alone?
|
||||
if (!m_windowsByIndexSets[indexSet].empty())
|
||||
@@ -399,15 +399,19 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
auto dpi = GetDpiForMonitor(MonitorFromWindow(workAreaWindow, MONITOR_DEFAULTTOPRIMARY));
|
||||
zoneTitleBar = m_zoneTitleBarByIndexSets.emplace(indexSet, MakeZoneTitleBar(m_config.ZoneTitleBarStyle, m_hinstance, zone, dpi)).first;
|
||||
|
||||
zoneTitleBarHeight = zoneTitleBar->second->GetHeight();
|
||||
rect.top += zoneTitleBarHeight;
|
||||
SizeWindowToRect(hwnd, rect);
|
||||
zoneTitleBarInlineFrame = zoneTitleBar->second->GetInlineFrame();
|
||||
auto rectForResize = AdjustRectForSizeWindowToRect(hwnd, *zoneTitleBarInlineFrame.get(), workAreaWindow);
|
||||
SizeWindowToRect(hwnd, rectForResize);
|
||||
}
|
||||
else
|
||||
{
|
||||
zoneTitleBarInlineFrame = rect;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust the rect
|
||||
zoneTitleBarHeight = zoneTitleBar->second->GetHeight();
|
||||
zoneTitleBarInlineFrame = zoneTitleBar->second->GetInlineFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,8 +424,15 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
|
||||
auto shouldSuppressMove = ShouldSuppressMove(window, rect, suppressMove);
|
||||
if (!shouldSuppressMove)
|
||||
{
|
||||
rect.top += zoneTitleBarHeight;
|
||||
SizeWindowToRect(window, rect);
|
||||
if (IsRectEmpty(zoneTitleBarInlineFrame.get()))
|
||||
{
|
||||
SizeWindowToRect(window, rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto rectForResize = AdjustRectForSizeWindowToRect(window, *zoneTitleBarInlineFrame.get(), workAreaWindow);
|
||||
SizeWindowToRect(window, rectForResize);
|
||||
}
|
||||
}
|
||||
|
||||
auto oldBitmask = GetWindowStamp(window);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "util.h"
|
||||
#include "Window.h"
|
||||
#include "Settings.h"
|
||||
|
||||
@@ -10,7 +11,7 @@ public:
|
||||
virtual void Show(bool show) = 0;
|
||||
virtual void UpdateZoneWindows(std::vector<HWND> zoneWindows) = 0;
|
||||
virtual void ReadjustPos() = 0;
|
||||
virtual int GetHeight() const = 0;
|
||||
virtual FancyZonesUtils::Rect GetInlineFrame() const = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IZoneTitleBar> MakeZoneTitleBar(ZoneTitleBarStyle style, HINSTANCE hinstance, FancyZonesUtils::Rect zone, UINT dpi);
|
||||
@@ -51,6 +51,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
|
||||
AutoHideTabs = 7,
|
||||
Labels = 8,
|
||||
AutoHideLabels = 9,
|
||||
Pager = 10,
|
||||
AutoHidePager = 11,
|
||||
Buttons = 12,
|
||||
AutoHideButtons = 13,
|
||||
}
|
||||
|
||||
public FancyZonesViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<FancyZonesSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc, string configFileSubfolder = "")
|
||||
|
||||
@@ -1192,6 +1192,12 @@ Made with 💗 by Microsoft and the PowerToys community.</value>
|
||||
<data name="FancyZones_ZoneTitleBarStyle_Labels.Content" xml:space="preserve">
|
||||
<value>Labels</value>
|
||||
</data>
|
||||
<data name="FancyZones_ZoneTitleBarStyle_Pager.Content" xml:space="preserve">
|
||||
<value>Pager</value>
|
||||
</data>
|
||||
<data name="FancyZones_ZoneTitleBarStyle_Buttons.Content" xml:space="preserve">
|
||||
<value>Buttons</value>
|
||||
</data>
|
||||
<data name="FancyZones_ZoneTitleBar_AutoHide.Header" xml:space="preserve">
|
||||
<value>Auto hide</value>
|
||||
</data>
|
||||
|
||||
@@ -104,6 +104,8 @@
|
||||
<ComboBoxItem x:Uid="FancyZones_ZoneTitleBarStyle_Icons" />
|
||||
<ComboBoxItem x:Uid="FancyZones_ZoneTitleBarStyle_Tabs" />
|
||||
<ComboBoxItem x:Uid="FancyZones_ZoneTitleBarStyle_Labels" />
|
||||
<ComboBoxItem x:Uid="FancyZones_ZoneTitleBarStyle_Pager" />
|
||||
<ComboBoxItem x:Uid="FancyZones_ZoneTitleBarStyle_Buttons" />
|
||||
</ComboBox>
|
||||
</controls:Setting.ActionContent>
|
||||
</controls:Setting>
|
||||
|
||||
Reference in New Issue
Block a user