[backends/hwcomper] Initial support for input handling
Unfortunately on libhybris enabled systems libinput doesn't work, thus the backend needs to handle input events which can be read from hybris. So far the backend only handles touch events properly, though some aspects look wrong. E.g. motion gives only for one touch contact point. Unfortunately the documentation is quite weak, so there might be something important missing.
This commit is contained in:
parent
1f62c0acb0
commit
6a66d84f5c
5 changed files with 134 additions and 2 deletions
|
@ -11,6 +11,7 @@ target_link_libraries(KWinWaylandHwcomposerBackend
|
|||
libhybris::libhardware
|
||||
libhybris::hwcomposer
|
||||
libhybris::hybriseglplatform
|
||||
libhybris::inputstack
|
||||
libhybris::sync
|
||||
)
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"input": false
|
||||
"input": true
|
||||
}
|
||||
|
|
|
@ -25,9 +25,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
// KWayland
|
||||
#include <KWayland/Server/display.h>
|
||||
#include <KWayland/Server/output_interface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
// hybris/android
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwcomposer.h>
|
||||
#include <hybris/input/input_stack_compatibility_layer.h>
|
||||
#include <hybris/input/input_stack_compatibility_layer_flags_key.h>
|
||||
#include <hybris/input/input_stack_compatibility_layer_flags_motion.h>
|
||||
|
||||
// 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<HwcomposerBackend*>(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);
|
||||
|
|
|
@ -29,6 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue