Skip to content

Commit ea5881f

Browse files
committed
Start10: Fix positioning when the taskbar is placed vertically (#3462)
1 parent de2532d commit ea5881f

File tree

3 files changed

+247
-10
lines changed

3 files changed

+247
-10
lines changed

ExplorerPatcher/ExplorerPatcher.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@
256256
<ClCompile Include="TaskbarCenter.c">
257257
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
258258
</ClCompile>
259+
<ClCompile Include="TwinUIPatches.cpp">
260+
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
261+
</ClCompile>
259262
<ClCompile Include="updates.cpp">
260263
<ExcludedFromBuild Condition="'$(WithMainPatcher)'!='true'">true</ExcludedFromBuild>
261264
</ClCompile>

ExplorerPatcher/TwinUIPatches.cpp

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#include <Windows.h>
2+
#include <Shlwapi.h>
3+
#include <initguid.h>
4+
5+
#include <wrl/client.h>
6+
#include <wil/result_macros.h>
7+
8+
#include "utility.h"
9+
10+
using namespace Microsoft::WRL;
11+
12+
DEFINE_GUID(SID_EdgeUi, 0x0D189B30, 0xF12B, 0x4B13, 0x94, 0xCF, 0x53, 0xCB, 0x0E, 0x0E, 0x24, 0x0D); // 0d189b30-f12b-4b13-94cf-53cb0e0e240d
13+
14+
interface IImmersiveApplication;
15+
interface IEdgeUiInvocationProvider;
16+
17+
enum EDGEUI_COMPONENT
18+
{
19+
EUICMP_UNKNOWN = -1,
20+
EUICMP_SWITCHER = 0,
21+
EUICMP_CHARMSBAR,
22+
EUICMP_APPBAR,
23+
EUICMP_TASKBAR,
24+
EUICMP_TITLEBAR,
25+
EUICMP_TABLETMODEVIEWMANAGER,
26+
EUICMP_ACTIONCENTER,
27+
EUICMP_TOTALCOUNT,
28+
};
29+
30+
enum DISMISSED_UI_FLAGS
31+
{
32+
DUF_NONE = 0x0,
33+
DUF_FORCEOBSERVATIONOFF = 0x1,
34+
};
35+
36+
enum EDGEUI_TRAYSTUCKPLACE
37+
{
38+
EUITSP_UNKNOWN = -1,
39+
EUITSP_LEFT = 0,
40+
EUITSP_TOP,
41+
EUITSP_RIGHT,
42+
EUITSP_BOTTOM,
43+
};
44+
45+
MIDL_INTERFACE("6e6c3c52-5a5e-4b4b-a0f8-7fe12621a93e")
46+
IEdgeUiManager : IUnknown
47+
{
48+
virtual HRESULT STDMETHODCALLTYPE GetTargetApplicationFromPoint(POINT, int, IImmersiveApplication**) = 0;
49+
virtual HRESULT STDMETHODCALLTYPE DismissedUI(EDGEUI_COMPONENT, DISMISSED_UI_FLAGS) = 0;
50+
virtual HRESULT STDMETHODCALLTYPE HandleEdgeGesturePrefChanged(HWND) = 0;
51+
virtual HRESULT STDMETHODCALLTYPE DiscreteInvokeForApp(EDGEUI_COMPONENT, IImmersiveApplication*) = 0;
52+
virtual HRESULT STDMETHODCALLTYPE BeginInputObservation(EDGEUI_COMPONENT) = 0;
53+
virtual HRESULT STDMETHODCALLTYPE GetRegionForCornerOrEdge(EDGEUI_COMPONENT, HRGN*) = 0;
54+
virtual HRESULT STDMETHODCALLTYPE NotifyTrayStuckPlaceChanged(EDGEUI_TRAYSTUCKPLACE) = 0;
55+
virtual HRESULT STDMETHODCALLTYPE GetTrayStuckPlace(EDGEUI_TRAYSTUCKPLACE*) = 0;
56+
virtual HRESULT STDMETHODCALLTYPE NotifyTraySearchBoxVisibilityChanged(BOOL) = 0;
57+
virtual HRESULT STDMETHODCALLTYPE GetTraySearchBoxVisibility(BOOL*) = 0;
58+
virtual HRESULT STDMETHODCALLTYPE NotifyPearlRectChanged(RECT) = 0;
59+
virtual HRESULT STDMETHODCALLTYPE GetPearlRect(RECT*) = 0;
60+
virtual HRESULT STDMETHODCALLTYPE UpdateEdgeWindowZorder() = 0;
61+
virtual HRESULT STDMETHODCALLTYPE ShowStandardSystemOverlays(IImmersiveApplication*) = 0;
62+
virtual HRESULT STDMETHODCALLTYPE OverrideInvocation(IEdgeUiInvocationProvider*) = 0;
63+
virtual HRESULT STDMETHODCALLTYPE NotifyAutohideImmuneWorkAreaMayHaveChanged(RECT) = 0;
64+
virtual HRESULT STDMETHODCALLTYPE GetAutohideImmuneWorkArea(RECT*) = 0;
65+
virtual HRESULT STDMETHODCALLTYPE TaskbarRaised() = 0;
66+
virtual HRESULT STDMETHODCALLTYPE GetTrayRect(RECT*) = 0;
67+
};
68+
69+
enum IMMERSIVE_MONITOR_FILTER_FLAGS
70+
{
71+
IMMERSIVE_MONITOR_FILTER_FLAGS_NONE = 0x0,
72+
IMMERSIVE_MONITOR_FILTER_FLAGS_DISABLE_TRAY = 0x1,
73+
};
74+
75+
DEFINE_ENUM_FLAG_OPERATORS(IMMERSIVE_MONITOR_FILTER_FLAGS);
76+
77+
MIDL_INTERFACE("880b26f8-9197-43d0-8045-8702d0d72000")
78+
IImmersiveMonitor : IUnknown
79+
{
80+
virtual HRESULT STDMETHODCALLTYPE GetIdentity(DWORD*) = 0;
81+
virtual HRESULT STDMETHODCALLTYPE ConnectObject(IUnknown*) = 0;
82+
virtual HRESULT STDMETHODCALLTYPE GetHandle(HMONITOR*) = 0;
83+
virtual HRESULT STDMETHODCALLTYPE IsConnected(BOOL*) = 0;
84+
virtual HRESULT STDMETHODCALLTYPE IsPrimary(BOOL*) = 0;
85+
virtual HRESULT STDMETHODCALLTYPE IsImmersiveDisplayDevice(BOOL*) = 0;
86+
virtual HRESULT STDMETHODCALLTYPE GetDisplayRect(RECT*) = 0;
87+
virtual HRESULT STDMETHODCALLTYPE GetOrientation(DWORD*) = 0;
88+
virtual HRESULT STDMETHODCALLTYPE GetWorkArea(RECT*) = 0;
89+
virtual HRESULT STDMETHODCALLTYPE IsEqual(IImmersiveMonitor*, BOOL*) = 0;
90+
virtual HRESULT STDMETHODCALLTYPE IsImmersiveCapable(BOOL*) = 0;
91+
virtual HRESULT STDMETHODCALLTYPE GetEffectiveDpi(UINT*, UINT*) = 0;
92+
virtual HRESULT STDMETHODCALLTYPE GetFilterFlags(IMMERSIVE_MONITOR_FILTER_FLAGS*) = 0;
93+
};
94+
95+
DEFINE_GUID(SID_ImmersiveLauncher, 0x6F86E01C, 0xC649, 0x4D61, 0xBE, 0x23, 0xF1, 0x32, 0x2D, 0xDE, 0xCA, 0x9D); // 6f86e01c-c649-4d61-be23-f1322ddeca9d
96+
97+
enum IMMERSIVELAUNCHERSHOWMETHOD
98+
{
99+
ILSM_INVALID = 0,
100+
ILSM_HSHELLTASKMAN = 1,
101+
ILSM_IMMERSIVEBACKGROUND = 4,
102+
ILSM_APPCLOSED = 6,
103+
ILSM_STARTBUTTON = 11,
104+
ILSM_RETAILDEMO_EDUCATIONAPP = 12,
105+
ILSM_BACK = 13,
106+
ILSM_SESSIONONUNLOCK = 14,
107+
};
108+
109+
enum IMMERSIVELAUNCHERSHOWFLAGS
110+
{
111+
ILSF_NONE = 0x0,
112+
ILSF_IGNORE_SET_FOREGROUND_ERROR = 0x4,
113+
};
114+
115+
DEFINE_ENUM_FLAG_OPERATORS(IMMERSIVELAUNCHERSHOWFLAGS);
116+
117+
enum IMMERSIVELAUNCHERDISMISSMETHOD
118+
{
119+
ILDM_INVALID = 0,
120+
ILDM_HSHELLTASKMAN = 1,
121+
ILDM_STARTCHARM = 2,
122+
ILDM_BACKGESTURE = 3,
123+
ILDM_ESCAPEKEY = 4,
124+
ILDM_SHOWDESKTOP = 5,
125+
ILDM_STARTTIP = 6,
126+
ILDM_GENERIC_NONANIMATING = 7,
127+
ILDM_SEARCH_OPENING = 8,
128+
ILDM_DRAG = 9,
129+
};
130+
131+
MIDL_INTERFACE("d8d60399-a0f1-f987-5551-321fd1b49864")
132+
IImmersiveLauncher : IUnknown
133+
{
134+
virtual HRESULT STDMETHODCALLTYPE ShowStartView(IMMERSIVELAUNCHERSHOWMETHOD, IMMERSIVELAUNCHERSHOWFLAGS) = 0;
135+
virtual HRESULT STDMETHODCALLTYPE Dismiss(IMMERSIVELAUNCHERDISMISSMETHOD) = 0;
136+
virtual HRESULT STDMETHODCALLTYPE DismissToLastDesktopApplication(IMMERSIVELAUNCHERDISMISSMETHOD) = 0;
137+
virtual HRESULT STDMETHODCALLTYPE DismissSynchronouslyWithoutTransition() = 0;
138+
virtual HRESULT STDMETHODCALLTYPE IsVisible(BOOL*) = 0;
139+
virtual HRESULT STDMETHODCALLTYPE OnStartButtonPressed(IMMERSIVELAUNCHERSHOWMETHOD, IMMERSIVELAUNCHERDISMISSMETHOD) = 0;
140+
virtual HRESULT STDMETHODCALLTYPE SetForeground() = 0;
141+
virtual HRESULT STDMETHODCALLTYPE ConnectToMonitor(IImmersiveMonitor*) = 0;
142+
virtual HRESULT STDMETHODCALLTYPE GetMonitor(IImmersiveMonitor**) = 0;
143+
virtual HRESULT STDMETHODCALLTYPE OnFirstSignAnimationFinished() = 0;
144+
virtual HRESULT STDMETHODCALLTYPE Prelaunch() = 0;
145+
};
146+
147+
class CSingleViewShellExperience;
148+
149+
inline BOOL IsBiDiLocale(LCID locale)
150+
{
151+
int info;
152+
int charsRead = GetLocaleInfoW(
153+
locale,
154+
LOCALE_IREADINGLAYOUT | LOCALE_RETURN_NUMBER,
155+
(LPWSTR)&info,
156+
sizeof(info) / sizeof(WCHAR)
157+
);
158+
return charsRead > 0 ? info == 1 : false;
159+
}
160+
161+
BOOL Mirror_IsThreadRTL()
162+
{
163+
return IsBiDiLocale(GetThreadUILanguage());
164+
}
165+
166+
extern "C" HRESULT CStartExperienceManager_GetMonitorInformationHook(void* _this, CSingleViewShellExperience* experience, RECT* rcOutWorkArea, EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor)
167+
{
168+
*rcOutWorkArea = {};
169+
*outTrayStuckPlace = EUITSP_BOTTOM;
170+
*bOutRtl = false;
171+
if (hOutMonitor)
172+
*hOutMonitor = nullptr;
173+
174+
ComPtr<IServiceProvider> spImmersiveShellServiceProvider;
175+
RETURN_IF_FAILED(CoCreateInstance(CLSID_ImmersiveShell, nullptr, CLSCTX_LOCAL_SERVER, IID_IServiceProvider, &spImmersiveShellServiceProvider));
176+
177+
ComPtr<IImmersiveLauncher> spImmersiveLauncher;
178+
RETURN_IF_FAILED(spImmersiveShellServiceProvider->QueryService(SID_ImmersiveLauncher, IID_PPV_ARGS(&spImmersiveLauncher)));
179+
180+
ComPtr<IImmersiveMonitor> spImmersiveMonitor;
181+
HRESULT hr = spImmersiveLauncher->GetMonitor(&spImmersiveMonitor);
182+
if (FAILED(hr))
183+
return hr;
184+
185+
HMONITOR hMonitor = nullptr;
186+
if (hOutMonitor)
187+
hr = spImmersiveMonitor->GetHandle(&hMonitor);
188+
189+
if (FAILED(hr))
190+
return hr;
191+
192+
ComPtr<IEdgeUiManager> spEdgeUiManager;
193+
hr = IUnknown_QueryService(spImmersiveMonitor.Get(), SID_EdgeUi, IID_PPV_ARGS(&spEdgeUiManager));
194+
if (FAILED(hr))
195+
return hr;
196+
197+
EDGEUI_TRAYSTUCKPLACE trayStuckPlace;
198+
RETURN_IF_FAILED(spEdgeUiManager->GetTrayStuckPlace(&trayStuckPlace));
199+
200+
HWND hwndTray = FindWindowW(L"Shell_TrayWnd", nullptr);
201+
202+
RECT rcWork;
203+
if (hwndTray && GetPropW(hwndTray, L"IsAutoHideEnabled"))
204+
{
205+
RETURN_IF_FAILED(spEdgeUiManager->GetAutohideImmuneWorkArea(&rcWork));
206+
}
207+
else
208+
{
209+
RETURN_IF_FAILED(spImmersiveMonitor->GetWorkArea(&rcWork));
210+
}
211+
212+
*rcOutWorkArea = rcWork;
213+
*outTrayStuckPlace = trayStuckPlace;
214+
*bOutRtl = Mirror_IsThreadRTL() != FALSE;
215+
if (hOutMonitor)
216+
*hOutMonitor = hMonitor;
217+
218+
return S_OK;
219+
}

ExplorerPatcher/dllmain.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11295,19 +11295,20 @@ enum DWMTRANSITION_TARGET
1129511295
DWMTARGET_LAUNCHERFULLSCREEN = 0x52,
1129611296
};
1129711297

11298-
HRESULT(*CStartExperienceManager_GetMonitorInformationFunc)(void* _this, void* experience, RECT* a3, enum EDGEUI_TRAYSTUCKPLACE* pTsp, bool* a5, HMONITOR* a7);
11299-
HRESULT(*CExperienceManagerAnimationHelper_BeginFunc)(void* _this, void*, enum DWMTRANSITION_TARGET, const RECT*, const RECT*, const RECT*, const RECT*, const RECT*);
11298+
extern HRESULT CStartExperienceManager_GetMonitorInformationHook(void* _this, void* experience, RECT* rcOutWorkArea, enum EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor);
11299+
HRESULT(*CStartExperienceManager_GetMonitorInformationFunc)(void* _this, void* experience, RECT* rcOutWorkArea, enum EDGEUI_TRAYSTUCKPLACE* outTrayStuckPlace, bool* bOutRtl, HMONITOR* hOutMonitor);
11300+
HRESULT(*CExperienceManagerAnimationHelper_BeginFunc)(void* _this, void* pViewWrapper, enum DWMTRANSITION_TARGET target, const RECT* prcBeginSource, const RECT* prcBeginDestination, const RECT* prcEndSource, const RECT* prcEndDestination, const RECT* prcClip);
1130011301
HRESULT(*CExperienceManagerAnimationHelper_EndFunc)(void* _this);
1130111302

1130211303
HRESULT(*OnViewUncloakingFunc)(void* eventHandler, void* pSender);
1130311304
HRESULT OnViewUncloakingHook(void* eventHandler, void* pSender)
1130411305
{
1130511306
PBYTE _this = (PBYTE)eventHandler - g_SMAnimationPatchOffsets.startExperienceManager_SingleViewShellExperienceEventHandler;
1130611307

11307-
RECT rc;
11308+
RECT rcWorkArea;
1130811309
enum EDGEUI_TRAYSTUCKPLACE tsp;
11309-
bool bUnknown;
11310-
if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationFunc(_this, pSender, &rc, &tsp, &bUnknown, NULL)))
11310+
bool bRtl;
11311+
if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationHook(_this, pSender, &rcWorkArea, &tsp, &bRtl, NULL)))
1131111312
{
1131211313
enum DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT;
1131311314
if (*(bool*)((PBYTE)pSender + 0x34))
@@ -11324,7 +11325,7 @@ HRESULT OnViewUncloakingHook(void* eventHandler, void* pSender)
1132411325
CExperienceManagerAnimationHelper_BeginFunc(
1132511326
_this + g_SMAnimationPatchOffsets.startExperienceManager_openingAnimation,
1132611327
*(void**)((PBYTE)pSender + 0x18), // viewWrapper
11327-
target | 0x200000, NULL, NULL, NULL, NULL, &rc);
11328+
target | 0x200000, NULL, NULL, NULL, NULL, &rcWorkArea);
1132811329
}
1132911330

1133011331
if (global_rovi.dwBuildNumber >= 25169)
@@ -11411,11 +11412,11 @@ HRESULT OnViewCloakingHook(void* eventHandler, void* pSender)
1141111412
bool bTransitioningToCortana = *(_this + g_SMAnimationPatchOffsets.startExperienceManager_bTransitioningToCortana);
1141211413
if (!bTransitioningToCortana)
1141311414
{
11414-
RECT rc;
11415+
RECT rcWorkArea;
1141511416
enum EDGEUI_TRAYSTUCKPLACE tsp;
11416-
bool bUnknown;
11417+
bool bRtl;
1141711418
HMONITOR hMonitor;
11418-
if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationFunc(_this, pSender, &rc, &tsp, &bUnknown, &hMonitor)))
11419+
if (SUCCEEDED(CStartExperienceManager_GetMonitorInformationHook(_this, pSender, &rcWorkArea, &tsp, &bRtl, &hMonitor)))
1141911420
{
1142011421
enum DWMTRANSITION_TARGET target = DWMTARGET_LAUNCHERFLYOUT;
1142111422
if (*(bool*)((PBYTE)pSender + 0x34))
@@ -11432,7 +11433,7 @@ HRESULT OnViewCloakingHook(void* eventHandler, void* pSender)
1143211433
CExperienceManagerAnimationHelper_BeginFunc(
1143311434
_this + g_SMAnimationPatchOffsets.startExperienceManager_closingAnimation,
1143411435
*(void**)((PBYTE)pSender + 0x18), // viewWrapper
11435-
target | 0x200000u, NULL, NULL, NULL, NULL, &rc);
11436+
target | 0x200000u, NULL, NULL, NULL, NULL, &rcWorkArea);
1143611437
}
1143711438
}
1143811439

@@ -11985,6 +11986,20 @@ BOOL FixStartMenuAnimation(LPMODULEINFO mi)
1198511986
}
1198611987
#endif
1198711988

11989+
int rv = -1;
11990+
if (CStartExperienceManager_GetMonitorInformationFunc)
11991+
{
11992+
rv = funchook_prepare(
11993+
funchook,
11994+
(void**)&CStartExperienceManager_GetMonitorInformationFunc,
11995+
CStartExperienceManager_GetMonitorInformationHook
11996+
);
11997+
}
11998+
if (rv != 0)
11999+
{
12000+
printf("Failed to hook CStartExperienceManager::GetMonitorInformation(). rv = %d\n", rv);
12001+
}
12002+
1198812003
return TRUE;
1198912004
}
1199012005
#endif

0 commit comments

Comments
 (0)