diff --git a/backends/hwcomposer/CMakeLists.txt b/backends/hwcomposer/CMakeLists.txt index 6181b8eb9c..6d6794592c 100644 --- a/backends/hwcomposer/CMakeLists.txt +++ b/backends/hwcomposer/CMakeLists.txt @@ -11,6 +11,7 @@ target_link_libraries(KWinWaylandHwcomposerBackend libhybris::libhardware libhybris::hwcomposer libhybris::hybriseglplatform + libhybris::inputstack libhybris::sync ) diff --git a/backends/hwcomposer/hwcomposer.json b/backends/hwcomposer/hwcomposer.json index 404bba5384..1551bf5de1 100644 --- a/backends/hwcomposer/hwcomposer.json +++ b/backends/hwcomposer/hwcomposer.json @@ -1,3 +1,3 @@ { - "input": false + "input": true } diff --git a/backends/hwcomposer/hwcomposer_backend.cpp b/backends/hwcomposer/hwcomposer_backend.cpp index 48e44cd017..5ec3656804 100644 --- a/backends/hwcomposer/hwcomposer_backend.cpp +++ b/backends/hwcomposer/hwcomposer_backend.cpp @@ -25,9 +25,13 @@ along with this program. If not, see . // KWayland #include #include +#include // hybris/android #include #include +#include +#include +#include // based on test_hwcomposer.c from libhybris project (Apache 2 licensed) @@ -45,6 +49,68 @@ HwcomposerBackend::~HwcomposerBackend() if (m_device) { hwc_close_1(m_device); } + if (m_inputListener) { + android_input_stack_stop(); + android_input_stack_shutdown(); + delete m_inputListener; + } +} + +static QPointF eventPosition(Event *event) +{ + return QPointF(event->details.motion.pointer_coordinates[0].x, + event->details.motion.pointer_coordinates[0].y); +} + +void HwcomposerBackend::inputEvent(Event *event, void *context) +{ + HwcomposerBackend *backend = reinterpret_cast(context); + switch (event->type) { + case KEY_EVENT_TYPE: + switch (event->action) { + case ISCL_KEY_EVENT_ACTION_DOWN: + // TODO: implement + break; + case ISCL_KEY_EVENT_ACTION_UP: + // TODO: implement + break; + case ISCL_KEY_EVENT_ACTION_MULTIPLE: // TODO: implement + default: + break; + } + break; + case MOTION_EVENT_TYPE: { + const uint buttonIndex = (event->action & ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT; + switch (event->action & ISCL_MOTION_EVENT_ACTION_MASK) { + case ISCL_MOTION_EVENT_ACTION_DOWN: + case ISCL_MOTION_EVENT_ACTION_POINTER_DOWN: + backend->touchDown(buttonIndex, eventPosition(event), event->details.motion.event_time); + break; + case ISCL_MOTION_EVENT_ACTION_UP: + case ISCL_MOTION_EVENT_ACTION_POINTER_UP: + // first update position - up events can contain additional motion events + backend->touchMotion(0, eventPosition(event), event->details.motion.event_time); + backend->touchFrame(); + backend->touchUp(buttonIndex, event->details.motion.event_time); + break; + case ISCL_MOTION_EVENT_ACTION_MOVE: + // it's always for the first index, other touch points seem not to be provided + backend->touchMotion(0, eventPosition(event), event->details.motion.event_time); + backend->touchFrame(); + break; + case ISCL_MOTION_EVENT_ACTION_CANCEL: + backend->touchCancel(); + break; + default: + // TODO: implement + break; + } + break; + } + case HW_SWITCH_EVENT_TYPE: + qCDebug(KWIN_HWCOMPOSER) << "HW switch event:"; + break; + } } static KWayland::Server::OutputInterface *createOutput(hwc_composer_device_1_t *device) @@ -116,10 +182,36 @@ void HwcomposerBackend::init() qCDebug(KWIN_HWCOMPOSER) << "Display size:" << m_displaySize; m_device = hwcDevice; + initInput(); + emit screensQueried(); setReady(true); } +void HwcomposerBackend::initInput() +{ + Q_ASSERT(!m_inputListener); + m_inputListener = new AndroidEventListener; + m_inputListener->on_new_event = inputEvent; + m_inputListener->context = this; + + struct InputStackConfiguration config = { + true, + 10000, + m_displaySize.width(), + m_displaySize.height() + }; + + android_input_stack_initialize(m_inputListener, &config); + android_input_stack_start(); + + // we don't know what is really supported, but there is touch + // and kind of keyboard + waylandServer()->seat()->setHasPointer(false); + waylandServer()->seat()->setHasKeyboard(true); + waylandServer()->seat()->setHasTouch(true); +} + HwcomposerWindow *HwcomposerBackend::createSurface() { return new HwcomposerWindow(this); diff --git a/backends/hwcomposer/hwcomposer_backend.h b/backends/hwcomposer/hwcomposer_backend.h index 0ab8a0aa1d..de240090b4 100644 --- a/backends/hwcomposer/hwcomposer_backend.h +++ b/backends/hwcomposer/hwcomposer_backend.h @@ -29,6 +29,8 @@ along with this program. If not, see . typedef struct hwc_display_contents_1 hwc_display_contents_1_t; typedef struct hwc_layer_1 hwc_layer_1_t; typedef struct hwc_composer_device_1 hwc_composer_device_1_t; +struct Event; +struct AndroidEventListener; namespace KWin { @@ -59,8 +61,11 @@ public: } private: + static void inputEvent(Event *event, void *context); + void initInput(); QSize m_displaySize; hwc_composer_device_1_t *m_device = nullptr; + AndroidEventListener *m_inputListener = nullptr; }; class HwcomposerWindow : public HWComposerNativeWindow diff --git a/cmake/modules/Findlibhybris.cmake b/cmake/modules/Findlibhybris.cmake index 68904d0e9f..1c75b205c9 100644 --- a/cmake/modules/Findlibhybris.cmake +++ b/cmake/modules/Findlibhybris.cmake @@ -47,6 +47,7 @@ if(NOT WIN32) pkg_check_modules(PKG_hwcomposerwindow QUIET hwcomposer-egl) pkg_check_modules(PKG_hybriseglplatform QUIET hybris-egl-platform) pkg_check_modules(PKG_hybrissync QUIET libsync) + pkg_check_modules(PKG_hybrisinputstack QUIET libis) set(libhardware_DEFINITIONS ${PKG_libhardware_CFLAGS_OTHER}) set(libhardware_VERSION ${PKG_libhardware_VERSION}) @@ -201,7 +202,40 @@ if(NOT WIN32) mark_as_advanced(hybrissync_LIBRARY) - if(libhardware_FOUND AND libhwcomposer_FOUND AND hybriseglplatform_FOUND AND hybrissync_FOUND) + ############################################## + # hybrisinputstack + ############################################## + set(hybrisinputstack_DEFINITIONS ${PKG_hybrisinputstack_CFLAGS_OTHER}) + set(hybrisinputstack_VERSION ${PKG_hybrisinputstack_VERSION}) + + find_library(hybrisinputstack_LIBRARY + NAMES + libis.so + HINTS + ${PKG_hybrisinputstack_LIBRARY_DIRS} + ) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(hybrisinputstack + FOUND_VAR + hybrisinputstack_FOUND + REQUIRED_VARS + hybrisinputstack_LIBRARY + VERSION_VAR + hybrisinputstack_VERSION + ) + + if(hybrisinputstack_FOUND AND NOT TARGET libhybris::inputstack) + add_library(libhybris::inputstack UNKNOWN IMPORTED) + set_target_properties(libhybris::inputstack PROPERTIES + IMPORTED_LOCATION "${hybrisinputstack_LIBRARY}" + INTERFACE_COMPILE_OPTIONS "${hybrisinputstack_DEFINITIONS}" + ) + endif() + + mark_as_advanced(hybrisinputstack_LIBRARY) + + if(libhardware_FOUND AND libhwcomposer_FOUND AND hybriseglplatform_FOUND AND hybrissync_FOUND AND hybrisinputstack_FOUND) set(libhybris_FOUND TRUE) else() set(libhybris_FOUND FALSE)