Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Config::getGestureConfig(const std::string &application,
void Config::loadDefaultGlobalSettings() {
this->globalSettings["animation_delay"] = "150";
this->globalSettings["action_execute_threshold"] = "20";
this->globalSettings["reposition_cursor"] = "NEVER";
}

std::string Config::getConfigKey(const std::string &application,
Expand Down
22 changes: 13 additions & 9 deletions src/config/xml-config-loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,35 +59,39 @@ std::filesystem::path XmlConfigLoader::getConfigFilePath() {

if (!std::filesystem::exists(usrConfigFile)) {
throw std::runtime_error{
"File /usr/share/touchegg/touchegg.conf not found.\n"
"Reinstall Touchégg to solve this issue"};
"File \"/usr/share/touchegg/touchegg.conf\" not found.\n"
"\tReinstall Touchégg to solve this issue."};
}

return std::filesystem::exists(homeConfigFile) ? homeConfigFile
: usrConfigFile;
}

void XmlConfigLoader::parseConfig() {
void XmlConfigLoader::parseConfig(bool isReload) {
std::filesystem::path configPath = XmlConfigLoader::getConfigFilePath();
tlg::info << "Using configuration file " << configPath << std::endl;
tlg::info << "\tUsing configuration file: " << configPath << std::endl;

pugi::xml_document doc;
pugi::xml_parse_result parsedSuccessfully = doc.load_file(configPath.c_str());

if (!parsedSuccessfully) {
throw std::runtime_error{"Error parsing configuration file"};
throw std::runtime_error{"Error parsing configuration file."};
}

pugi::xml_node rootNode = doc.document_element();
this->parseGlobalSettings(rootNode);
this->parseGlobalSettings(rootNode, isReload);
this->parseApplicationXmlNodes(rootNode);
}

void XmlConfigLoader::parseGlobalSettings(const pugi::xml_node &rootNode) {
void XmlConfigLoader::parseGlobalSettings(const pugi::xml_node &rootNode, bool isReload) {
pugi::xml_node settingsNode = rootNode.child("settings");
for (pugi::xml_node propertyNode : settingsNode.children("property")) {
const std::string property = propertyNode.attribute("name").value();
const std::string value = propertyNode.child_value();
if (isReload && property == "reposition_cursor") {
tlg::info << "\tNote: Changing \"reposition_cursor\" currently requires"
" restarting the client service.\n" << std::endl;
}
this->config->saveGlobalSetting(property, value);
}
}
Expand Down Expand Up @@ -168,10 +172,10 @@ void XmlConfigLoader::watchConfig() {
}

if (reloadSettings) {
tlg::info << "Your configuration file changed, reloading your settings"
tlg::info << "Your configuration file changed. Reloading your settings..."
<< std::endl;
this->config->clear();
this->parseConfig();
this->parseConfig(true);
}
}
}};
Expand Down
4 changes: 2 additions & 2 deletions src/config/xml-config-loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ class XmlConfigLoader {
/**
* Parse the XML configuration file placed in path.
*/
void parseConfig();
void parseConfig(bool isReload = false);

/**
* Parse the global settings.
* @param rootNode XML root node, usually named "touchégg".
*/
void parseGlobalSettings(const pugi::xml_node &rootNode);
void parseGlobalSettings(const pugi::xml_node &rootNode, bool isReload);

/**
* Parse the "application" nodes in the XML.
Expand Down
18 changes: 13 additions & 5 deletions src/daemon/daemon-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,19 @@ std::unique_ptr<Gesture> DaemonClient::makeGestureFromSignalParams(
int fingers = -1;
DeviceType deviceType = DeviceType::UNKNOWN;
uint64_t elapsedTime = -1;

g_variant_get(signalParameters, // NOLINT
"(uudiut)", &type, &direction, &percentage, &fingers,
&deviceType, &elapsedTime);
XYPosition cursorPosition = {-1, -1};

if (g_variant_check_format_string(signalParameters, "(uudiut)", false)) {
g_variant_get(signalParameters, // NOLINT
"(uudiut)", &type, &direction, &percentage, &fingers,
&deviceType, &elapsedTime);
} else {
g_variant_get(
signalParameters, // NOLINT
"(uudiut(dd))", &type, &direction, &percentage, &fingers,
&deviceType, &elapsedTime, &(cursorPosition.x), &(cursorPosition.y));
}

return std::make_unique<Gesture>(type, direction, percentage, fingers,
deviceType, elapsedTime);
deviceType, elapsedTime, cursorPosition);
}
33 changes: 25 additions & 8 deletions src/daemon/daemon-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,31 @@ void DaemonServer::send(const std::string &signalName,
std::vector<GDBusConnection *> closedConnections{};

// Copy every gesture field into the signal parameters for serialization
GVariant *signalParams =
g_variant_new("(uudiut)", // NOLINT
static_cast<int>(gesture->type()), // u
static_cast<int>(gesture->direction()), // u
gesture->percentage(), // d
gesture->fingers(), // i
static_cast<int>(gesture->performedOnDeviceType()), // u
gesture->elapsedTime()); // t
GVariant *signalParams;
if (
signalName == DBUS_ON_GESTURE_UPDATE
|| signalName == DBUS_ON_GESTURE_END
) {
signalParams = {
g_variant_new(
"(uudiut(dd))", // NOLINT
static_cast<int>(gesture->type()), // u
static_cast<int>(gesture->direction()), // u
gesture->percentage(), // d
gesture->fingers(), // i
static_cast<int>(gesture->performedOnDeviceType()), // u
gesture->elapsedTime(), // t
gesture->cursorPosition())}; // dd
} else {
signalParams = {g_variant_new(
"(uudiut)", // NOLINT
static_cast<int>(gesture->type()), // u
static_cast<int>(gesture->direction()), // u
gesture->percentage(), // d
gesture->fingers(), // i
static_cast<int>(gesture->performedOnDeviceType()), // u
gesture->elapsedTime())}; // t
}
g_variant_ref_sink(signalParams);

// Send the message to every client
Expand Down
2 changes: 2 additions & 0 deletions src/daemon/dbus.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ constexpr auto DBUS_INTROSPECTION_XML =
" <arg name='fingers' type='i' />"
" <arg name='performed_on_device_type' type='u' />"
" <arg name='elapsed_time' type='t' />"
" <arg name='cursor_end_position' type='(dd)' />"
" </signal>"
" <signal name='OnGestureEnd'>"
" <arg name='gesture_type' type='u' />"
Expand All @@ -58,6 +59,7 @@ constexpr auto DBUS_INTROSPECTION_XML =
" <arg name='fingers' type='i' />"
" <arg name='performed_on_device_type' type='u' />"
" <arg name='elapsed_time' type='t' />"
" <arg name='cursor_end_position' type='(dd)' />"
" </signal>"
" </interface>"
"</node>";
Expand Down
29 changes: 28 additions & 1 deletion src/gesture-controller/gesture-controller.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@

GestureController::GestureController(const Config &config,
const WindowSystem &windowSystem)
: config(config), windowSystem(windowSystem) {}
: config(config), windowSystem(windowSystem),
repositionCursor(repositionCursorOptFromStr(config.getGlobalSetting("reposition_cursor"))) {}

void GestureController::onGestureBegin(std::unique_ptr<Gesture> gesture) {
tlg::debug << "Gesture begin detected" << std::endl;
Expand Down Expand Up @@ -76,6 +77,18 @@ void GestureController::onGestureBegin(std::unique_ptr<Gesture> gesture) {
}

void GestureController::onGestureUpdate(std::unique_ptr<Gesture> gesture) {
// Move cursor to gesture update position, if setting is enabled.
XYPosition curPos = gesture->cursorPosition();
if (
(repositionCursor & RepositionCursorOpt::GESTURE_UPDATE)
&& gestureTypeSupportsCursorReposition(gesture->type())
) {
tlg::debug << "cursorPosition (GestureUpdate): {"
<< curPos.x << ", " << curPos.y
<< "}" << std::endl;
this->windowSystem.positionCursor(curPos.x, curPos.y);
}

if (this->executeAction) {
tlg::debug << "Gesture update detected (" << gesture->percentage() << "%)"
<< std::endl;
Expand All @@ -85,6 +98,20 @@ void GestureController::onGestureUpdate(std::unique_ptr<Gesture> gesture) {
}

void GestureController::onGestureEnd(std::unique_ptr<Gesture> gesture) {
// Move cursor to position where gesture ended, if setting is enabled.
XYPosition curPos = gesture->cursorPosition();
if (
(repositionCursor & RepositionCursorOpt::GESTURE_END)
&& gestureTypeSupportsCursorReposition(gesture->type())
) {
tlg::debug << "cursorPosition (GestureEnd): {"
<< curPos.x << ", " << curPos.y
<< "}" << std::endl;
this->windowSystem.positionCursor(curPos.x, curPos.y,
// Extra verbose debugging if set to *only* GESTURE_END.
(repositionCursor == RepositionCursorOpt::GESTURE_END));
}

if (this->executeAction) {
tlg::debug << "Gesture end detected" << std::endl;
gesture->setDirection(this->rotatedDirection);
Expand Down
4 changes: 4 additions & 0 deletions src/gesture-controller/gesture-controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "actions/action.h"
#include "gesture-controller/gesture-controller-delegate.h"
#include "utils/reposition-cursor.h"
class Config;
class Gesture;
class WindowSystem;
Expand All @@ -44,6 +45,9 @@ class GestureController : public GestureControllerDelegate {
const Config &config;
const WindowSystem &windowSystem;

// Setting values cached for efficient access:
RepositionCursorOpt repositionCursor; // Bitmask.

/**
* The action to perform.
*/
Expand Down
Empty file modified src/gesture-gatherer/libinput-gesture-gatherer.h
100755 → 100644
Empty file.
6 changes: 4 additions & 2 deletions src/gesture-gatherer/libinput-touch-handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ void LibinputTouchHandler::handleTouchUp(struct libinput_event *event) {

auto gesture = std::make_unique<Gesture>(
this->state.type, this->state.direction, percentage,
this->state.startFingers, DeviceType::TOUCHSCREEN, elapsedTime);
this->state.startFingers, DeviceType::TOUCHSCREEN, elapsedTime,
XYPosition{this->state.currentX[slot], this->state.currentY[slot]});
this->gestureController->onGestureEnd(std::move(gesture));

this->state.reset();
Expand Down Expand Up @@ -152,7 +153,8 @@ void LibinputTouchHandler::handleTouchMotion(struct libinput_event *event) {

auto gesture = std::make_unique<Gesture>(
this->state.type, this->state.direction, percentage,
this->state.startFingers, DeviceType::TOUCHSCREEN, elapsedTime);
this->state.startFingers, DeviceType::TOUCHSCREEN, elapsedTime,
XYPosition{this->state.currentX[slot], this->state.currentY[slot]});
this->gestureController->onGestureUpdate(std::move(gesture));
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/gesture/gesture.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
#include "gesture/gesture-direction.h"
#include "gesture/gesture-type.h"

/**
* Intended to store absolute position on display in millimeters.
* Useful to export position from Libinput, which seems unaware of pixels.
*/
struct XYPosition {
double x;
double y;
};

/**
* Gestures implementations change depending on the driver/backend. This is the
* basic interface of a gesture.
Expand All @@ -38,6 +47,16 @@ class Gesture {
gestureFingers(fingers),
deviceType(performedOnDeviceType),
gestureElapsedTime(elapsedTime) {}
Gesture(GestureType type, GestureDirection direction, double percentage,
int fingers, DeviceType performedOnDeviceType, uint64_t elapsedTime,
XYPosition cursorEndPosition)
: gestureType(type),
gestureDirection(direction),
gesturePercentage(percentage),
gestureFingers(fingers),
deviceType(performedOnDeviceType),
gestureElapsedTime(elapsedTime),
gestureEndPosition(cursorEndPosition) {}

/**
* @returns The gesture type.
Expand Down Expand Up @@ -73,6 +92,12 @@ class Gesture {
*/
uint64_t elapsedTime() const { return this->gestureElapsedTime; }

/**
* Position to set cursor when gesture ends..
* @returns A struct containing X and Y position integers.
*/
XYPosition cursorPosition() const { return this->gestureEndPosition; }

/**
* Set the gesture direction.
* @see GestureDirection
Expand All @@ -88,6 +113,7 @@ class Gesture {
int gestureFingers = -1;
DeviceType deviceType = DeviceType::UNKNOWN;
uint64_t gestureElapsedTime = -1;
XYPosition gestureEndPosition{-1, -1};
};

#endif // GESTURE_GESTURE_H_
55 changes: 55 additions & 0 deletions src/utils/reposition-cursor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#ifndef UTILS_REPOSITION_CURSOR_H_
#define UTILS_REPOSITION_CURSOR_H_

#include <string>
#include "gesture/gesture-type.h"

// Bitmask representing options for when cursor should be repositioned.
enum RepositionCursorOpt {
NEVER = 0b00, // 0
GESTURE_END = 0b01, // 1
GESTURE_UPDATE = 0b10, // 2
GESTURE_UPDATE_AND_END = 0b11 // 3
};

inline bool gestureTypeSupportsCursorReposition(GestureType gestureType) {
switch (gestureType) {
case GestureType::SWIPE:
case GestureType::TAP:
return true;
default:
return false;
}
};

inline std::string repositionCursorOptToStr(RepositionCursorOpt repositionCursorOpt) {
switch (repositionCursorOpt) {
case RepositionCursorOpt::NEVER:
return "NEVER";
case RepositionCursorOpt::GESTURE_END:
return "GESTURE_END";
case RepositionCursorOpt::GESTURE_UPDATE:
return "GESTURE_UPDATE";
case RepositionCursorOpt::GESTURE_UPDATE_AND_END:
return "GESTURE_UPDATE_AND_END";
default:
return "NEVER";
}
}

inline RepositionCursorOpt repositionCursorOptFromStr(const std::string &str) {
constexpr auto prefixLength = sizeof("GESTURE_")-1; // -1 for terminating null.
if (!str.compare(prefixLength, std::string::npos, "END")) {
return RepositionCursorOpt::GESTURE_END;
}
if (!str.compare(prefixLength, std::string::npos, "UPDATE")) {
return RepositionCursorOpt::GESTURE_UPDATE;
}
if (!str.compare(prefixLength, std::string::npos, "UPDATE_AND_END")) {
return RepositionCursorOpt::GESTURE_UPDATE_AND_END;
}
// Consider warning user if (str != "NEVER") ...
return RepositionCursorOpt::NEVER;
}

#endif // UTILS_REPOSITION_CURSOR_H_
7 changes: 7 additions & 0 deletions src/window-system/window-system.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,13 @@ class WindowSystem {
*/
virtual void sendMouseUp(int button) const = 0;

/**
* Directly positions cursor.
* Only one movement event should be triggered.
* No button click events should be sent.
*/
virtual void positionCursor(double x, double y, bool verboseDebug = false) const = 0;

/**
* @returns The size of the desktop workarea, ie, the area of the desktop not
* used by system elements like docks, panels, etc.
Expand Down
Loading
Loading