From 8db53b86b7fb576eaf44aaa772c00a53a8933590 Mon Sep 17 00:00:00 2001 From: Michael Maltsev <4129781+m417z@users.noreply.github.com> Date: Tue, 10 Dec 2024 16:57:10 +0200 Subject: [PATCH] Windows 11 Start Menu Styler v1.2 (#1322) * The start menu search (what you see when you click on the start menu search bar) is now styled as well. Most of the search content is a WebView element, and the mod now allows to style it with CSS targets and styles. Refer to the mod description for more details. * Added the Everblush theme. * Updated themes: SideBySide2, Fluent2Inspired, Metro10Minimal. --- mods/windows-11-start-menu-styler.wh.cpp | 610 +++++++++++++++++------ 1 file changed, 456 insertions(+), 154 deletions(-) diff --git a/mods/windows-11-start-menu-styler.wh.cpp b/mods/windows-11-start-menu-styler.wh.cpp index 616d0b8d..f3782f11 100644 --- a/mods/windows-11-start-menu-styler.wh.cpp +++ b/mods/windows-11-start-menu-styler.wh.cpp @@ -2,12 +2,13 @@ // @id windows-11-start-menu-styler // @name Windows 11 Start Menu Styler // @description Customize the start menu with themes contributed by others or create your own -// @version 1.1.6 +// @version 1.2 // @author m417z // @github https://github.com/m417z // @twitter https://twitter.com/m417z // @homepage https://m417z.com/ // @include StartMenuExperienceHost.exe +// @include SearchHost.exe // @architecture x86-64 // @compilerOptions -lcomctl32 -lole32 -loleaut32 -lruntimeobject -lversion -Wl,--export-all-symbols // ==/WindhawkMod== @@ -74,6 +75,10 @@ RosePine](https://github.com/ramensoftware/windows-11-start-menu-styling-guide/b \ Windows11_Metro10Minimal](https://github.com/ramensoftware/windows-11-start-menu-styling-guide/blob/main/Themes/Windows11_Metro10Minimal/README.md) +[![Everblush](https://raw.githubusercontent.com/ramensoftware/windows-11-start-menu-styling-guide/main/Themes/Everblush/screenshot-small.png) +\ +Everblush](https://github.com/ramensoftware/windows-11-start-menu-styling-guide/blob/main/Themes/Everblush/README.md) + More themes can be found in the **Themes** section of [The Windows 11 start menu styling guide](https://github.com/ramensoftware/windows-11-start-menu-styling-guide/blob/main/README.md#themes). @@ -131,6 +136,34 @@ specified as following: `Style@VisualState=Value`, in which case the style will only apply when the visual state group specified in the target matches the specified visual state. +### Search WebView styles + +While the start menu uses WinUI for its user interface, most of the search +content (all but the top search bar) is a WebView element. To style the search +WebView, CSS targets and styles can be used. For example, to set a red +background, the target `body` and the style `background: red !important` can be +used. + +### Search WebView custom JavaScript code + +Custom JavaScript code can be injected into the search content WebView. One use +case example is loading the [DOM +Inspector](https://github.com/janmyler/DOM-inspector) script to inspect the +search content elements: + +![Screenshot](https://i.imgur.com/19PL0ss.png) + +The following JavaScript code can be used to load a bundled version of DOM +Inspector: + +``` +const s=document.createElement('script');s.setAttribute('src','https://m417z.github.io/DOM-inspector/acid-dom/bundled.js');document.head.appendChild(s); +``` + +To reset all side-effects of the injected scripts, clear the custom code in the +mod settings and then terminate the search host process. It will be relaunched +automatically by Windows. + ### Resource variables Some variables, such as size and padding for various controls, are defined as @@ -164,12 +197,21 @@ code from the **TranslucentTB** project. - Fluent2Inspired: Fluent2Inspired - RosePine: RosePine - Windows11_Metro10Minimal: Windows11_Metro10Minimal + - Everblush: Everblush - controlStyles: - - target: "" $name: Target - styles: [""] $name: Styles $name: Control styles +- webContentStyles: + - - target: "" + $name: Target + - styles: [""] + $name: Styles + $name: Search WebView styles +- webContentCustomJs: "" + $name: Search WebView custom JavaScript code - resourceVariables: - - variableKey: "" $name: Variable key @@ -364,8 +406,6 @@ const Theme g_themeSideBySide2 = {{ L"Margin=-268,0,0,0"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.FlyoutPresenter[1] > Grid", { L"Margin=-543,0,543,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#TopLevelRoot > Windows.UI.Xaml.Controls.Grid[2]", { - L"MinHeight=302"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.FlyoutPresenter", { L"Margin=-245,-12,0,0"}}, }}; @@ -784,8 +824,7 @@ const Theme g_themeFluent2Inspired = {{ ThemeTargetStyles{L"Button#CloseAllAppsButton", { L"CornerRadius=14", L"Margin=0,0,-32,0", - L"Width=74", - L"Height=26"}}, + L"Padding=10,4,12,5"}}, ThemeTargetStyles{L"Grid#ShowMoreSuggestions", { L"Visibility=1"}}, ThemeTargetStyles{L"Grid#SuggestionsParentContainer", { @@ -795,39 +834,43 @@ const Theme g_themeFluent2Inspired = {{ ThemeTargetStyles{L"Button#ShowAllAppsButton", { L"CornerRadius=14", L"Margin=0,0,32,0", - L"Width=148", - L"Height=26"}}, + L"Padding=12,4,10,5"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton", { - L"Margin=30,0,31,28"}}, + L"Margin=30,0,120,26"}}, ThemeTargetStyles{L"PipsPager#PinnedListPipsPager", { L"Visibility=1"}}, ThemeTargetStyles{L"Border#AcrylicBorder", { - L"Background:=", + L"Background:=", L"CornerRadius=12", - L"BorderBrush:=", - L"BorderThickness=1"}}, + L"BorderBrush:="}}, ThemeTargetStyles{L"Grid#MainContent", { L"CornerRadius=12"}}, ThemeTargetStyles{L"StartMenu.PinnedList", { - L"Height=690"}}, + L"MaxWidth=650", + L"Height=504", + L"Margin=-8,14,8,-14"}}, ThemeTargetStyles{L"TextBlock#DisplayName", { - L"Margin=0,16,0,-16", + L"Margin=0,8,0,-8", L"FontSize=13", L"FontFamily=Aptos", - L"Opacity=.65"}}, + L"Opacity=.75", + L"FontWeight=500", + L"Padding=14,0,14,0"}}, ThemeTargetStyles{L"TextBlock#PinnedListHeaderText", { - L"Margin=-29,0,0,0", + L"Margin=-14,0,0,0", L"FontFamily=Aptos", L"Opacity=.85", - L"FontSize=16"}}, + L"FontSize=16", + L"Margin=-32,0,0,0"}}, ThemeTargetStyles{L"Border#TaskbarSearchBackground", { L"Visibility=1"}}, ThemeTargetStyles{L"Border#AppBorder", { - L"Background:=", + L"Background:=", L"BorderBrush:=", L"CornerRadius=12"}}, ThemeTargetStyles{L"Border#dropshadow", { - L"CornerRadius=12"}}, + L"CornerRadius=12", + L"Margin=-1"}}, ThemeTargetStyles{L"Cortana.UI.Views.RichSearchBoxControl#SearchBoxControl", { L"Margin=33,33,33,10"}}, ThemeTargetStyles{L"TextBlock#UserTileNameText", { @@ -839,15 +882,13 @@ const Theme g_themeFluent2Inspired = {{ L"Opacity=.85"}}, ThemeTargetStyles{L"Border#ContentBorder", { L"CornerRadius=6"}}, - ThemeTargetStyles{L"GridViewItem > Border#ContentBorder > Grid#DroppedFlickerWorkaroundWrapper > Border#BackgroundBorder", { - L"FocusVisualPrimaryThickness=0"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton > Grid > ContentPresenter > TextBlock#PlaceholderText", { L"Text=Where to next?", L"FontWeight=700", L"FontFamily=Aptos", L"FontSize=24", L"Foreground:=", - L"Margin=10,0,0,0"}}, + L"Margin=2,0,0,0"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton > Grid > Border", { L"Background=transparent", L"BorderBrush=transparent"}}, @@ -857,9 +898,6 @@ const Theme g_themeFluent2Inspired = {{ L"FontSize=24"}}, ThemeTargetStyles{L"Grid#TopLevelRoot", { L"Margin=0,-8,0,0"}}, - ThemeTargetStyles{L"GridViewItem", { - L"Height=96", - L"Margin=0,0,0,2"}}, ThemeTargetStyles{L"StartDocked.UserTileView", { L"Margin=512,-1290,-2000,0"}}, ThemeTargetStyles{L"StartDocked.UserTileView > StartDocked.NavigationPaneButton > Grid > Border", { @@ -871,20 +909,23 @@ const Theme g_themeFluent2Inspired = {{ L"Opacity=.85"}}, ThemeTargetStyles{L"TextBlock#ShowAllAppsButtonText", { L"FontFamily=Aptos", - L"Opacity=.85"}}, + L"Opacity=.85", + L"FontWeight=500"}}, ThemeTargetStyles{L"Button#CloseAllAppsButton > ContentPresenter > StackPanel > TextBlock", { L"FontFamily=Aptos", - L"Opacity=.85"}}, + L"Opacity=.85", + L"FontWeight=500"}}, ThemeTargetStyles{L"Border#AcrylicOverlay", { L"Visibility=1"}}, ThemeTargetStyles{L"Grid#AllAppsPaneHeader", { - L"Margin=64,-8,64,0"}}, + L"Margin=64,-8,64,5"}}, ThemeTargetStyles{L"Grid#InnerContent", { L"Margin=0,31,0,-64"}}, ThemeTargetStyles{L"TextBlock#AppDisplayName", { L"FontFamily=Aptos", L"Opacity=.85", - L"Margin=4,0,0,0"}}, + L"Margin=4,0,0,4", + L"FontWeight=500"}}, ThemeTargetStyles{L"Button#Header > Border > TextBlock", { L"FontFamily=Aptos", L"FontWeight=600", @@ -893,23 +934,23 @@ const Theme g_themeFluent2Inspired = {{ L"CornerRadius=99", L"Margin=1"}}, ThemeTargetStyles{L"TileGrid", { - L"Background:=", + L"Background:=", L"CornerRadiusProtected=8", L"BorderThicknessProtected=1", - L"BorderBrushProtected:="}}, + L"BorderBrushProtected:=", + L"Margin=0,0,0,20"}}, ThemeTargetStyles{L"ListViewItem", { - L"Margin=1,0,-6,0", - L"CornerRadius=4", - L"Padding=0,0,6,0"}}, + L"Margin=1,5,-5,-5", + L"CornerRadius=4"}}, ThemeTargetStyles{L"Button#Header", { - L"Margin=4,0,-3,0"}}, + L"Margin=4,0,-3,-5"}}, ThemeTargetStyles{L"StartDocked.AllAppsPane#AllAppsPanel", { L"Margin=-20,0,-6,0"}}, ThemeTargetStyles{L"TextBlock#PlaceholderTextContentPresenter", { L"FontFamily=Aptos", L"FontSize=24", L"FontWeight=700", - L"Foreground:="}}, + L"Foreground:="}}, ThemeTargetStyles{L"Microsoft.UI.Xaml.Controls.AnimatedIcon#SearchIconPlayer", { L"Visibility=1"}}, ThemeTargetStyles{L"Button#SearchGlyphContainer", { @@ -917,7 +958,7 @@ const Theme g_themeFluent2Inspired = {{ L"Visibility=1"}}, ThemeTargetStyles{L"Cortana.UI.Views.CortanaRichSearchBox#SearchTextBox", { L"FontSize=24", - L"Foreground:=", + L"Foreground:=", L"FontFamily=Aptos", L"Opacity=.85", L"FontWeight=ExtraBold"}}, @@ -929,23 +970,22 @@ const Theme g_themeFluent2Inspired = {{ L"FontSize=32", L"Opacity=.85"}}, ThemeTargetStyles{L"Cortana.UI.Views.RichSearchBoxControl#SearchBoxControl", { - L"Margin=25,32,25,13"}}, - ThemeTargetStyles{L"Grid#WebViewGrid > WebView", { - L"Margin=-3,0,0,0"}}, + L"Margin=31,31,17,17"}}, + ThemeTargetStyles{L"Grid#WebViewGrid", { + L"Margin=-13,0,-10,15"}}, ThemeTargetStyles{L"TextBlock#StatusMessage", { L"Visibility=1"}}, ThemeTargetStyles{L"Border#LogoBackgroundPlate", { L"Margin=12,0,0,0"}}, - ThemeTargetStyles{L"Grid#WebViewGrid", { - L"CornerRadius=0,0,12,0"}}, ThemeTargetStyles{L"Border#DropShadow", { - L"CornerRadius=12"}}, + L"CornerRadius=12", + L"Margin=-1"}}, ThemeTargetStyles{L"Border#DropShadowDismissTarget", { L"CornerRadius=12"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.FlyoutPresenter[1]", { L"Margin=-250,50,0,0"}}, ThemeTargetStyles{L"StartDocked.LauncherFrame > Grid#RootGrid > Grid#RootContent > Grid#MainContent > Grid#InnerContent > Rectangle", { - L"Visibility=Collapsed"}}, + L"Visibility=1"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.FlyoutPresenter", { L"Margin=-250,0,0,0"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton > Grid > FontIcon#SearchGlyph", { @@ -960,6 +1000,33 @@ const Theme g_themeFluent2Inspired = {{ L"Margin=0,0,0,-60"}}, ThemeTargetStyles{L"StartDocked.NavigationPaneView#NavigationPane > Grid > StartDocked.AppListView", { L"Margin=0,0,-36,0"}}, + ThemeTargetStyles{L"Image#SearchIconOn", { + L"Visibility=1"}}, + ThemeTargetStyles{L"Grid#TopLevelSuggestionsContainer", { + L"Visibility=1"}}, + ThemeTargetStyles{L"Image#SearchIconOff", { + L"Visibility=1"}}, + ThemeTargetStyles{L"Grid#ContentBorder > Border#BackgroundBorder", { + L"CornerRadius=99", + L"Height=38", + L"Width=38"}}, + ThemeTargetStyles{L"Grid#ContentBorder > ContentPresenter > FontIcon", { + L"Opacity=.85"}}, + ThemeTargetStyles{L"StartDocked.AppListView#NavigationPanePlacesListView", { + L"Padding=2,0,6,0"}}, + ThemeTargetStyles{L"StartDocked.AppListView#NavigationPanePlacesListView > Border > ScrollViewer > Border#Root > Grid > ScrollContentPresenter > ItemsPresenter > ItemsStackPanel > ListViewItem", { + L"Margin=-2,0,0,0"}}, + ThemeTargetStyles{L"StartDocked.AppListView#NavigationPanePlacesListView", { + L"Margin=0,0,-46,0"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.ItemsWrapGrid", { + L"ItemHeight=84"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Primitives.ScrollBar#VerticalScrollBar", { + L"Transform3D:=", + L"Margin=0,5,0,55"}}, + ThemeTargetStyles{L"Grid#ContentBorder > Border#BorderBackground", { + L"Margin=1,0,-1,0"}}, + ThemeTargetStyles{L"StackPanel#RootPanel > Button#Header > Border#Border", { + L"Margin=0,0,-1,0"}}, }}; const Theme g_themeRosePine = {{ @@ -1076,123 +1143,42 @@ const Theme g_themeRosePine = {{ const Theme g_themeWindows11_Metro10Minimal = {{ ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#UndockedRoot", { - L"Visibility=Visible", - L"MaxWidth=600", - L"Margin=290,-10,0,0"}}, + L"MaxWidth=0", + L"Margin=0"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#AllAppsRoot", { L"Visibility=Visible", - L"Width=360", - L"Transform3D:=", - L"Margin=180,0,-220,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Button#CloseAllAppsButton", { - L"Visibility=Collapsed"}}, + L"Width=540", + L"Margin=-1000,0,0,0"}}, ThemeTargetStyles{L"StartDocked.StartSizingFrame", { - L"MinWidth=650", - L"MaxWidth=650", + L"MinWidth=460", + L"MaxWidth=460", L"MaxHeight=670"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#ShowMoreSuggestions", { L"Visibility=Collapsed"}}, ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Button#ShowAllAppsButton", { L"Visibility=Collapsed"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.GridView#RecommendedList > Windows.UI.Xaml.Controls.Border > Windows.UI.Xaml.Controls.ScrollViewer#ScrollViewer > Windows.UI.Xaml.Controls.Border#Root > Windows.UI.Xaml.Controls.Grid > Windows.UI.Xaml.Controls.ScrollContentPresenter#ScrollContentPresenter > Windows.UI.Xaml.Controls.ItemsPresenter > Windows.UI.Xaml.Controls.ItemsWrapGrid > Windows.UI.Xaml.Controls.GridViewItem", { - L"MaxWidth=145", - L"MinWidth=145", - L"Margin=0"}}, ThemeTargetStyles{L"StartDocked.AllAppsGridListView#AppsList", { L"Padding=90,3,6,16"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#AllAppsPaneHeader", { - L"Margin=97,-10,0,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#SuggestionsParentContainer", { - L"Height=168"}}, + ThemeTargetStyles{L"Grid#AllAppsPaneHeader", { + L"Visibility=Collapsed"}}, ThemeTargetStyles{L"StartDocked.NavigationPaneView#NavigationPane", { - L"FlowDirection=0", L"Margin=30,0,30,0"}}, - ThemeTargetStyles{L"StartDocked.PowerOptionsView#PowerButton", { - L"FlowDirection=0"}}, ThemeTargetStyles{L"StartDocked.AppListView#NavigationPanePlacesListView", { L"FlowDirection=1"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.ListViewItem", { - L"FlowDirection=0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.ItemsStackPanel > Windows.UI.Xaml.Controls.ListViewItem", { - L"FlowDirection=0"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton#StartMenuSearchBox", { L"Margin=23,-101,23,14"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.TextBlock#NoSuggestionsWithoutSettingsLink", { - L"Margin=11,0,48,0"}}, - ThemeTargetStyles{L"StartDocked.LauncherFrame > Windows.UI.Xaml.Controls.Grid#RootGrid > Windows.UI.Xaml.Controls.Grid#RootContent > Windows.UI.Xaml.Controls.Grid#MainContent > Windows.UI.Xaml.Controls.Grid#InnerContent > Windows.UI.Xaml.Shapes.Rectangle", { - L"Margin=67,7,0,21"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.SemanticZoom#ZoomControl", { - L"IsZoomOutButtonEnabled=true", - L"Margin=0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Button#ZoomOutButton > Windows.UI.Xaml.Controls.ContentPresenter#ContentPresenter > Windows.UI.Xaml.Controls.TextBlock", { - L"Text=\uE73F"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Button#ZoomOutButton", { - L"Width=28", - L"Height=28", - L"Margin=-1,-36,0,0", - L"FontSize=14", - L"CornerRadius=4", - L"VerticalAlignment=0", - L"Background=Transparent", - L"BorderBrush=Transparent"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.ListView#ZoomAppsList", { - L"Padding=86,0,27,0"}}, ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton", { - L"Height=0", - L"Margin=0,-100,0,24"}}, - ThemeTargetStyles{L"StartMenu.PinnedList", { - L"MaxHeight=400"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.TextBlock#PinnedListHeaderText", { - L"Margin=-30,-2,0,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#SuggestionsParentContainer", { - L"Margin=-20,0,0,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid#TopLevelSuggestionsListHeader", { - L"Margin=35,0,0,0"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Border#ContentBorder > Windows.UI.Xaml.Controls.Grid#DroppedFlickerWorkaroundWrapper > Border@CommonStates", { - L"BorderBrush@Active:=", - L"Background:=", - L"Margin=1", - L"BorderBrush:="}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Border#ContentBorder > Windows.UI.Xaml.Controls.Grid#DroppedFlickerWorkaroundWrapper > Border#BackgroundBorder", { - L"Background:=", - L"Margin=2"}}, - ThemeTargetStyles{L"Windows.UI.Xaml.Controls.TextBlock#PinnedListHeaderText", { - L"Visibility=Visible"}}, + L"Height=0"}}, ThemeTargetStyles{L"Rectangle[4]", { L"Margin=0,-20,0,0"}}, - ThemeTargetStyles{L"GridView#RecommendedList", { - L"Margin=-20,0,20,0"}}, - ThemeTargetStyles{L"StartMenu.ExpandedFolderList > Grid > Grid", { - L"Margin=0,0,80,0"}}, - ThemeTargetStyles{L"StartMenu.ExpandedFolderList > Grid > Border", { - L"Width=350", - L"Margin=0,0,92,0"}}, - ThemeTargetStyles{L"Microsoft.UI.Xaml.Controls.PipsPager#PinnedListPipsPager", { - L"Margin=-10,0,0,0"}}, ThemeTargetStyles{L"StartMenu.ExpandedFolderList > Grid > Grid > Microsoft.UI.Xaml.Controls.PipsPager#PinnedListPipsPager", { L"Margin=-20,0,20,0"}}, ThemeTargetStyles{L"StartMenu.StartInnerFrame", { L"Visibility=Collapsed"}}, - ThemeTargetStyles{L"Grid#AllAppsPaneHeader", { - L"Visibility=Collapsed"}}, - ThemeTargetStyles{L"Button#ZoomOutButton", { - L"Visibility=Collapsed"}}, - ThemeTargetStyles{L"SemanticZoom#ZoomControl", { - L"IsZoomOutButtonEnabled=False"}}, - ThemeTargetStyles{L"Grid#UndockedRoot", { - L"MaxWidth=0", - L"Margin=0"}}, - ThemeTargetStyles{L"StartDocked.StartSizingFrame", { - L"MaxWidth=460", - L"MinWidth=460"}}, ThemeTargetStyles{L"Grid#RootContent", { L"MinWidth=460"}}, ThemeTargetStyles{L"Grid#InnerContent", { L"Margin=0,12,0,0"}}, - ThemeTargetStyles{L"Grid#AllAppsRoot", { - L"Transform3D:=", - L"Margin=0", - L"Width=540"}}, ThemeTargetStyles{L"Border#AcrylicBorder", { L"Background:=", L"BorderBrush:=", @@ -1204,6 +1190,74 @@ const Theme g_themeWindows11_Metro10Minimal = {{ L"Visibility=1"}}, }}; +const Theme g_themeEverblush = {{ + ThemeTargetStyles{L"Border#AcrylicBorder", { + L"Background=#141b1e", + L"BorderBrush=#268ccf7e"}}, + ThemeTargetStyles{L"Border#AcrylicOverlay", { + L"Background=#141b1e"}}, + ThemeTargetStyles{L"StartDocked.SearchBoxToggleButton > Grid > Border", { + L"Background=#232a2d", + L"BorderBrush=transparent"}}, + ThemeTargetStyles{L"StartMenu.ExpandedFolderList > Grid > Border", { + L"Background=#232a2d"}}, + ThemeTargetStyles{L"TextBlock#PlaceholderText", { + L"Foreground=#80b3b9b8"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Button", { + L"Background=#d28ccf7e"}}, + ThemeTargetStyles{L"StackPanel > Windows.UI.Xaml.Controls.Button", { + L"Background=transparent", + L"BorderBrush=transparent"}}, + ThemeTargetStyles{L"Microsoft.UI.Xaml.Controls.ItemsRepeater > Windows.UI.Xaml.Controls.Button", { + L"Background=transparent", + L"BorderBrush=transparent"}}, + ThemeTargetStyles{L"TextBlock#DisplayName", { + L"Foreground=#b3b9b8"}}, + ThemeTargetStyles{L"TextBlock#Title", { + L"Foreground=#b3b9b8"}}, + ThemeTargetStyles{L"TextBlock#Subtitle", { + L"Foreground=#6cbfbf"}}, + ThemeTargetStyles{L"TextBlock#PinnedListHeaderText", { + L"Foreground=#8ccf7e"}}, + ThemeTargetStyles{L"TextBlock#TopLevelSuggestionsListHeaderText", { + L"Foreground=#8ccf7e"}}, + ThemeTargetStyles{L"TextBlock#AllAppsHeading", { + L"Foreground=#8ccf7e"}}, + ThemeTargetStyles{L"TextBlock#MoreSuggestionsListHeaderText", { + L"Foreground=#8ccf7e"}}, + ThemeTargetStyles{L"TextBlock#AppDisplayName", { + L"Foreground=#b3b9b8"}}, + ThemeTargetStyles{L"TextBlock#Text ", { + L"Foreground=#e5c76b"}}, + ThemeTargetStyles{L"TextBlock#FolderGlyph", { + L"Foreground=#e5c76b"}}, + ThemeTargetStyles{L"TextBlock#StatusMessage", { + L"Foreground=#8ccf7e"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Border#ContentBorder > Windows.UI.Xaml.Controls.Grid#DroppedFlickerWorkaroundWrapper > Border@CommonStates", { + L"Background:= ", + L"BorderBrush:= ", + L"CornerRadius=6"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Border#ContentBorder > Windows.UI.Xaml.Controls.Grid#DroppedFlickerWorkaroundWrapper > Border#BackgroundBorder", { + L"Background=transparent"}}, + ThemeTargetStyles{L" Border#AppBorder", { + L"Background=#141b1e"}}, + ThemeTargetStyles{L"Border#TaskbarSearchBackground", { + L"Background=#232a2d", + L"BorderBrush=transparent"}}, + ThemeTargetStyles{L"Grid", { + L"RequestedTheme=2"}}, + ThemeTargetStyles{L"TextBlock#UserTileNameText", { + L"Foreground=#67b0e8"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.ContentPresenter > Windows.UI.Xaml.Controls.FontIcon > Windows.UI.Xaml.Controls.Grid > Windows.UI.Xaml.Controls.TextBlock", { + L"Foreground=#6cbfbf"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.Grid > Windows.UI.Xaml.Controls.FontIcon > Windows.UI.Xaml.Controls.Grid > Windows.UI.Xaml.Controls.TextBlock", { + L"Foreground=#e5c76b"}}, + ThemeTargetStyles{L"MenuFlyoutPresenter", { + L"Background=#232a2d"}}, + ThemeTargetStyles{L"Windows.UI.Xaml.Controls.FontIcon#SearchGlyph > Windows.UI.Xaml.Controls.Grid > Windows.UI.Xaml.Controls.TextBlock", { + L"Foreground=#232a2d"}}, +}}; + // clang-format on std::atomic g_targetThreadId = 0; @@ -1445,7 +1499,9 @@ HRESULT WindhawkTAP::SetSite(IUnknown *pUnkSite) try } catch (...) { - return winrt::to_hresult(); + HRESULT hr = winrt::to_hresult(); + Wh_Log(L"Error %08X", hr); + return hr; } HRESULT WindhawkTAP::GetSite(REFIID riid, void **ppvSite) noexcept @@ -1476,7 +1532,9 @@ struct SimpleFactory : winrt::implements, IClassFactory, winrt: } catch (...) { - return winrt::to_hresult(); + HRESULT hr = winrt::to_hresult(); + Wh_Log(L"Error %08X", hr); + return hr; } HRESULT STDMETHODCALLTYPE LockServer(BOOL) noexcept override @@ -1509,7 +1567,9 @@ _Use_decl_annotations_ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LP } catch (...) { - return winrt::to_hresult(); + HRESULT hr = winrt::to_hresult(); + Wh_Log(L"Error %08X", hr); + return hr; } __declspec(dllexport) @@ -1561,13 +1621,23 @@ HRESULT InjectWindhawkTAP() noexcept return HRESULT_FROM_WIN32(GetLastError()); } - const HRESULT hr2 = ixde(L"VisualDiagConnection1", GetCurrentProcessId(), nullptr, location, CLSID_WindhawkTAP, nullptr); - if (FAILED(hr2)) [[unlikely]] + // I didn't find a better way than trying many connections until one works. + // Reference: + // https://github.com/microsoft/microsoft-ui-xaml/blob/d74a0332cf0d5e58f12eddce1070fa7a79b4c2db/src/dxaml/xcp/dxaml/lib/DXamlCore.cpp#L2782 + HRESULT hr; + for (int i = 0; i < 10000; i++) { - return hr2; + WCHAR connectionName[256]; + wsprintf(connectionName, L"VisualDiagConnection%d", i + 1); + + hr = ixde(connectionName, GetCurrentProcessId(), L"", location, CLSID_WindhawkTAP, nullptr); + if (hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND)) + { + break; + } } - return S_OK; + return hr; } #pragma endregion // api_cpp @@ -1610,6 +1680,13 @@ struct deleter_from_fn { using string_setting_unique_ptr = std::unique_ptr>; +enum class Target { + StartMenu, + SearchHost, +}; + +Target g_target; + using PropertyKeyValue = std::pair; @@ -1677,6 +1754,17 @@ struct ElementCustomizationState { std::unordered_map g_elementsCustomizationState; +std::wstring g_webContentCss; +std::wstring g_webContentJs; + +struct WebViewCustomizationState { + winrt::weak_ref element; + winrt::event_token navigationCompletedEventToken; +}; + +std::unordered_map + g_webViewsCustomizationState; + bool g_elementPropertyModifying; winrt::Windows::Foundation::IInspectable ReadLocalValueWithWorkaround( @@ -1733,8 +1821,8 @@ void SetOrClearValue(DependencyObject elementDo, std::wstring EscapeXmlAttribute(std::wstring_view data) { std::wstring buffer; buffer.reserve(data.size()); - for (size_t pos = 0; pos != data.size(); ++pos) { - switch (data[pos]) { + for (const auto c : data) { + switch (c) { case '&': buffer.append(L"&"); break; @@ -1751,7 +1839,7 @@ std::wstring EscapeXmlAttribute(std::wstring_view data) { buffer.append(L">"); break; default: - buffer.append(&data[pos], 1); + buffer.push_back(c); break; } } @@ -2285,9 +2373,125 @@ void RestoreCustomizationsForVisualStateGroup( } } +std::wstring EscapeJsTemplateString(std::wstring_view str) { + std::wstring buffer; + buffer.reserve(str.size()); + for (const auto c : str) { + switch (c) { + case '\\': + buffer.append(L"\\\\"); + break; + case '`': + buffer.append(L"\\`"); + break; + default: + buffer.push_back(c); + break; + } + } + + return buffer; +} + +bool ApplyWebViewCustomizations(Controls::WebView webViewElement) { + auto source = webViewElement.Source(); + if (!source) { + return false; + } + + auto canonicalUri = source.AbsoluteCanonicalUri(); + Wh_Log(L"WebView source: %s", canonicalUri.c_str()); + + if (canonicalUri != L"https://www.bing.com/WS/Init") { + return false; + } + + std::wstring jsCode = + LR"( + const styleElementId = "windhawk-windows-11-start-menu-styler-style"; + const styleContent = ` + )"; + + jsCode += EscapeJsTemplateString(g_webContentCss); + + jsCode += + LR"( + `; + if (!document.getElementById(styleElementId)) { + const style = document.createElement("style"); + style.id = styleElementId; + style.textContent = styleContent; + document.head.appendChild(style); + } + )"; + + jsCode += g_webContentJs; + + Wh_Log(L"======================================== JS:"); + Wh_Log(L"%p", winrt::get_abi(webViewElement)); + std::wstringstream ss(jsCode); + std::wstring line; + while (std::getline(ss, line, L'\n')) { + Wh_Log(L"%s", line.c_str()); + } + Wh_Log(L"========================================"); + + webViewElement.InvokeScriptAsync( + L"eval", + winrt::single_threaded_vector({jsCode.c_str()})); + + return true; +} + +void ClearWebViewCustomizations(Controls::WebView webViewElement) { + PCWSTR jsCode = + LR"( + const styleElementId = "windhawk-windows-11-start-menu-styler-style"; + const style = document.getElementById(styleElementId); + if (style) { + style.parentNode.removeChild(style); + } + )"; + + Wh_Log(L"======================================== JS:"); + Wh_Log(L"%p", winrt::get_abi(webViewElement)); + std::wstringstream ss(jsCode); + std::wstring line; + while (std::getline(ss, line, L'\n')) { + Wh_Log(L"%s", line.c_str()); + } + Wh_Log(L"========================================"); + + webViewElement.InvokeScriptAsync( + L"eval", winrt::single_threaded_vector( + {winrt::to_hstring(jsCode)})); +} + void ApplyCustomizations(InstanceHandle handle, FrameworkElement element, PCWSTR fallbackClassName) { + if ((!g_webContentCss.empty() || !g_webContentJs.empty()) && + winrt::get_class_name(element) == L"Windows.UI.Xaml.Controls.WebView") { + auto& webViewCustomizationState = g_webViewsCustomizationState[handle]; + if (!webViewCustomizationState.element.get()) { + webViewCustomizationState.element = element; + + auto webViewElement = element.as(); + + ApplyWebViewCustomizations(webViewElement); + + webViewCustomizationState.navigationCompletedEventToken = + webViewElement.NavigationCompleted( + [](const Controls::WebView& sender, + const Controls::WebViewNavigationCompletedEventArgs& + args) { + if (args.IsSuccess()) { + ApplyWebViewCustomizations(sender); + } + }); + } + } + auto overrides = FindElementPropertyOverrides(element, fallbackClassName); if (overrides.empty()) { return; @@ -2325,22 +2529,37 @@ void ApplyCustomizations(InstanceHandle handle, } void CleanupCustomizations(InstanceHandle handle) { - auto it = g_elementsCustomizationState.find(handle); - if (it == g_elementsCustomizationState.end()) { - return; - } + if (auto it = g_elementsCustomizationState.find(handle); + it != g_elementsCustomizationState.end()) { + auto& elementCustomizationState = it->second; - auto& elementCustomizationState = it->second; + auto element = elementCustomizationState.element.get(); - auto element = elementCustomizationState.element.get(); + for (const auto& [visualStateGroupOptionalWeakPtrIter, stateIter] : + elementCustomizationState.perVisualStateGroup) { + RestoreCustomizationsForVisualStateGroup( + element, visualStateGroupOptionalWeakPtrIter, stateIter); + } - for (const auto& [visualStateGroupOptionalWeakPtrIter, stateIter] : - elementCustomizationState.perVisualStateGroup) { - RestoreCustomizationsForVisualStateGroup( - element, visualStateGroupOptionalWeakPtrIter, stateIter); + g_elementsCustomizationState.erase(it); } - g_elementsCustomizationState.erase(it); + if (auto it = g_webViewsCustomizationState.find(handle); + it != g_webViewsCustomizationState.end()) { + auto& webViewCustomizationState = it->second; + + auto element = webViewCustomizationState.element.get(); + if (element) { + auto webViewElement = element.as(); + + ClearWebViewCustomizations(webViewElement); + + webViewElement.NavigationCompleted( + webViewCustomizationState.navigationCompletedEventToken); + } + + g_webViewsCustomizationState.erase(it); + } } ElementMatcher ElementMatcherFromString(std::wstring_view str) { @@ -2567,6 +2786,46 @@ bool ProcessSingleTargetStylesFromSettings(int index) { return true; } +void ProcessWebStylesFromSettings() { + std::wstring webContentCss; + + for (int i = 0;; i++) { + string_setting_unique_ptr targetStringSetting( + Wh_GetStringSetting(L"webContentStyles[%d].target", i)); + if (!*targetStringSetting.get()) { + break; + } + + Wh_Log(L"Processing WebView styles for %s", targetStringSetting.get()); + + webContentCss += targetStringSetting.get(); + webContentCss += L" {\n"; + + for (int styleIndex = 0;; styleIndex++) { + string_setting_unique_ptr styleSetting(Wh_GetStringSetting( + L"webContentStyles[%d].styles[%d]", i, styleIndex)); + if (!*styleSetting.get()) { + break; + } + + // Skip if commented. + if (styleSetting[0] == L'/' && styleSetting[1] == L'/') { + continue; + } + + webContentCss += styleSetting.get(); + webContentCss += L";\n"; + } + + webContentCss += L"}\n"; + } + + g_webContentCss = std::move(webContentCss); + g_webContentJs = + string_setting_unique_ptr(Wh_GetStringSetting(L"webContentCustomJs")) + .get(); +} + void ProcessAllStylesFromSettings() { PCWSTR themeName = Wh_GetStringSetting(L"theme"); const Theme* theme = nullptr; @@ -2590,6 +2849,8 @@ void ProcessAllStylesFromSettings() { theme = &g_themeRosePine; } else if (wcscmp(themeName, L"Windows11_Metro10Minimal") == 0) { theme = &g_themeWindows11_Metro10Minimal; + } else if (wcscmp(themeName, L"Everblush") == 0) { + theme = &g_themeEverblush; } Wh_FreeStringSetting(themeName); @@ -2620,6 +2881,10 @@ void ProcessAllStylesFromSettings() { Wh_Log(L"Error: %S", ex.what()); } } + + if (g_target == Target::SearchHost) { + ProcessWebStylesFromSettings(); + } } bool ProcessSingleResourceVariableFromSettings(int index) { @@ -2691,6 +2956,21 @@ void UninitializeSettingsAndTap() { g_elementsCustomizationRules.clear(); + for (const auto& [handle, webViewCustomizationState] : + g_webViewsCustomizationState) { + auto element = webViewCustomizationState.element.get(); + if (element) { + auto webViewElement = element.as(); + + ClearWebViewCustomizations(webViewElement); + + webViewElement.NavigationCompleted( + webViewCustomizationState.navigationCompletedEventToken); + } + } + + g_webViewsCustomizationState.clear(); + g_targetThreadId = 0; } @@ -2893,6 +3173,28 @@ HWND GetCoreWnd() { BOOL Wh_ModInit() { Wh_Log(L">"); + g_target = Target::StartMenu; + + WCHAR moduleFilePath[MAX_PATH]; + switch ( + GetModuleFileName(nullptr, moduleFilePath, ARRAYSIZE(moduleFilePath))) { + case 0: + case ARRAYSIZE(moduleFilePath): + Wh_Log(L"GetModuleFileName failed"); + break; + + default: + if (PCWSTR moduleFileName = wcsrchr(moduleFilePath, L'\\')) { + moduleFileName++; + if (_wcsicmp(moduleFileName, L"SearchHost.exe") == 0) { + g_target = Target::SearchHost; + } + } else { + Wh_Log(L"GetModuleFileName returned an unsupported path"); + } + break; + } + HMODULE user32Module = LoadLibrary(L"user32.dll"); if (user32Module) { void* pCreateWindowInBand =