Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5638bf1

Browse files
committed
feat: calculate taskbar position and display on top of it
1 parent059179c commit5638bf1

File tree

1 file changed

+97
-52
lines changed

1 file changed

+97
-52
lines changed

‎App/Views/TrayWindow.xaml.cs

Lines changed: 97 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@
99
usingMicrosoft.UI.Windowing;
1010
usingMicrosoft.UI.Xaml;
1111
usingMicrosoft.UI.Xaml.Controls;
12-
usingMicrosoft.UI.Xaml.Media;
1312
usingMicrosoft.UI.Xaml.Media.Animation;
1413
usingSystem;
15-
usingSystem.Diagnostics;
14+
usingSystem.Drawing.Printing;
1615
usingSystem.Runtime.InteropServices;
1716
usingWindows.Graphics;
1817
usingWindows.System;
@@ -34,8 +33,6 @@ public sealed partial class TrayWindow : Window
3433
privateint_lastWindowHeight;
3534
privateStoryboard?_currentSb;
3635

37-
privateNativeApi.POINT?_lastActivatePosition;
38-
3936
privatereadonlyIRpcController_rpcController;
4037
privatereadonlyICredentialManager_credentialManager;
4138
privatereadonlyISyncSessionController_syncSessionController;
@@ -60,7 +57,6 @@ public TrayWindow(IRpcController rpcController, ICredentialManager credentialMan
6057

6158
InitializeComponent();
6259
AppWindow.Hide();
63-
SystemBackdrop=newDesktopAcrylicBackdrop();
6460
Activated+=Window_Activated;
6561
RootFrame.SizeChanged+=RootFrame_SizeChanged;
6662

@@ -97,18 +93,18 @@ public TrayWindow(IRpcController rpcController, ICredentialManager credentialMan
9793
WindowNative.GetWindowHandle(this)));
9894
SizeProxy.SizeChanged+=(_,e)=>
9995
{
100-
if(_currentSbisnull)return;// nothing running
96+
if(_currentSbisnull)return;// nothing running
10197

102-
intnewHeight=(int)Math.Round(
98+
varnewHeight=(int)Math.Round(
10399
e.NewSize.Height*DisplayScale.WindowScale(this));
104100

105-
intdelta=newHeight-_lastWindowHeight;
101+
vardelta=newHeight-_lastWindowHeight;
106102
if(delta==0)return;
107103

108104
varpos=_aw.Position;
109105
varsize=_aw.Size;
110106

111-
pos.Y-=delta;// grow upward
107+
pos.Y-=delta;// grow upward
112108
size.Height=newHeight;
113109

114110
_aw.MoveAndResize(
@@ -118,7 +114,6 @@ public TrayWindow(IRpcController rpcController, ICredentialManager credentialMan
118114
};
119115
}
120116

121-
122117
privatevoidSetPageByState(RpcModelrpcModel,CredentialModelcredentialModel,
123118
SyncSessionControllerStateModelsyncSessionModel)
124119
{
@@ -225,7 +220,6 @@ private void OnStoryboardCompleted(object? sender, object e)
225220

226221
privatevoidMoveResizeAndActivate()
227222
{
228-
SaveCursorPos();
229223
varsize=CalculateWindowSize(RootFrame.GetContentSize().Height);
230224
varpos=CalculateWindowPosition(size);
231225
varrect=newRectInt32(pos.X,pos.Y,size.Width,size.Height);
@@ -234,18 +228,6 @@ private void MoveResizeAndActivate()
234228
NativeApi.SetForegroundWindow(WindowNative.GetWindowHandle(this));
235229
}
236230

237-
privatevoidSaveCursorPos()
238-
{
239-
varres=NativeApi.GetCursorPos(outvarcursorPosition);
240-
if(res)
241-
_lastActivatePosition=cursorPosition;
242-
else
243-
// When the cursor position is null, we will spawn the window in
244-
// the bottom right corner of the primary display.
245-
// TODO: log(?) an error when this happens
246-
_lastActivatePosition=null;
247-
}
248-
249231
privateSizeInt32CalculateWindowSize(doubleheight)
250232
{
251233
if(height<=0)height=100;// will be resolved next frame typically
@@ -257,41 +239,38 @@ private SizeInt32 CalculateWindowSize(double height)
257239
returnnewSizeInt32(newWidth,newHeight);
258240
}
259241

260-
privatePointInt32CalculateWindowPosition(SizeInt32size)
242+
privatePointInt32CalculateWindowPosition(SizeInt32panelSize)
261243
{
262-
varwidth=size.Width;
263-
varheight=size.Height;
244+
vararea=DisplayArea.GetFromWindowId(AppWindow.Id,DisplayAreaFallback.Primary);
245+
varbounds=area.OuterBounds;// entire monitor rect
246+
varworkArea=area.WorkArea;// monitor minus taskbar (and other app bars)
264247

265-
varcursorPosition=_lastActivatePosition;
266-
if(cursorPositionisnull)
267-
{
268-
varprimaryWorkArea=DisplayArea.Primary.WorkArea;
269-
returnnewPointInt32(
270-
primaryWorkArea.Width-width,
271-
primaryWorkArea.Height-height
272-
);
273-
}
274-
275-
// Spawn the window to the top right of the cursor.
276-
varx=cursorPosition.Value.X+10;
277-
vary=cursorPosition.Value.Y-10-height;
248+
vartb=GetTaskbarInfo(area);
278249

279-
varworkArea=DisplayArea.GetFromPoint(
280-
newPointInt32(cursorPosition.Value.X,cursorPosition.Value.Y),
281-
DisplayAreaFallback.Primary
282-
).WorkArea;
283-
284-
// Adjust if the window goes off the right edge of the display.
285-
if(x+width>workArea.X+workArea.Width)x=workArea.X+workArea.Width-width;
250+
intx,y;
251+
switch(tb.Position)
252+
{
253+
caseTaskbarPosition.Left:
254+
x=bounds.X+tb.Gap;
255+
y=workArea.Y+workArea.Height-panelSize.Height;
256+
break;
286257

287-
// Adjust if the window goes off the bottom edge of the display.
288-
if(y+height>workArea.Y+workArea.Height)y=workArea.Y+workArea.Height-height;
258+
caseTaskbarPosition.Top:
259+
x=workArea.X+workArea.Width-panelSize.Width;
260+
y=bounds.Y+tb.Gap;
261+
break;
289262

290-
// Adjust if the window goes off the left edge of the display (somehow).
291-
if(x<workArea.X)x=workArea.X;
263+
caseTaskbarPosition.Bottomwhentb.AutoHide:
264+
// Auto-hide bottom bar sits under the workArea – use workArea, not bounds.
265+
x=workArea.X+workArea.Width-panelSize.Width;
266+
y=workArea.Y+workArea.Height-panelSize.Height-tb.Gap;
267+
break;
292268

293-
// Adjust if the window goes off the top edge of the display (somehow).
294-
if(y<workArea.Y)y=workArea.Y;
269+
default:// right or bottom when not auto-hiding
270+
x=workArea.X+workArea.Width-panelSize.Width;
271+
y=bounds.Y+bounds.Height-panelSize.Height-tb.Gap;
272+
break;
273+
}
295274

296275
returnnewPointInt32(x,y);
297276
}
@@ -338,4 +317,70 @@ public struct POINT
338317
publicintY;
339318
}
340319
}
320+
internalenumTaskbarPosition{Left,Top,Right,Bottom}
321+
322+
internalreadonlyrecordstructTaskbarInfo(TaskbarPositionPosition,intGap,boolAutoHide);
323+
324+
// -----------------------------------------------------------------------------
325+
// Taskbar helpers – ABM_GETTASKBARPOS / ABM_GETSTATE via SHAppBarMessage
326+
// -----------------------------------------------------------------------------
327+
privatestaticTaskbarInfoGetTaskbarInfo(DisplayAreaarea)
328+
{
329+
vardata=newAPPBARDATA
330+
{
331+
cbSize=(uint)Marshal.SizeOf<APPBARDATA>()
332+
};
333+
334+
// Locate the taskbar.
335+
if(SHAppBarMessage(ABM_GETTASKBARPOS,refdata)==0)
336+
returnnewTaskbarInfo(TaskbarPosition.Bottom,0,false);// failsafe
337+
338+
varautoHide=(SHAppBarMessage(ABM_GETSTATE,refdata)&ABS_AUTOHIDE)!=0;
339+
340+
// Use uEdge instead of guessing from the RECT.
341+
varpos=data.uEdgeswitch
342+
{
343+
ABE_LEFT=>TaskbarPosition.Left,
344+
ABE_TOP=>TaskbarPosition.Top,
345+
ABE_RIGHT=>TaskbarPosition.Right,
346+
_=>TaskbarPosition.Bottom,// ABE_BOTTOM or anything unexpected
347+
};
348+
349+
// Thickness (gap) = shorter side of the rect.
350+
vargap=(pos==TaskbarPosition.Left||pos==TaskbarPosition.Right)
351+
?data.rc.right-data.rc.left// width
352+
:data.rc.bottom-data.rc.top;// height
353+
354+
returnnewTaskbarInfo(pos,gap,autoHide);
355+
}
356+
357+
// ------------- P/Invoke plumbing -------------
358+
privateconstuintABM_GETTASKBARPOS=0x0005;
359+
privateconstuintABM_GETSTATE=0x0004;
360+
privateconstintABS_AUTOHIDE=0x0001;
361+
362+
privateconstintABE_LEFT=0;// values returned in APPBARDATA.uEdge
363+
privateconstintABE_TOP=1;
364+
privateconstintABE_RIGHT=2;
365+
privateconstintABE_BOTTOM=3;
366+
367+
[StructLayout(LayoutKind.Sequential)]
368+
privatestructAPPBARDATA
369+
{
370+
publicuintcbSize;
371+
publicIntPtrhWnd;
372+
publicuintuCallbackMessage;
373+
publicuintuEdge;// contains ABE_* value
374+
publicRECTrc;
375+
publicintlParam;
376+
}
377+
378+
[StructLayout(LayoutKind.Sequential)]
379+
privatestructRECT
380+
{
381+
publicintleft,top,right,bottom;
382+
}
383+
384+
[DllImport("shell32.dll",CharSet=CharSet.Auto)]
385+
privatestaticexternuintSHAppBarMessage(uintdwMessage,refAPPBARDATApData);
341386
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp