Skip to content

Commit

Permalink
Simplify pen to mouse events logic (#310)
Browse files Browse the repository at this point in the history
* Simplify pen to mouse events logic

* Remove EventFilter::root and fix bug

* Fix button logic

* Fix compile

* Filter handled events

* Use TabletEvent::button() instead of hard coded

* Update eventfilter.cpp
  • Loading branch information
Eeems authored Jan 14, 2024
1 parent 1c997c4 commit 8ed7acc
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 144 deletions.
3 changes: 0 additions & 3 deletions applications/launcher/controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <QGuiApplication>
#include <QMutableListIterator>
#include <liboxide.h>
#include <liboxide/eventfilter.h>
#include <liboxide/sysobject.h>

#include "appitem.h"
Expand All @@ -19,7 +18,6 @@
using namespace codes::eeems::oxide1;
using codes::eeems::oxide1::Power;
using Oxide::SysObject;
using Oxide::EventFilter;
using namespace Oxide::Sentry;

enum State { Normal, PowerSaving };
Expand Down Expand Up @@ -61,7 +59,6 @@ class Controller : public QObject
Q_PROPERTY(int maxTouchHeight READ maxTouchHeight)
public:
static std::string exec(const char* cmd);
EventFilter* filter;
QObject* stateController;
QObject* root = nullptr;
explicit Controller(QObject* parent = 0)
Expand Down
6 changes: 2 additions & 4 deletions applications/launcher/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <cstdlib>
#include <signal.h>
#include <liboxide.h>
#include <liboxide/eventfilter.h>

#include "controller.h"

Expand All @@ -30,16 +31,13 @@ int main(int argc, char* argv[]){
deviceSettings.setupQtEnvironment();
QGuiApplication app(argc, argv);
sentry_init("oxide", argv);
auto filter = new EventFilter(&app);
app.setOrganizationName("Eeems");
app.setOrganizationDomain(OXIDE_SERVICE);
app.setApplicationName("oxide");
app.setApplicationDisplayName("Launcher");
app.installEventFilter(filter);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
Controller* controller = new Controller();
controller->filter = filter;
qmlRegisterAnonymousType<AppItem>("codes.eeems.oxide", 2);
qmlRegisterAnonymousType<Controller>("codes.eeems.oxide", 2);
context->setContextProperty("screenGeometry", app.primaryScreen()->geometry());
Expand All @@ -52,7 +50,7 @@ int main(int argc, char* argv[]){
}
QObject* root = engine.rootObjects().first();
controller->root = root;
filter->root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
QObject* stateController = root->findChild<QObject*>("stateController");
if(!stateController){
qDebug() << "Can't find stateController";
Expand Down
5 changes: 2 additions & 3 deletions applications/lockscreen/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ int main(int argc, char *argv[]){
deviceSettings.setupQtEnvironment();
QGuiApplication app(argc, argv);
sentry_init("decay", argv);
auto filter = new EventFilter(&app);
app.installEventFilter(filter);
app.setOrganizationName("Eeems");
app.setOrganizationDomain(OXIDE_SERVICE);
app.setApplicationName("decay");
Expand All @@ -34,7 +32,8 @@ int main(int argc, char *argv[]){
return -1;
}
auto root = engine.rootObjects().first();
filter->root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
controller.setRoot(root);
qDebug() << root;
return app.exec();
}
4 changes: 1 addition & 3 deletions applications/process-manager/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ int main(int argc, char *argv[]){
app.setApplicationName("tarnish");
app.setApplicationDisplayName("Process Monitor");
app.setApplicationVersion(APP_VERSION);
EventFilter filter;
app.installEventFilter(&filter);
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
Controller controller(&engine);
Expand All @@ -38,7 +36,7 @@ int main(int argc, char *argv[]){
return -1;
}
QObject* root = engine.rootObjects().first();
filter.root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
QQuickItem* tasksView = root->findChild<QQuickItem*>("tasksView");
if(!tasksView){
qDebug() << "Can't find tasksView";
Expand Down
4 changes: 1 addition & 3 deletions applications/screenshot-viewer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ int main(int argc, char *argv[]){
deviceSettings.setupQtEnvironment();
QGuiApplication app(argc, argv);
sentry_init("anxiety", argv);
auto filter = new EventFilter(&app);
app.installEventFilter(filter);
app.setOrganizationName("Eeems");
app.setOrganizationDomain(OXIDE_SERVICE);
app.setApplicationName("anxiety");
Expand All @@ -40,7 +38,7 @@ int main(int argc, char *argv[]){
return -1;
}
auto root = engine.rootObjects().first();
filter->root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
controller.setRoot(root);

signal(SIGINT, sigHandler);
Expand Down
4 changes: 1 addition & 3 deletions applications/task-switcher/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ int main(int argc, char *argv[]){
deviceSettings.setupQtEnvironment();
QGuiApplication app(argc, argv);
sentry_init("corrupt", argv);
auto filter = new EventFilter(&app);
app.installEventFilter(filter);
app.setOrganizationName("Eeems");
app.setOrganizationDomain(OXIDE_SERVICE);
app.setApplicationName("corrupt");
Expand All @@ -46,7 +44,7 @@ int main(int argc, char *argv[]){
return -1;
}
auto root = engine.rootObjects().first();
filter->root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
controller.setRoot(root);

signal(SIGINT, sigHandler);
Expand Down
171 changes: 57 additions & 114 deletions shared/liboxide/eventfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,21 @@
#include <QScreen>
#include <QGuiApplication>

#include <qpa/qwindowsysteminterface.h>
#include <qpa/qwindowsysteminterface_p.h>

#define DISPLAYWIDTH 1404
#define DISPLAYHEIGHT 1872.0
#define WACOM_X_SCALAR (float(DISPLAYWIDTH) / float(DISPLAYHEIGHT))
#define WACOM_Y_SCALAR (float(DISPLAYHEIGHT) / float(DISPLAYWIDTH))
//#define DEBUG_EVENTS
#ifdef DEBUG_EVENTS
#define O_DEBUG_EVENT(msg) O_DEBUG(msg)
#else
#define O_DEBUG_EVENT(msg)
#endif

namespace Oxide{
EventFilter::EventFilter(QObject *parent) : QObject(parent), root(nullptr){}
EventFilter::EventFilter(QObject *parent) : QObject(parent) {}

QPointF swap(QPointF pointF){
return QPointF(pointF.y(), pointF.x());
Expand All @@ -32,124 +34,65 @@ namespace Oxide{
pointF.setY((DISPLAYWIDTH - pointF.y()) * WACOM_Y_SCALAR);
return pointF;
}
QPointF globalPos(QQuickItem* obj){
qreal x = obj->x();
qreal y = obj->y();
while(obj->parentItem() != nullptr){
obj = obj->parentItem();
x += obj->x();
y += obj->y();

bool EventFilter::eventFilter(QObject* obj, QEvent* ev){
auto type = ev->type();
if(QObject::eventFilter(obj, ev)){
return true;
}
return QPointF(x, y);
}
QMouseEvent* toMouseEvent(QEvent::Type type, QEvent* ev){
auto tabletEvent = (QTabletEvent*)ev;
auto button = tabletEvent->pressure() > 0 || type == QMouseEvent::MouseButtonRelease ? Qt::LeftButton : Qt::NoButton;
return new QMouseEvent(
type,
transpose(tabletEvent->posF()),
transpose(tabletEvent->globalPosF()),
transpose(tabletEvent->globalPosF()),
button,
button,
tabletEvent->modifiers()
);
}
bool isAt(QQuickItem* item, QPointF pos){
auto itemPos = globalPos(item);
auto otherItemPos = QPointF(itemPos.x() + item->width(), itemPos.y() + item->height());
return pos.x() >= itemPos.x() && pos.x() <= otherItemPos.x() && pos.y() >= itemPos.y() && pos.y() <= otherItemPos.y();
}
QList<QObject*> widgetsAt(QQuickItem* root, QPointF pos){
QList<QObject*> result;
auto children = root->findChildren<QQuickItem*>();
for(auto child : children){
if(result.contains(child)){
continue;
}
if(!child->isVisible() || !child->isEnabled()){
continue;
}
if(child->acceptedMouseButtons() & Qt::LeftButton && isAt(child, pos)){
result.append((QObject*)child);
for(auto item : widgetsAt(child, pos)){
if(!result.contains(item)){
result.append(item);
}
}
continue;
}
if(!child->clip()){
for(auto item : widgetsAt(child, pos)){
if(!result.contains(item)){
result.append(item);
}
}
}
if(type == QEvent::TabletPress){
O_DEBUG_EVENT(ev);
auto tabletEvent = (QTabletEvent*)ev;
QWindowSystemInterface::handleMouseEvent(
nullptr,
transpose(tabletEvent->posF()),
transpose(tabletEvent->globalPosF()),
tabletEvent->buttons(),
tabletEvent->button(),
QEvent::MouseButtonPress
);
tabletEvent->accept();
return true;
}
return result;
}
int parentCount(QQuickItem* obj){
int count = 0;
while(obj->parentItem()){
count++;
obj = obj->parentItem();
if(type == QEvent::TabletRelease){
O_DEBUG_EVENT(ev);
auto tabletEvent = (QTabletEvent*)ev;
QWindowSystemInterface::handleMouseEvent(
nullptr,
transpose(tabletEvent->posF()),
transpose(tabletEvent->globalPosF()),
tabletEvent->buttons(),
tabletEvent->button(),
QEvent::MouseButtonRelease
);
tabletEvent->accept();
return true;
}
return count;
}
void postEvent(QEvent::Type type, QEvent* ev, QQuickItem* root){
auto mouseEvent = toMouseEvent(type, ev);
auto pos = mouseEvent->globalPos();
for(auto postWidget : widgetsAt(root, pos)){
if(parentCount((QQuickItem*)postWidget)){
O_DEBUG_EVENT("postWidget: " << postWidget);
auto event = new QMouseEvent(
mouseEvent->type(), mouseEvent->localPos(), mouseEvent->windowPos(),
mouseEvent->screenPos(), mouseEvent->button(), mouseEvent->buttons(),
mouseEvent->modifiers()
);
auto widgetPos = globalPos((QQuickItem*)postWidget);
auto localPos = event->localPos();
localPos.setX(pos.x() - widgetPos.x());
localPos.setY((pos.y()) - widgetPos.y());
event->setLocalPos(localPos);
QGuiApplication::postEvent(postWidget, event);
}
if(type == QEvent::TabletMove){
O_DEBUG_EVENT(ev);
auto tabletEvent = (QTabletEvent*)ev;
QWindowSystemInterface::handleMouseEvent(
nullptr,
transpose(tabletEvent->posF()),
transpose(tabletEvent->globalPosF()),
tabletEvent->buttons(),
tabletEvent->button(),
QEvent::MouseMove
);
tabletEvent->accept();
return true;
}
delete mouseEvent;
}

bool EventFilter::eventFilter(QObject* obj, QEvent* ev){
auto type = ev->type();
bool filtered = QObject::eventFilter(obj, ev);
if(!filtered){
if(type == QEvent::TabletPress){
O_DEBUG_EVENT(ev);
postEvent(QMouseEvent::MouseButtonPress, ev, root);
}else if(type == QEvent::TabletRelease){
O_DEBUG_EVENT(ev);
postEvent(QMouseEvent::MouseButtonRelease, ev, root);
}else if(type == QEvent::TabletMove){
O_DEBUG_EVENT(ev);
postEvent(QMouseEvent::MouseMove, ev, root);
}
#ifdef DEBUG_EVENTS
else if(
type == QEvent::MouseMove
|| type == QEvent::MouseButtonPress
|| type == QEvent::MouseButtonRelease
){
for(auto widget : widgetsAt(root, ((QMouseEvent*)ev)->globalPos())){
if(parentCount((QQuickItem*)widget)){
O_DEBUG("postWidget: " << widget);
}
}
O_DEBUG(obj);
O_DEBUG(ev);
}
#endif
if(
type == QEvent::MouseMove
|| type == QEvent::MouseButtonPress
|| type == QEvent::MouseButtonRelease
){
O_DEBUG(obj);
O_DEBUG(ev);
}
return filtered;
#endif
return false;
}
}

Expand Down
6 changes: 0 additions & 6 deletions shared/liboxide/eventfilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ namespace Oxide{
{
Q_OBJECT
public:
/*!
* \brief The root element in the Qt application
*
* This is needed to find wigets to send mouse events when a pen touch is detected
*/
QQuickItem* root;
/*!
* \brief Create a new EventFilter instance
* \param parent The parent object. Usually should be qApp
Expand Down
7 changes: 2 additions & 5 deletions shared/liboxide/examples/oxide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ try{
#include <QtPlugin>

#import <liboxide>
#include <liboxide/eventfilter.h>

#ifdef __arm__
Q_IMPORT_PLUGIN(QsgEpaperPlugin)
Expand All @@ -49,10 +50,6 @@ Q_IMPORT_PLUGIN(QsgEpaperPlugin)
using namespace Oxide;
int main(int argc, char *argv[]){
QGuiApplication app(argc, argv);

auto filter = new EventFilter(&app);
app.installEventFilter(filter);

QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
context->setContextProperty("screenGeometry", app.primaryScreen()->geometry());
Expand All @@ -63,7 +60,7 @@ int main(int argc, char *argv[]){
}

auto root = engine.rootObjects().first();
filter->root = (QQuickItem*)root;
root->installEventFilter(new EventFilter(&app));
return app.exec();
}
//! [EventFilter]
Expand Down
1 change: 1 addition & 0 deletions shared/liboxide/liboxide.pro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
QT -= gui
QT += quick
QT += dbus
QT += gui-private

TEMPLATE = lib
DEFINES += LIBOXIDE_LIBRARY
Expand Down

0 comments on commit 8ed7acc

Please sign in to comment.