예제 #1
0
        protected override void Initialize()
        {
            _xkbContext = XkbCommon.xkb_context_new();
            if (_xkbContext == null)
            {
                throw new OpenWindowException("Failed to create xkbcommon context.");
            }

            LogDebug("Connecting to display...");

            _wlDisplay = WlDisplay.Connect();
            if (_wlDisplay.IsNull)
            {
                var error = WaylandClient.wl_display_get_error(null);
                throw new OpenWindowException($"Failed to connect to Wayland display ({error}).");
            }
            _wlDisplay.SetListener(DisplayErrorCallback, null);

            LogDebug("Connected to display.");

            WaylandBindings.Load();
            XdgShellBindings.Load();
            XdgDecorationUnstableV1Bindings.Load();
            ViewporterBindings.Load();

            _wlRegistry = _wlDisplay.GetRegistry();

            if (_wlRegistry.IsNull)
            {
                throw new OpenWindowException("Failed to get Wayland registry.");
            }

            LogDebug("Got registry.");

            _wlRegistry.SetListener(RegistryGlobalCallback, RegistryGlobalRemoveCallback);

            LogDebug("Initiating first display roundtrip.");
            _wlDisplay.Roundtrip();

            LogDebug("Initiating second display roundtrip.");
            _wlDisplay.Roundtrip();

            if (_wlCompositor.IsNull)
            {
                throw new OpenWindowException("Server did not advertise a compositor.");
            }
            if (_xdgWmBase.IsNull)
            {
                if (_wlShellAvailable)
                {
                    LogError("Server did not advertise xdg_wm_base, but it advertised a wl_shell. wl_shell is deprecated and not supported by OpenWindow.");
                }
                throw new OpenWindowException("Server did not advertise xdg_wm_base.");
            }
        }
예제 #2
0
        private void KeymapCallback(void *data, wl_keyboard *proxy, wl_keyboard_keymap_format format, int fd, uint size)
        {
            if (format != wl_keyboard_keymap_format.XkbV1)
            {
                Libc.close(fd);
                throw new NotImplementedException("Only xkbcommon compatible keymaps are currently supported.");
            }

            var kbdStr = Libc.mmap(null, size, Libc.PROT_READ, Libc.MAP_PRIVATE, fd, 0);

            if (kbdStr == null)
            {
                Libc.close(fd);
                return;
            }

            var newKeymap = XkbCommon.xkb_keymap_new_from_string(_xkbContext, kbdStr, XkbCommon.XKB_KEYMAP_FORMAT_TEXT_V1);

            Libc.munmap(kbdStr, size);
            Libc.close(fd);

            if (newKeymap == null)
            {
                throw new OpenWindowException("Failed to create xkb keymap.");
            }

            var newState = XkbCommon.xkb_state_new(newKeymap);

            if (newState == null)
            {
                XkbCommon.xkb_keymap_unref(newKeymap);
                throw new OpenWindowException("Failed to create xkb state.");
            }

            if (_xkbKeymap != null)
            {
                XkbCommon.xkb_keymap_unref(_xkbKeymap);
            }
            if (_xkbState != null)
            {
                XkbCommon.xkb_state_unref(_xkbState);
            }

            _xkbKeymap = newKeymap;
            _xkbState  = newState;

            UpdateKeymap();
        }
예제 #3
0
        private void KeyboardKeyCallback(void *data, wl_keyboard *proxy, uint serial, uint time, uint lsc, wl_keyboard_key_state state)
        {
            if (lsc >= WaylandKeyMaps.LinuxToOwScanCode.Length)
            {
                return;
            }

            var osc = WaylandKeyMaps.LinuxToOwScanCode[lsc];

            SetKey(osc, state == wl_keyboard_key_state.Pressed);

            if (state == wl_keyboard_key_state.Released)
            {
                return;
            }

            // this returns zero if the key press generates more than 1 character in UTF32
            var utf32 = XkbCommon.xkb_state_key_get_utf32(_xkbState, lsc + 8);

            if (utf32 != 0)
            {
                SendCharacter(utf32);
            }
            else
            {
                var strBufSize = XkbCommon.xkb_state_key_get_utf8(_xkbState, lsc + 8, null, 0);
                if (strBufSize == 0)
                {
                    return;
                }

                byte *strBuf = stackalloc byte[strBufSize];
                XkbCommon.xkb_state_key_get_utf8(_xkbState, lsc + 8, strBuf, strBufSize);

                // We send text in UTF-32 i.e. no more than 32 bits at a time
                var offset = 0;
                while (ReadUtf32FromUtf8(strBuf, ref offset, out utf32))
                {
                    SendCharacter(utf32);
                }
            }
        }
예제 #4
0
        private void UpdateKeymap()
        {
            for (var lsc = 0; lsc < WaylandKeyMaps.LinuxToOwScanCode.Length; lsc++)
            {
                var osc = WaylandKeyMaps.LinuxToOwScanCode[lsc];
                if (osc == ScanCode.Unknown)
                {
                    continue;
                }

                var sym = XkbCommon.xkb_state_key_get_one_sym(_xkbState, (uint)(lsc + 8));
                var owk = WaylandKeyMaps.XkbToOwKey(sym);

                if (owk == Key.Unknown)
                {
                    continue;
                }

                _keyboardState.Set(osc, owk);
            }

            _keyboardState.Set(ScanCode.PrintScreen, Key.PrintScreen);
        }