Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        /// <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();
                }
            }
        }
Ejemplo n.º 3
0
        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);
                }
            }
        }