diff --git a/README.md b/README.md index 2730bf5..fdb1b67 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/windows/CMakeLists.txt b/src/windows/CMakeLists.txt index b05779a..1f89e2c 100644 --- a/src/windows/CMakeLists.txt +++ b/src/windows/CMakeLists.txt @@ -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}) diff --git a/src/windows/ui_interfaces/wayland/WaylandKeyboard.cpp b/src/windows/ui_interfaces/wayland/WaylandKeyboard.cpp new file mode 100644 index 0000000..b18ec62 --- /dev/null +++ b/src/windows/ui_interfaces/wayland/WaylandKeyboard.cpp @@ -0,0 +1,113 @@ +#include "WaylandKeyboard.h" + +#include "FileLogger.h" + +#include +#include + +void WaylandKeyboard::keyboardKeymapEvent(void *data, struct wl_keyboard *wl_keyboard, uint32_t format, int32_t fd, uint32_t size) +{ + auto thisClass = static_cast(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(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(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(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(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(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); +} diff --git a/src/windows/ui_interfaces/wayland/WaylandKeyboard.h b/src/windows/ui_interfaces/wayland/WaylandKeyboard.h new file mode 100644 index 0000000..ee310b3 --- /dev/null +++ b/src/windows/ui_interfaces/wayland/WaylandKeyboard.h @@ -0,0 +1,30 @@ +#pragma once + +#include "wayland-client.h" + +#include + +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; +}; diff --git a/src/windows/ui_interfaces/wayland/WaylandPointerInterface.cpp b/src/windows/ui_interfaces/wayland/WaylandPointerInterface.cpp index 8c367c4..a0ca2e1 100644 --- a/src/windows/ui_interfaces/wayland/WaylandPointerInterface.cpp +++ b/src/windows/ui_interfaces/wayland/WaylandPointerInterface.cpp @@ -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(data); @@ -122,8 +127,3 @@ WaylandPointerInterface::WaylandPointerInterface(wl_pointer* pointer) wl_pointer_add_listener(mPointer, &mPointerListener, this); } - -wl_pointer* WaylandPointerInterface::getPointer() const -{ - return mPointer; -} diff --git a/src/windows/ui_interfaces/wayland/WaylandPointerInterface.h b/src/windows/ui_interfaces/wayland/WaylandPointerInterface.h index 1caa38f..3b13421 100644 --- a/src/windows/ui_interfaces/wayland/WaylandPointerInterface.h +++ b/src/windows/ui_interfaces/wayland/WaylandPointerInterface.h @@ -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); diff --git a/src/windows/ui_interfaces/wayland/WaylandSeatInterface.cpp b/src/windows/ui_interfaces/wayland/WaylandSeatInterface.cpp index 35bb09d..a9f9935 100644 --- a/src/windows/ui_interfaces/wayland/WaylandSeatInterface.cpp +++ b/src/windows/ui_interfaces/wayland/WaylandSeatInterface.cpp @@ -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(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) -{ - -} diff --git a/src/windows/ui_interfaces/wayland/WaylandSeatInterface.h b/src/windows/ui_interfaces/wayland/WaylandSeatInterface.h index 11f4139..ca21d42 100644 --- a/src/windows/ui_interfaces/wayland/WaylandSeatInterface.h +++ b/src/windows/ui_interfaces/wayland/WaylandSeatInterface.h @@ -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 mKeyboard; std::unique_ptr mPointerInterface; };