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

Commitf566547

Browse files
authored
feat: calculate taskbar position and display on top of it (#125)
Closes:#119
1 parentcf25db5 commitf566547

File tree

1 file changed

+105
-50
lines changed

1 file changed

+105
-50
lines changed

‎App/Views/TrayWindow.xaml.cs

Lines changed: 105 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ public sealed partial class TrayWindow : Window
3333
privateint_lastWindowHeight;
3434
privateStoryboard?_currentSb;
3535

36-
privateNativeApi.POINT?_lastActivatePosition;
37-
3836
privatereadonlyIRpcController_rpcController;
3937
privatereadonlyICredentialManager_credentialManager;
4038
privatereadonlyISyncSessionController_syncSessionController;
@@ -98,18 +96,18 @@ public TrayWindow(IRpcController rpcController, ICredentialManager credentialMan
9896
WindowNative.GetWindowHandle(this)));
9997
SizeProxy.SizeChanged+=(_,e)=>
10098
{
101-
if(_currentSbisnull)return;// nothing running
99+
if(_currentSbisnull)return;// nothing running
102100

103-
intnewHeight=(int)Math.Round(
101+
varnewHeight=(int)Math.Round(
104102
e.NewSize.Height*DisplayScale.WindowScale(this));
105103

106-
intdelta=newHeight-_lastWindowHeight;
104+
vardelta=newHeight-_lastWindowHeight;
107105
if(delta==0)return;
108106

109107
varpos=_aw.Position;
110108
varsize=_aw.Size;
111109

112-
pos.Y-=delta;// grow upward
110+
pos.Y-=delta;// grow upward
113111
size.Height=newHeight;
114112

115113
_aw.MoveAndResize(
@@ -225,7 +223,6 @@ private void OnStoryboardCompleted(object? sender, object e)
225223

226224
privatevoidMoveResizeAndActivate()
227225
{
228-
SaveCursorPos();
229226
varsize=CalculateWindowSize(RootFrame.GetContentSize().Height);
230227
varpos=CalculateWindowPosition(size);
231228
varrect=newRectInt32(pos.X,pos.Y,size.Width,size.Height);
@@ -234,18 +231,6 @@ private void MoveResizeAndActivate()
234231
ForegroundWindow.MakeForeground(this);
235232
}
236233

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-
249234
privateSizeInt32CalculateWindowSize(doubleheight)
250235
{
251236
if(height<=0)height=100;// will be resolved next frame typically
@@ -257,41 +242,44 @@ private SizeInt32 CalculateWindowSize(double height)
257242
returnnewSizeInt32(newWidth,newHeight);
258243
}
259244

260-
privatePointInt32CalculateWindowPosition(SizeInt32size)
245+
privatePointInt32CalculateWindowPosition(SizeInt32panelSize)
261246
{
262-
varwidth=size.Width;
263-
varheight=size.Height;
264-
265-
varcursorPosition=_lastActivatePosition;
266-
if(cursorPositionisnull)
247+
vararea=DisplayArea.GetFromWindowId(AppWindow.Id,DisplayAreaFallback.Primary);
248+
// whole monitor
249+
varbounds=area.OuterBounds;
250+
// monitor minus taskbar
251+
varworkArea=area.WorkArea;
252+
253+
// get taskbar details - position, gap (size), auto-hide
254+
vartb=GetTaskbarInfo(area);
255+
256+
// safe edges where tray window can touch the screen
257+
varsafeRight=workArea.X+workArea.Width;
258+
varsafeBottom=workArea.Y+workArea.Height;
259+
260+
// if the taskbar is auto-hidden at the bottom, stay clear of its reveal band
261+
if(tb.Position==TaskbarPosition.Bottom&&tb.AutoHide)
262+
safeBottom-=tb.Gap;// shift everything up by its thickness
263+
264+
// pick corner & position the panel
265+
intx,y;
266+
switch(tb.Position)
267267
{
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;
278-
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;
286-
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;
268+
caseTaskbarPosition.Left:// for Left we will stick to the left-bottom corner
269+
x=bounds.X+tb.Gap;// just right of the bar
270+
y=safeBottom-panelSize.Height;
271+
break;
289272

290-
// Adjust if the window goes off the left edge of the display (somehow).
291-
if(x<workArea.X)x=workArea.X;
273+
caseTaskbarPosition.Top:// for Top we will stick to the top-right corner
274+
x=safeRight-panelSize.Width;
275+
y=bounds.Y+tb.Gap;// just below the bar
276+
break;
292277

293-
// Adjust if the window goes off the top edge of the display (somehow).
294-
if(y<workArea.Y)y=workArea.Y;
278+
default:// Bottom or Right bar we will stick to the bottom-right corner
279+
x=safeRight-panelSize.Width;
280+
y=safeBottom-panelSize.Height;
281+
break;
282+
}
295283

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

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp