Browse Source

feat: Add API for fetching window Z-order

pull/14909/head
Bartosz Korczyński 3 years ago
parent
commit
f0c14376ed
  1. 2
      native/Avalonia.Native/src/OSX/WindowImpl.h
  2. 12
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  3. 6
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  4. 6
      src/Avalonia.Controls/Window.cs
  5. 1
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  6. 1
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  7. 9
      src/Avalonia.Native/WindowImpl.cs
  8. 2
      src/Avalonia.Native/avn.idl
  9. 40
      src/Avalonia.X11/X11Window.cs
  10. 1
      src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs
  11. 14
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  12. 23
      src/Windows/Avalonia.Win32/WindowImpl.cs

2
native/Avalonia.Native/src/OSX/WindowImpl.h

@ -82,6 +82,8 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT GetExtendTitleBarHeight (double*ret) override;
virtual HRESULT SetExtendTitleBarHeight (double value) override;
virtual HRESULT GetWindowZOrder (long* zOrder) override;
void EnterFullScreenMode ();

12
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -366,6 +366,18 @@ HRESULT WindowImpl::GetWindowState(AvnWindowState *ret) {
}
}
HRESULT WindowImpl::GetWindowZOrder(long* zOrder) {
START_COM_CALL;
@autoreleasepool {
if (zOrder == nullptr) {
return E_POINTER;
}
*zOrder = [Window orderedIndex];
return S_OK;
}
}
HRESULT WindowImpl::TakeFocusFromChildren() {
START_COM_CALL;

6
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -98,6 +98,12 @@ namespace Avalonia.Platform
/// </summary>
Thickness OffScreenMargin { get; }
/// <summary>
/// Gets the window's z-order position. The highest value is the front, lower numbers are further back.
/// If the z-order can't be determined or the platform doesn't support window stacking, null is returned.
/// </summary>
IntPtr? ZOrder { get; }
/// <summary>
/// Starts moving a window with left button being held. Should be called from left mouse button press event handler.
/// </summary>

6
src/Avalonia.Controls/Window.cs

@ -428,6 +428,12 @@ namespace Avalonia.Controls
set => PlatformImpl?.Move(value);
}
/// <summary>
/// Gets the window's z-order position. The highest value is the front, lower numbers are further back.
/// If the z-order can't be determined or the platform doesn't support window stacking, null is returned.
/// </summary>
public IntPtr? WindowZOrder => PlatformImpl?.ZOrder;
/// <summary>
/// Starts moving a window with left button being held. Should be called from left mouse button press event handler
/// </summary>

1
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -39,6 +39,7 @@ namespace Avalonia.DesignerSupport.Remote
public double DesktopScaling => 1.0;
public PixelPoint Position { get; set; }
public IntPtr? ZOrder => null;
public Action<PixelPoint> PositionChanged { get; set; }
public Action Deactivated { get; set; }
public Action Activated { get; set; }

1
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -41,6 +41,7 @@ namespace Avalonia.DesignerSupport.Remote
public IPopupImpl CreatePopup() => new WindowStub(this);
public PixelPoint Position { get; set; }
public IntPtr? ZOrder => null;
public Action<PixelPoint> PositionChanged { get; set; }
public WindowState WindowState { get; set; }
public Action<WindowState> WindowStateChanged { get; set; }

9
src/Avalonia.Native/WindowImpl.cs

@ -103,6 +103,15 @@ namespace Avalonia.Native
public Thickness OffScreenMargin { get; } = new Thickness();
public IntPtr? ZOrder
{
get
{
// macOS returns z-order in reverse order - the topmost window has the lowest z-order
return new IntPtr(-_native.WindowZOrder.ToInt64());
}
}
private bool _isExtended;
public bool IsClientAreaExtendedToDecorations => _isExtended;

2
src/Avalonia.Native/avn.idl

@ -2,6 +2,7 @@
@clr-access internal
@clr-map bool int
@clr-map u_int64_t ulong
@clr-map long IntPtr
@cpp-preamble @@
#pragma once
#include "com.h"
@ -750,6 +751,7 @@ interface IAvnWindow : IAvnWindowBase
HRESULT SetExtendClientAreaHints(AvnExtendClientAreaChromeHints hints);
HRESULT GetExtendTitleBarHeight(double*ret);
HRESULT SetExtendTitleBarHeight(double value);
HRESULT GetWindowZOrder(long*ret);
}
[uuid(939b6599-40a8-4710-a4c8-5d72d8f174fb)]

40
src/Avalonia.X11/X11Window.cs

@ -1133,6 +1133,46 @@ namespace Avalonia.X11
}
}
public IntPtr? ZOrder
{
get
{
var stack = new Stack<IntPtr>();
var zOrder = 0;
stack.Push(_x11.RootWindow);
while (stack.Count > 0)
{
var currentWindow = stack.Pop();
if (currentWindow == _handle)
{
return new IntPtr(zOrder);
}
zOrder++;
if (XQueryTree(_x11.Display, currentWindow, out _, out _,
out var childrenPtr, out var childrenCount) != 0)
{
if (childrenPtr == IntPtr.Zero)
continue;
var children = (IntPtr*)childrenPtr;
// Children are returned bottom to top, so we need to push them in reverse order
// In order to traverse bottom children first
for (int i = childrenCount - 1; i >= 0; i--)
stack.Push(children[i]);
XFree(childrenPtr);
}
}
return null;
}
}
public IMouseDevice MouseDevice => _mouse;
public TouchDevice TouchDevice => _touch;

1
src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs

@ -100,6 +100,7 @@ namespace Avalonia.Headless
public PixelPoint Position { get; set; }
public Action<PixelPoint>? PositionChanged { get; set; }
public IntPtr? ZOrder => null;
public void Activate()
{
Dispatcher.UIThread.Post(() => Activated?.Invoke(), DispatcherPriority.Input);

14
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -1274,6 +1274,20 @@ namespace Avalonia.Win32.Interop
[DllImport("user32.dll")]
public static extern int GetSystemMetrics(SystemMetric smIndex);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCommand uCmd);
public enum GetWindowCommand : uint
{
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6,
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4
}
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowLongPtrW", ExactSpelling = true)]
public static extern uint GetWindowLongPtr(IntPtr hWnd, int nIndex);

23
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -711,6 +711,29 @@ namespace Avalonia.Win32
public void SetEnabled(bool enable) => EnableWindow(_hwnd, enable);
public IntPtr? ZOrder
{
get
{
var lowestHwnd = GetWindow(_hwnd, GetWindowCommand.GW_HWNDLAST);
var zOrder = 0;
var hwnd = lowestHwnd;
while (hwnd != IntPtr.Zero)
{
if (_hwnd == hwnd)
{
return new IntPtr(zOrder);
}
hwnd = GetWindow(hwnd, GetWindowCommand.GW_HWNDPREV);
zOrder++;
}
return null;
}
}
public void BeginMoveDrag(PointerPressedEventArgs e)
{
e.Pointer.Capture(null);

Loading…
Cancel
Save