diff --git a/README.md b/README.md
index c4cfe5d..0d795ec 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,16 @@ Comfortable, seamless, and fast 3-finger (and 4-finger) touchpad swipe gestures
## Installation
-1. Install git, libinput, and g++
+1. Install git and g++
```bash
- sudo apt-get install git libinput-tools libxdo-dev g++
+ sudo apt install git g++
+ ```
+
+1. Install libinput-tools and C libraries
+
+ ```bash
+ sudo apt install libinput-tools libconfig-dev libxdo-dev
```
2. Clone this repository
diff --git a/comfortable-swipe b/comfortable-swipe
index d42c72c..42267f2 100755
--- a/comfortable-swipe
+++ b/comfortable-swipe
@@ -180,7 +180,7 @@ case $i in
exit 0
;;
-v | --version) # eagerly print version
- echo "$version"
+ echo "comfortable-swipe $version"
exit 0
;;
*) # unknown option
diff --git a/comfortable-swipe-buffer.cpp b/comfortable-swipe-buffer.cpp
new file mode 100644
index 0000000..57edac0
--- /dev/null
+++ b/comfortable-swipe-buffer.cpp
@@ -0,0 +1,89 @@
+#ifndef __comfortable_swipe_buffer__
+#define __comfortable_swipe_buffer__
+
+/*
+Comfortable Swipe (as of v1.2.0)
+by Rico Tiongson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#include // fgets_unlocked, stdin
+#include // ios, cout, cin
+#include // cfg_t
+
+#include "comfortable-swipe-config.cpp"
+#include "comfortable-swipe-defines.cpp"
+#include "comfortable-swipe-gesture-mousehold.cpp"
+#include "comfortable-swipe-gesture-swipe.cpp"
+
+/**
+ * The main driver program.
+ */
+int main() {
+ using namespace std;
+ using namespace comfortable_swipe;
+
+ // unsync with for faster IO
+ ios::sync_with_stdio(false);
+ cin.tie(0);
+ cout.tie(0);
+ cout.flush();
+
+ // prepare config file
+
+ cfg_ auto config =
+ comfortable_swipe::read_config_file(COMFORTABLE_SWIPE_CONFIG);
+
+ // initialize mouse hold gesture handler
+ // for now, this supports 3-finger and 4-finger hold
+ // Examples:
+ // hold3=move move mouse on 3 fingers
+ // hold3=button1 hold button 1 on 3 fingers
+ // hold4=button3 hold button 3 (right click) on 3 fingers
+ // hold3=ignore
+ gesture_mousehold mouse_hold(config_get_string("hold3"), config_get_string("hold4"));
+
+ // initialize keyboard swipe gesture handler
+ gesture_swipe = keyboard_swipe(
+ config_get_float("threshold"),
+ config_get_string("left3"),
+ config_get_string("left4"),
+ config_get_string("right3"),
+ config_get_string("right4"),
+ config_get_string("up3"),
+ config_get_string("up4"),
+ config_get_string("down3"),
+ config_get_string("down4"),
+ );
+
+ // prepare data containers
+ array line;
+
+ // start reading lines from input one by one
+ while (fgets_unlocked(line.data(), line.size(), stdin) != NULL) {
+ // prioritize mouse hold gesture first
+ mouse_hold.parse_line(line.data());
+
+ // if mouse hold fails, try keyboard hold
+ if (!mouse_hold.is_mousedown()) {
+ // attempt to parse keyboard gestures
+ keyboard_swipe.parse_line(line.data());
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/comfortable-swipe-config.cpp b/comfortable-swipe-config.cpp
new file mode 100644
index 0000000..d7caf29
--- /dev/null
+++ b/comfortable-swipe-config.cpp
@@ -0,0 +1,84 @@
+#ifndef __comfortable_swipe_config__
+#define __comfortable_swipe_config__
+
+/*
+Comfortable Swipe (as of v1.2.0)
+by Rico Tiongson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#include // std::array
+#include // std::cout
+#include // std::unique_ptr
+extern "C" {
+#include // cfg_t
+}
+#include "comfortable-swipe-defines.cpp"
+
+namespace comfortable_swipe {
+// prepare config file
+// Examples: cfg_getstr(get_config(), "left3")
+// cfg_getfloat(get_config(), "threshold")
+cfg_t *get_config() {
+ using namespace std;
+
+ // use std::unique_ptr for auto garbage collection
+ static std::unique_ptr config;
+
+ // try to return existing config
+ if (config != nullptr)
+ return config.get();
+
+ // list down possible options here
+ // second argument is the default value
+ // make sure to end with CFG_END()
+ array cfg_options = {
+ CFG_STR("left3", "", CFGF_NONE),
+ CFG_STR("left4", "", CFGF_NONE),
+ CFG_STR("right3", "", CFGF_NONE),
+ CFG_STR("right4", "", CFGF_NONE),
+ CFG_STR("up3", "", CFGF_NONE),
+ CFG_STR("up4", "", CFGF_NONE),
+ CFG_STR("down3", "", CFGF_NONE),
+ CFG_STR("down4", "", CFGF_NONE),
+ CFG_FLOAT("threshold", 0.0, CFGF_NONE),
+ CFG_STR("hold3", "", CFGF_NONE),
+ CFG_STR("hold4", "", CFGF_NONE),
+ // make sure to end here
+ CFG_END()
+ );
+
+ // initialize
+ config = std::auto_ptr(cfg_init(cfg_options.data(), CFGF_NONE)):
+
+ if (cfg_parse(config.get(), COMFORTABLE_SWIPE_CONFIG) == CFG_PARSE_ERROR) {
+ throw runtime_error(
+ "cannot parse config file at: " COMFORTABLE_SWIPE_CONFIG);
+ }
+
+ return config.get();
+}
+
+// utility methods
+inline const char *get_config_string(const char *key) {
+ return cfg_getstr(get_config(), key);
+}
+
+inline double get_config_float(const char *key) {
+ return cfg_getfloat(get_config(), key);
+}
+} // namespace comfortable_swipe
+
+#endif /* __comfortable_swipe_config__ */
diff --git a/comfortable-swipe-defines.cpp b/comfortable-swipe-defines.cpp
new file mode 100644
index 0000000..43d2c7f
--- /dev/null
+++ b/comfortable-swipe-defines.cpp
@@ -0,0 +1,38 @@
+#ifndef __comfortable_swipe_defines__
+#define __comfortable_swipe_defines__
+// Place #define statements here
+
+/*
+Comfortable Swipe (as of v1.2.0)
+by Rico Tiongson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#ifndef COMFORTABLE_SWIPE_CONFIG
+#warning Please define COMFORTABLE_SWIPE_CONFIG during compilation!\
+ (g++ -DCOMFORTABLE_SWIPE_CONFIG="\"/home/$USER/.config/comfortable-swipe.conf\"")
+#endif /* COMFORTABLE_SWIPE_CONFIG */
+
+#ifndef COMFORTABLE_SWIPE_AUTOSTART
+#warning Please define COMFORTABLE_SWIPE_AUTOSTART during compilation!\
+ (g++ -DCOMFORTABLE_SWIPE_AUTOSTART="\"/home/$USER/.config/autostart/comfortable-swipe.desktop\"")
+#endif /* COMFORTABLE_SWIPE_AUTOSTART */
+
+#ifndef COMFORTABLE_SWIPE_VERSION
+#warning COMFORTABLE_SWIPE_VERSION is not defined
+#define COMFORTABLE_SWIPE_VERSION "v(UNKNOWN)"
+#endif /* COMFORTABLE_SWIPE_VERSION */
+
+#endif /* __comfortable_swipe_defines__ */
diff --git a/comfortable-swipe-gesture-mousehold.cpp b/comfortable-swipe-gesture-mousehold.cpp
new file mode 100644
index 0000000..5a3d865
--- /dev/null
+++ b/comfortable-swipe-gesture-mousehold.cpp
@@ -0,0 +1,218 @@
+#ifndef __comfortable_swipe_gesture_mousehold__
+#define __comfortable_swipe_gesture_mousehold__
+
+/*
+Comfortable Swipe
+by Rico Tiongson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#include // std::sscanf
+#include // strncmp
+#include // std::cout, std::endl
+
+extern "C" {
+#include // xdo, xdo_new, xdo_free,
+ // xdo_get_mouse_location
+ // CURRENT_WINDOW
+}
+
+#include "comfortable-swipe-gesture-swipe.cpp"
+
+namespace comfortable_swipe {
+
+// enumerations for mouse hold gesture types
+enum {
+ MOUSE_NONE = -1,
+ MOUSE_MOVE = 0,
+ MOUSE_LEFT_CLICK = 1,
+ MOUSE_MIDDLE_CLICK = 2,
+ MOUSE_RIGHT_CLICK = 3,
+ MOUSE_WHEEL_UP = 4,
+ MOUSE_WHEEL_DOWN = 5,
+ MOUSE_SCROLL = 6,
+ MOUSE_SCROLL_REVERSE = 7
+};
+
+class gesture_mousehold : public gesture_swipe {
+public:
+ // constructor
+ gesture_mousehold(const char *hold3, // 3 finger mouse down
+ const char *hold4 // 4 finger mouse down
+ );
+
+ // the button being clicked
+ int button;
+
+ virtual ~gesture_mousehold();
+
+ // override begin and end for mousedown
+ virtual void begin() override;
+ virtual void update() override;
+ virtual void end() override;
+
+ // provide our own mouse functions
+ virtual void do_mousedown(const char *);
+ virtual void do_mouseup(const char *);
+ virtual bool is_mousedown() const;
+
+ // utility method to parse mouse input given config characters
+ static int parse_mouse_button(const char *);
+
+protected:
+ // command holders
+ const char *hold3;
+ const char *hold4;
+
+ // flag we can use to check if mouse is down
+ bool flag_mousedown;
+};
+} // namespace comfortable_swipe
+
+/**
+ * Constructs a new mouse gesture, given "hold3" and "hold4" configurations.
+ */
+gesture_mousehold::gesture_mousehold(const char *hold3, const char *hold4)
+ : gesture_swipe(), button(MOUSE_NONE), hold3(hold3), hold4(hold4),
+ flag_mousedown(false) {}
+
+/**
+ * Destructs this mouse swipe gesture.
+ */
+gesture_mousehold::~gesture_mousehold() {}
+
+/**
+ * Run mousedown command on hold input.
+ */
+void gesture_mousehold::do_mousedown(const char *mouseinput) {
+ const int button = this->button = this->parse_mouse_button(mouseinput);
+ if (button != MOUSE_NONE) {
+ // eg. MOUSE DOWN hold3 mouse1
+ std::printf("MOUSE DOWN hold%d %s\n", this->fingers, mouseinput);
+ if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
+ // send mouse down on associated button
+ xdo_mouse_down(this->xdo, CURRENTWINDOW, button);
+ }
+ this->flag_mousedown = true;
+ }
+}
+
+/**
+ * Run mouseup command on hold output.
+ */
+void gesture_mousehold::do_mouseup(const char *mouseinput) {
+ const int button = this->button = this->parse_mouse_button(mouseinput);
+ if (button != MOUSE_NONE) {
+ std::printf("MOUSE UP hold%d %s\n", this->fingers, mouseinput);
+ if (MOUSE_LEFT_CLICK <= button && button <= MOUSE_RIGHT_CLICK) {
+ // send mouse up on associated button
+ xdo_mouse_up(this->xdo, CURRENTWINDOW, button);
+ }
+ this->flag_mousedown = false;
+ }
+}
+
+/**
+ * Utility method to parse mouse number from input.
+ * Returns -1 on failure.
+ */
+int gesture_mousehold::parse_mouse_button(const char *input) {
+ // just move without holding button down
+ if (std::strcmp(input, "move") == 0)
+ return MOUSE_MOVE;
+
+ if (std::strcmp(input, "scroll") == 0)
+ return MOUSE_SCROLL;
+
+ if (std::strcmp(input, "scroll_reverse") == 0)
+ return MOUSE_SCROLL_REVERSE;
+
+ // get button number
+ int button;
+ if (std::sscanf(input, "button%d", &button) == 1) {
+ if (1 <= button && button <= 6) {
+ return button;
+ }
+ }
+
+ return MOUSE_NONE;
+}
+
+/**
+ * Hook on begin of mouse swipe gesture.
+ */
+void gesture_mousehold::begin() {
+ // call superclass method
+ gesture_swipe::begin();
+ // dispatch mouse down event
+ if (this->fingers == 3) {
+ this->do_mousedown(this->hold3);
+ } else if (this->fingers == 4) {
+ this->do_mousedown(this->hold4);
+ }
+}
+
+/**
+ * Hook on end of mouse swipe gesture.
+ */
+void gesture_mousehold::update() {
+ // call superclass method
+ gesture_swipe::update();
+ if (this->is_mousedown()) {
+ if (0 <= this->button && this->button <= 3) {
+ // drag mouse with pointer during update
+ xdo_move_mouse_relative(this->xdo, this->udx, this->udy);
+ } else if (this->button == MOUSE_SCROLL ||
+ this->button == MOUSE_SCROLL_REVERSE) {
+ // perform naive scroll depending on vertical direction
+ int wheel = MOUSE_WHEEL_DOWN;
+ if ((this->udy > 0) == (this->button == MOUSE_SCROLL))
+ wheel = MOUSE_WHEEL_UP;
+
+ // click wheel on update (note: this is not precise)
+ xdo_mouse_down(this->xdo, CURRENTWINDOW, wheel);
+ xdo_mouse_up(this->xdo, CURRENTWINDOW, wheel);
+ } else if (this->button == MOUSE_WHEEL_UP ||
+ this->button == MOUSE_WHEEL_DOWN) {
+ // click wheel button on 4 or 5
+ xdo_mouse_down(this->xdo, CURRENTWINDOW, this->button);
+ xdo_mouse_up(this->xdo, CURRENTWINDOW, this->button);
+ }
+ }
+}
+
+/**
+ * Hook on end of swipe gesture.
+ */
+void gesture_mousehold::end() {
+ if (this->is_mousedown()) {
+ if (this->fingers == 3) {
+ this->do_mouseup(this->hold3);
+ } else if (this->fingers == 4) {
+ this->do_mouseup(this->hold4);
+ }
+ }
+
+ // call superclass method
+ gesture_swipe::end();
+}
+
+/**
+ * Utility method to check if mouse is current held.
+ */
+bool gesture_mousehold::is_mousedown() const { return this->flag_mousedown; }
+}
+
+#endif /* __comfortable_swipe_gesture_mousehold__ */
diff --git a/comfortable-swipe-gesture-swipe.cpp b/comfortable-swipe-gesture-swipe.cpp
new file mode 100644
index 0000000..22d8c88
--- /dev/null
+++ b/comfortable-swipe-gesture-swipe.cpp
@@ -0,0 +1,156 @@
+#ifndef __comfortable_swipe_gesture_swipe__
+#define __comfortable_swipe_gesture_swipe__
+
+/*
+Comfortable Swipe
+by Rico Tiongson
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+
+#include // std::cout, std::endl
+#include // std::regex, std::regex_match, std::cmatch
+#include // std::stoi, std::stof
+
+namespace comfortable_swipe {
+class gesture_swipe {
+public:
+ // constructor
+ gesture_swipe();
+
+ // destructor
+ virtual ~gesture_swipe();
+
+ // fields for xdo
+ int fingers;
+
+ // normal values (for touchpad mapping)
+ float x, y, dx, dy;
+
+ // unaccelerated values (for screen mapping)
+ float ux, uy, udx, udy;
+
+ // hooks that we can override (mark as virtual)
+ virtual void begin();
+ virtual void update();
+ virtual void end();
+ virtual bool parse_line(const char *);
+
+protected:
+ // xdo container
+ xdo_t *xdo;
+
+ // location of mouse
+ int screen_num, ix, iy;
+
+ // optimization flag for checking if GESTURE_SWIPE_BEGIN was dispatched
+ bool flag_swiping;
+
+public:
+ // regex patterns
+ static const std::regex *GESTURE_BEGIN_REGEX;
+ static const std::regex *GESTURE_UPDATE_REGEX;
+ static const std::regex *GESTURE_END_REGEX;
+};
+
+/**
+ * Constructs a new fresh swipe gesture container.
+ */
+gesture_swipe::gesture_swipe() : xdo(xdo_new(NULL)), flag_swiping(false) {
+ // improve responsiveness of first gesture by pre-empting xdotool
+ xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
+}
+
+/**
+ * Destructs this swipe gesture.
+ */
+gesture_swipe::~gesture_swipe() { xdo_free(this->xdo); }
+
+/**
+ * Hook on begin of swipe gesture (you can override this).
+ */
+void gesture_swipe::begin() {
+ // save current screen location for gestured mouse movement
+ xdo_get_mouse_location(this->xdo, &this->ix, &this->iy, &this->screen_num);
+ this->x = 0;
+ this->y = 0;
+ this->ux = 0;
+ this->uy = 0;
+}
+
+/**
+ * Hook on update of swipe gesture (you can override this).
+ */
+void gesture_swipe::update() {
+ this->x += this->dx;
+ this->y += this->dy;
+ this->ux += this->udx;
+ this->uy += this->udy;
+}
+
+/**
+ * Hook on end of swipe gesture (you can override this).
+ */
+void gesture_swipe::end() {}
+
+/**
+ * Dispatches begin/update/end depending on the regex pattern provided by this
+ * class.
+ *
+ * @param line the line from libinput debug-events to parse
+ * @return true if begin/update/end was dispatched
+ */
+bool gesture_swipe::parse_line(const char *line) {
+
+ // prepare holder for regex matches
+ static std::cmatch matches;
+
+ if (this->flag_swiping) {
+ // currently swiping
+ if (std::regex_match(line, matches, GESTURE_UPDATE_REGEX) != 0) {
+ // assign necessary variables for swipe update
+ this->fingers = std::stoi(matches[1]);
+ this->dx = std::stof(matches[2]);
+ this->dy = std::stof(matches[3]);
+ this->udx = std::stof(matches[4]);
+ this->udy = std::stof(matches[5]);
+ // dispatch update
+ this->update();
+ return true;
+ } else if (std::regex_match(line, matches, GESTURE_END_REGEX) != 0) {
+ // assign necessary variables for swipe end
+ this->flag_swiping = false;
+ this->fingers = std::stoi(matches[1]);
+ // dispatch end
+ this->end();
+ return true;
+ }
+ } else {
+ // not swiping, check if swipe will begin
+ if (std::regex_match(line, matches, GESTURE_BEGIN_REGEX) != 0 ||
+ std::regex_match(line, matches, GESTURE_UPDATE_REGEX) != 0) {
+ // assign necessary variables for swipe begin
+ this->flag_swiping = true;
+ this->fingers = std::stoi(matches[1]);
+ // dispatch begin
+ this->begin();
+ return true;
+ }
+ }
+
+ return false;
+}
+} // namespace comfortable_swipe
+
+#endif /* __comfortable_swipe_gesture_swipe__ */
diff --git a/comfortable-swipe.desktop b/comfortable-swipe.desktop
new file mode 100644
index 0000000..3b1da8f
--- /dev/null
+++ b/comfortable-swipe.desktop
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Type=Application
+Name=Comfortable Swipe
+Comment=Comfortable 3/4-finger touchpad gestures
+Exec=comfortable-swipe start
+Hidden=false
+NoDisplay=false
+X-GNOME-Autostart-enabled=true
diff --git a/command_line.cpp b/command_line.cpp
deleted file mode 100644
index 39e20f3..0000000
--- a/command_line.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-Comfortable Swipe
-by Rico Tiongson
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-#include "comfortable_swipe/lib"
-#include // std::ios
-#include // std::cin, std::cout, std::cerr
-#include // std::string
-
-/* Command-line function. */
-
-int main(int argc, char **args) {
- // improve buffering by decoupling loggers from stdio
- std::ios::sync_with_stdio(false);
- std::cin.tie(0);
- std::cout.tie(0);
- std::cerr.tie(0);
-
- if (argc > 1) {
- std::string arg = args[1];
-
- // select based on argument
- if (arg == "start")
- comfortable_swipe::service::start();
-
- else if (arg == "stop")
- comfortable_swipe::service::stop();
-
- else if (arg == "restart")
- comfortable_swipe::service::restart();
-
- else if (arg == "buffer")
- comfortable_swipe::service::buffer();
-
- else if (arg == "autostart")
- comfortable_swipe::service::autostart();
-
- else if (arg == "config")
- comfortable_swipe::service::config();
-
- else if (arg == "debug")
- comfortable_swipe::service::debug();
-
- else if (arg == "status")
- comfortable_swipe::service::status();
-
- else /* if (arg == "help") */
- comfortable_swipe::service::help();
- } else
- comfortable_swipe::service::help();
-
- return 0;
-}
diff --git a/cpp.compile.sh b/compile.sh
similarity index 57%
rename from cpp.compile.sh
rename to compile.sh
index 6dcd0ac..86b9b76 100755
--- a/cpp.compile.sh
+++ b/compile.sh
@@ -2,8 +2,12 @@
dir="$(dirname $0)"
version="$(cat "$dir/VERSION" | tr -d '[:space:]')"
+libraries=-lxdo -lconfig++
exec g++ $@ \
- -std=c++11 \
- -O2 -lxdo -Wno-unused-result \
+ -std=c++14 \
+ -O2 \
+ -lxdo \
+ -lconfig++ \
+ -Wno-unused-result \
-DCOMFORTABLE_SWIPE_VERSION="\"$version\""