Add simple keyboard handling for wayland.
This commit is contained in:
parent
e2cc98e1fb
commit
918c1d3046
8 changed files with 175 additions and 28 deletions
|
@ -33,7 +33,7 @@ sudo apt-get install libpng-dev
|
|||
#### Window rendering
|
||||
|
||||
```bash
|
||||
sudo apt-get install libwayland-dev wayland-protocols
|
||||
sudo apt-get install libwayland-dev wayland-protocols libx11-dev libxkbcommon-dev libx11-xcb-dev
|
||||
```
|
||||
|
||||
We need to generate suitable xdg shell c code for wayland:
|
||||
|
@ -48,6 +48,13 @@ export WAYLAND_EXTENSION_DIR=$WORK_DIR
|
|||
|
||||
In `xdg-shell-protocol.cpp` - we need access to `xdg_wm_base_interface` so export it also `extern const struct wl_interface xdg_wm_base_interface;` as per similar interface structs.
|
||||
|
||||
#### 3D Rendering
|
||||
|
||||
```bash
|
||||
sudo apt-get install libgl-dev
|
||||
```
|
||||
|
||||
|
||||
# Build from Source
|
||||
|
||||
## Linux
|
||||
|
|
|
@ -17,7 +17,8 @@ if(UNIX)
|
|||
ui_interfaces/x11/XcbKeyboard.cpp
|
||||
ui_interfaces/x11/GlxInterface.cpp
|
||||
)
|
||||
list(APPEND platform_LIBS ${X11_LIBRARIES} ${X11_xcb_LIB} ${X11_X11_xcb_LIB})
|
||||
list(APPEND platform_LIBS ${X11_LIBRARIES} ${X11_xcb_LIB} ${X11_X11_xcb_LIB} ${X11_xkbcommon_LIB})
|
||||
list(APPEND X11_INCLUDE_DIRS ${X11_xkbcommon_INCLUDE_PATH})
|
||||
else()
|
||||
message(STATUS "x11 development headers not found - skipping support")
|
||||
endif()
|
||||
|
@ -38,6 +39,7 @@ if(UNIX)
|
|||
ui_interfaces/wayland/WaylandBuffer.cpp
|
||||
ui_interfaces/wayland/WaylandPointerInterface.cpp
|
||||
ui_interfaces/wayland/WaylandSeatInterface.cpp
|
||||
ui_interfaces/wayland/WaylandKeyboard.cpp
|
||||
${WAYLAND_EXTENSIONS_INCLUDE_DIR}/xdg-shell-protocol.cpp
|
||||
)
|
||||
set(_HAS_WAYLAND ON)
|
||||
|
@ -81,6 +83,7 @@ target_include_directories(windows PUBLIC
|
|||
"${PROJECT_SOURCE_DIR}/src/ui_elements"
|
||||
"${PROJECT_SOURCE_DIR}/src/ui_elements/widgets"
|
||||
${WAYLAND_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(windows PUBLIC ${platform_LIBS} core geometry graphics ui_elements ${WAYLAND_CLIENT_LIBRARY})
|
||||
|
|
113
src/windows/ui_interfaces/wayland/WaylandKeyboard.cpp
Normal file
113
src/windows/ui_interfaces/wayland/WaylandKeyboard.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "WaylandKeyboard.h"
|
||||
|
||||
#include "FileLogger.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
void WaylandKeyboard::keyboardKeymapEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandKeyboard*>(data);
|
||||
thisClass->onKeymapEvent(wl_keyboard, format, fd, size);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::keyboardEnterEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandKeyboard*>(data);
|
||||
thisClass->onEnterEvent(keys);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::keyboardPressedEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandKeyboard*>(data);
|
||||
thisClass->onPressedEvent(key, state);
|
||||
}
|
||||
|
||||
static void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface)
|
||||
{
|
||||
fprintf(stderr, "keyboard leave\n");
|
||||
}
|
||||
|
||||
static void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, int32_t rate, int32_t delay)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void WaylandKeyboard::keyboardModifierEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandKeyboard*>(data);
|
||||
thisClass->onKeyboardModifier(mods_depressed, mods_latched, mods_locked, group);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::onKeyboardModifier(uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
|
||||
{
|
||||
xkb_state_update_mask(mXkbState, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::onEnterEvent(struct wl_array *keys)
|
||||
{
|
||||
MLOG_INFO("keyboard enter; keys pressed are:");
|
||||
|
||||
void* key;
|
||||
wl_array_for_each(key, keys)
|
||||
{
|
||||
uint32_t* key_type = static_cast<uint32_t*>(key);
|
||||
|
||||
char buf[128];
|
||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, *key_type + 8);
|
||||
xkb_keysym_get_name(sym, buf, sizeof(buf));
|
||||
fprintf(stderr, "sym: %-12s (%d), ", buf, sym);
|
||||
xkb_state_key_get_utf8(mXkbState, *key_type + 8, buf, sizeof(buf));
|
||||
fprintf(stderr, "utf8: '%s'\n", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void WaylandKeyboard::onPressedEvent(uint32_t key, uint32_t state)
|
||||
{
|
||||
char buf[128];
|
||||
uint32_t keycode = key + 8;
|
||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, keycode);
|
||||
xkb_keysym_get_name(sym, buf, sizeof(buf));
|
||||
const char *action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? "press" : "release";
|
||||
fprintf(stderr, "key %s: sym: %-12s (%d), ", action, buf, sym);
|
||||
xkb_state_key_get_utf8(mXkbState, keycode, buf, sizeof(buf));
|
||||
fprintf(stderr, "utf8: '%s'\n", buf);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::onKeymapEvent(struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size)
|
||||
{
|
||||
// assert(format == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1);
|
||||
char* map_shm = static_cast<char*>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
|
||||
// assert(map_shm != MAP_FAILED);
|
||||
|
||||
struct xkb_keymap* xkb_keymap = xkb_keymap_new_from_string(mXkbContext, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
munmap(map_shm, size);
|
||||
close(fd);
|
||||
|
||||
struct xkb_state* xkb_state = xkb_state_new(xkb_keymap);
|
||||
xkb_keymap_unref(mXkbKeymap);
|
||||
xkb_state_unref(mXkbState);
|
||||
mXkbKeymap = xkb_keymap;
|
||||
mXkbState = xkb_state;
|
||||
}
|
||||
|
||||
WaylandKeyboard::WaylandKeyboard(wl_keyboard* keyboard)
|
||||
: mKeyboard(keyboard)
|
||||
{
|
||||
mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
|
||||
mKeyboardListener.keymap = keyboardKeymapEvent;
|
||||
mKeyboardListener.enter = keyboardEnterEvent;
|
||||
mKeyboardListener.key = keyboardPressedEvent;
|
||||
mKeyboardListener.leave = wl_keyboard_leave;
|
||||
mKeyboardListener.modifiers = keyboardModifierEvent;
|
||||
mKeyboardListener.repeat_info = wl_keyboard_repeat_info;
|
||||
|
||||
wl_keyboard_add_listener(mKeyboard, &mKeyboardListener, this);
|
||||
}
|
||||
|
||||
|
||||
WaylandKeyboard::~WaylandKeyboard()
|
||||
{
|
||||
wl_keyboard_release(mKeyboard);
|
||||
}
|
30
src/windows/ui_interfaces/wayland/WaylandKeyboard.h
Normal file
30
src/windows/ui_interfaces/wayland/WaylandKeyboard.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "wayland-client.h"
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
class WaylandKeyboard
|
||||
{
|
||||
public:
|
||||
WaylandKeyboard(wl_keyboard* keyboard);
|
||||
|
||||
~WaylandKeyboard();
|
||||
|
||||
private:
|
||||
static void keyboardKeymapEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size);
|
||||
static void keyboardEnterEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys);
|
||||
static void keyboardPressedEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state);
|
||||
static void keyboardModifierEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
|
||||
|
||||
void onKeyboardModifier(uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
|
||||
void onKeymapEvent(struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size);
|
||||
void onEnterEvent(struct wl_array *keys);
|
||||
void onPressedEvent(uint32_t key, uint32_t state);
|
||||
|
||||
wl_keyboard* mKeyboard{nullptr};
|
||||
xkb_state* mXkbState{nullptr};
|
||||
xkb_context* mXkbContext{nullptr};
|
||||
xkb_keymap* mXkbKeymap{nullptr};
|
||||
wl_keyboard_listener mKeyboardListener;
|
||||
};
|
|
@ -22,6 +22,11 @@ static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
|
|||
|
||||
}
|
||||
|
||||
WaylandPointerInterface::~WaylandPointerInterface()
|
||||
{
|
||||
wl_pointer_release(mPointer);
|
||||
}
|
||||
|
||||
void WaylandPointerInterface::pointerFrameEvent(void *data, struct wl_pointer *wl_pointer)
|
||||
{
|
||||
auto thisClass = static_cast<WaylandPointerInterface*>(data);
|
||||
|
@ -122,8 +127,3 @@ WaylandPointerInterface::WaylandPointerInterface(wl_pointer* pointer)
|
|||
|
||||
wl_pointer_add_listener(mPointer, &mPointerListener, this);
|
||||
}
|
||||
|
||||
wl_pointer* WaylandPointerInterface::getPointer() const
|
||||
{
|
||||
return mPointer;
|
||||
}
|
||||
|
|
|
@ -7,10 +7,9 @@ class WaylandPointerInterface
|
|||
public:
|
||||
WaylandPointerInterface(wl_pointer* pointer);
|
||||
|
||||
wl_pointer* getPointer() const;
|
||||
~WaylandPointerInterface();
|
||||
|
||||
private:
|
||||
|
||||
static void pointerEnterEvent(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
static void pointerLeaveEvent(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface);
|
||||
static void pointerMotionEvent(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y);
|
||||
|
|
|
@ -18,8 +18,18 @@ void WaylandSeatInterface::onSeatCapabilitiesEvent(uint32_t capabilities)
|
|||
}
|
||||
else if (!have_pointer && mPointerInterface!= nullptr)
|
||||
{
|
||||
wl_pointer_release(mPointerInterface->getPointer());
|
||||
mPointerInterface.release();
|
||||
mPointerInterface.reset();
|
||||
}
|
||||
|
||||
const bool have_keyboard = capabilities & WL_SEAT_CAPABILITY_KEYBOARD;
|
||||
if (have_keyboard && mKeyboard == nullptr)
|
||||
{
|
||||
auto keyboard = wl_seat_get_keyboard(mSeat);
|
||||
mKeyboard = std::make_unique<WaylandKeyboard>(keyboard);
|
||||
}
|
||||
else if (!have_keyboard && mKeyboard!= nullptr)
|
||||
{
|
||||
mKeyboard.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,13 +46,3 @@ void WaylandSeatInterface::seatNameEvent(void *data, struct wl_seat *wl_seat, co
|
|||
{
|
||||
MLOG_INFO("seat name: " << name);
|
||||
}
|
||||
|
||||
void WaylandSeatInterface::setKeyboard(wl_keyboard* keyboard)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void WaylandSeatInterface::setPointer(wl_pointer* pointer)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "WaylandPointerInterface.h"
|
||||
#include "WaylandKeyboard.h"
|
||||
|
||||
#include "wayland-client.h"
|
||||
|
||||
|
@ -12,21 +13,15 @@ public:
|
|||
WaylandSeatInterface(wl_seat* seat);
|
||||
|
||||
private:
|
||||
|
||||
static void seatCapabilitiesEvent(void *data, struct wl_seat *wl_seat, uint32_t capabilities);
|
||||
|
||||
static void seatNameEvent(void *data, struct wl_seat *wl_seat, const char *name);
|
||||
|
||||
void onSeatCapabilitiesEvent(uint32_t capabilities);
|
||||
|
||||
void setKeyboard(wl_keyboard* keyboard);
|
||||
|
||||
void setPointer(wl_pointer* pointer);
|
||||
|
||||
wl_seat* mSeat{nullptr};
|
||||
wl_seat_listener mSeatListener;
|
||||
|
||||
wl_keyboard* mKeyboard{nullptr};
|
||||
|
||||
std::unique_ptr<WaylandKeyboard> mKeyboard;
|
||||
std::unique_ptr<WaylandPointerInterface> mPointerInterface;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue