using System; using System.IO; using System.Runtime.InteropServices; using Microsoft.UI; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Media; using Windows.Graphics; using WinRT.Interop; namespace LayersShell; public sealed partial class MainWindow : Window { private IntPtr _handle = IntPtr.Zero; private IntPtr _hwnd = IntPtr.Zero; private const double DefaultLogicalWidth = 480; private const double DefaultLogicalHeight = 640; private bool _isFocused = true; private bool _isHovered = false; public MainWindow() { App.Log("MainWindow ctor enter"); try { InitializeComponent(); } catch (Exception ex) { App.Log($"InitializeComponent FAILED: {ex}"); throw; } Title = "Layers"; _hwnd = WindowNative.GetWindowHandle(this); App.Log($"hwnd = {_hwnd:X}"); try { var appWindow = AppWindow.GetFromWindowId(Win32Interop.GetWindowIdFromWindow(_hwnd)); App.Log($"appWindow null? {appWindow is null}"); if (appWindow is not null) { appWindow.SetPresenter(AppWindowPresenterKind.Overlapped); App.Log($"presenter kind: {appWindow.Presenter?.Kind}"); if (appWindow.Presenter is OverlappedPresenter op) { op.IsAlwaysOnTop = true; op.IsResizable = true; op.IsMaximizable = false; op.IsMinimizable = true; op.SetBorderAndTitleBar(hasBorder: false, hasTitleBar: false); App.Log("OverlappedPresenter configured"); } appWindow.ResizeClient(new SizeInt32((int)DefaultLogicalWidth, (int)DefaultLogicalHeight)); App.Log("ResizeClient ok"); } } catch (Exception ex) { App.Log($"appWindow setup FAILED: {ex}"); throw; } try { SystemBackdrop = new MicaBackdrop { Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.Base }; App.Log("SystemBackdrop assigned"); } catch (Exception ex) { App.Log($"SystemBackdrop FAILED: {ex}"); throw; } Activated += OnActivated; Closed += OnClosed; App.Log("events wired"); DispatcherQueue.TryEnqueue(() => { try { App.Log("deferred init: PointToRust"); PointToRust(); App.Log("deferred init: StartupIfNeeded"); LayersNative.StartupIfNeeded(); App.Log("deferred init: CreateNativeHandle"); CreateNativeHandle(); App.Log($"deferred init: _handle = {_handle:X}"); StartRenderLoop(); App.Log("deferred init: render loop started"); } catch (Exception ex) { App.Log($"deferred init FAILED: {ex}"); throw; } }); } private void OnActivated(object sender, WindowActivatedEventArgs e) { _isFocused = e.WindowActivationState != WindowActivationState.Deactivated; ApplyFade(); } private void OnClosed(object sender, WindowEventArgs args) { _renderTimer?.Stop(); _renderTimer = null; if (_handle != IntPtr.Zero) { LayersNative.layers_destroy(_handle); _handle = IntPtr.Zero; } } private void PointToRust() { var exe = System.Reflection.Assembly.GetEntryAssembly()?.Location; if (string.IsNullOrEmpty(exe)) return; var binDir = Path.GetDirectoryName(exe) ?? string.Empty; var pluginRoot = Path.GetDirectoryName(binDir) ?? string.Empty; if (string.IsNullOrEmpty(pluginRoot)) return; LayersNative.layers_set_plugin_root(pluginRoot); } private void CreateNativeHandle() { if (_handle != IntPtr.Zero) return; var scale = (float)RenderSurface.CompositionScaleX; var width = (float)RenderSurface.ActualWidth; var height = (float)RenderSurface.ActualHeight; if (width <= 0 || height <= 0 || scale <= 0) return; // wgpu's dx12 backend wants an ISwapChainPanelNative*, not the raw IUnknown. var iid = typeof(ISwapChainPanelNative).GUID; var unknown = Marshal.GetIUnknownForObject(RenderSurface); IntPtr native = IntPtr.Zero; try { int hr = Marshal.QueryInterface(unknown, in iid, out native); if (hr < 0 || native == IntPtr.Zero) return; _handle = LayersNative.layers_create_from_swap_chain_panel(native, width, height, scale); } finally { if (native != IntPtr.Zero) Marshal.Release(native); Marshal.Release(unknown); } } private DispatcherTimer? _renderTimer; private void StartRenderLoop() { _renderTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(1000.0 / 60.0), }; _renderTimer.Tick += (_, __) => { if (_handle != IntPtr.Zero) { LayersNative.layers_render(_handle); } }; _renderTimer.Start(); } private void ApplyFade() { double target = (_isFocused && _isHovered) ? 1.0 : (_isFocused || _isHovered) ? 0.5 : 0.1; if (Content is FrameworkElement root) { root.Opacity = target; } } private void RenderSurface_SizeChanged(object sender, SizeChangedEventArgs e) { if (_handle == IntPtr.Zero) { CreateNativeHandle(); return; } var scale = (float)RenderSurface.CompositionScaleX; LayersNative.layers_resize(_handle, (float)e.NewSize.Width, (float)e.NewSize.Height, scale); } private void RenderSurface_PointerMoved(object sender, PointerRoutedEventArgs e) { if (_handle == IntPtr.Zero) return; var p = e.GetCurrentPoint(RenderSurface).Position; LayersNative.layers_mouse_move(_handle, (float)p.X, (float)p.Y); } private void RenderSurface_PointerPressed(object sender, PointerRoutedEventArgs e) { RenderSurface.Focus(FocusState.Programmatic); PushMouseButton(e, pressed: true); } private void RenderSurface_PointerReleased(object sender, PointerRoutedEventArgs e) { PushMouseButton(e, pressed: false); } private void PushMouseButton(PointerRoutedEventArgs e, bool pressed) { if (_handle == IntPtr.Zero) return; var p = e.GetCurrentPoint(RenderSurface); uint btn; var props = p.Properties; if (props.IsLeftButtonPressed || (!pressed && !props.IsRightButtonPressed && !props.IsMiddleButtonPressed)) btn = 0; else if (props.IsRightButtonPressed) btn = 1; else if (props.IsMiddleButtonPressed) btn = 2; else btn = 0; LayersNative.layers_mouse_button(_handle, (float)p.Position.X, (float)p.Position.Y, btn, pressed); } private void RenderSurface_PointerWheel(object sender, PointerRoutedEventArgs e) { if (_handle == IntPtr.Zero) return; var p = e.GetCurrentPoint(RenderSurface); var dy = (float)p.Properties.MouseWheelDelta / 3.0f; LayersNative.layers_mouse_scroll(_handle, (float)p.Position.X, (float)p.Position.Y, 0.0f, dy); } private void RenderSurface_PointerEntered(object sender, PointerRoutedEventArgs e) { _isHovered = true; ApplyFade(); } private void RenderSurface_PointerExited(object sender, PointerRoutedEventArgs e) { _isHovered = false; if (_handle != IntPtr.Zero) { LayersNative.layers_mouse_left(_handle); } ApplyFade(); } private void RenderSurface_KeyDown(object sender, KeyRoutedEventArgs e) => DispatchKey(e, pressed: true); private void RenderSurface_KeyUp(object sender, KeyRoutedEventArgs e) => DispatchKey(e, pressed: false); private void DispatchKey(KeyRoutedEventArgs e, bool pressed) { if (_handle == IntPtr.Zero) return; uint named = WinKeyMap.MapVirtualKey(e.Key); string? text = named == 0 ? WinKeyMap.TextForKey(e.Key) : null; uint mods = WinKeyMap.CurrentModifiers(); LayersNative.layers_key_event(_handle, named, text, mods, (ushort)e.Key, pressed); } }