internal XlibWindow(XlibWindowProvider windowProvider) : base(windowProvider, Thread.CurrentThread) { _handle = new ValueLazy <nuint>(CreateWindowHandle); _properties = new PropertySet(); _title = typeof(XlibWindow).FullName !; _bounds = new Rectangle(float.NaN, float.NaN, float.NaN, float.NaN); _flowDirection = FlowDirection.TopToBottom; _readingDirection = ReadingDirection.LeftToRight; _isEnabled = true; _ = _state.Transition(to: Initialized); }
/// <inheritdoc /> public override void DispatchPending() { ThrowIfNotThread(ParentThread); var display = ((XlibDispatchProvider)DispatchProvider).Display; while (XPending(display) != 0) { XEvent xevent; _ = XNextEvent(display, &xevent); var isWmProtocolsEvent = (xevent.type == ClientMessage) && (xevent.xclient.format == 32) && (xevent.xclient.message_type == ((XlibDispatchProvider)DispatchProvider).WmProtocolsAtom); if (!isWmProtocolsEvent || (xevent.xclient.data.l[0] != (nint)((XlibDispatchProvider)DispatchProvider).DispatcherExitRequestedAtom)) { XlibWindowProvider.ForwardWindowEvent(&xevent, isWmProtocolsEvent); } else { OnExitRequested(); } } }
internal static void ForwardWindowEvent(XEvent *xevent, bool isWmProtocolsEvent) { IntPtr userData; var dispatchProvider = Xlib.XlibDispatchProvider.Instance; if (isWmProtocolsEvent && (xevent->xclient.data.l[0] == (IntPtr)(void *)dispatchProvider.WindowProviderCreateWindowAtom)) { // We allow the WindowProviderCreateWindowAtom message to be forwarded to the Window instance // for xevent->xany.window. This allows some delayed initialization to occur since most of the // fields in Window are lazy. if (Environment.Is64BitProcess) { var lowerBits = unchecked ((uint)xevent->xclient.data.l[2].ToInt64()); var upperBits = unchecked ((ulong)(uint)xevent->xclient.data.l[3].ToInt64()); userData = (IntPtr)((upperBits << 32) | lowerBits); } else { var bits = xevent->xclient.data.l[1].ToInt32(); userData = (IntPtr)bits; } _ = XChangeProperty( xevent->xany.display, xevent->xany.window, dispatchProvider.WindowWindowProviderAtom, dispatchProvider.SystemIntPtrAtom, format: 8, PropModeReplace, (byte *)&userData, nelements: IntPtr.Size ); } else { UIntPtr actualTypeReturn; int actualFormatReturn; UIntPtr nitemsReturn; UIntPtr bytesAfterReturn; IntPtr *propReturn; ThrowExternalExceptionIfFailed(nameof(XGetWindowProperty), XGetWindowProperty( xevent->xany.display, xevent->xany.window, dispatchProvider.WindowWindowProviderAtom, long_offset: IntPtr.Zero, long_length: (IntPtr)IntPtr.Size, delete: False, dispatchProvider.SystemIntPtrAtom, &actualTypeReturn, &actualFormatReturn, &nitemsReturn, &bytesAfterReturn, (byte **)&propReturn )); userData = *propReturn; } XlibWindowProvider windowProvider = null !; Dictionary <UIntPtr, XlibWindow>?windows = null; var forwardMessage = false; XlibWindow?window = null; if (userData != IntPtr.Zero) { windowProvider = (XlibWindowProvider)GCHandle.FromIntPtr(userData).Target !; windows = windowProvider._windows.Value; forwardMessage = (windows?.TryGetValue(xevent->xany.window, out window)).GetValueOrDefault(); } if (forwardMessage) { Assert(windows != null, Resources.ArgumentNullExceptionMessage, nameof(windows)); Assert(window != null, Resources.ArgumentNullExceptionMessage, nameof(window)); window.ProcessWindowEvent(xevent, isWmProtocolsEvent); if (isWmProtocolsEvent && (xevent->xclient.data.l[0] == (IntPtr)(void *)dispatchProvider.WmDeleteWindowAtom)) { // We forward the WM_DELETE_WINDOW message to the corresponding Window instance // so that it can still be properly disposed of in the scenario that the // xevent->xany.window was destroyed externally. _ = RemoveWindow(windows, xevent->xany.display, xevent->xany.window, dispatchProvider); } } }