From 6905475c9522044d19825fb25a1587fb81dfad9c Mon Sep 17 00:00:00 2001 From: Thomas Jaeger Date: Fri, 7 Sep 2012 03:24:26 -0400 Subject: [PATCH] Port to gtk3 --- Makefile | 11 +- actions.cc | 32 ++-- composite.cc | 22 +-- composite.h | 2 +- dbus-server.cc | 90 ---------- dbus.xml | 13 -- easystroke.desktop.in | 7 +- gesture.h | 2 +- gui.glade | 125 ++++++++++---- main.cc | 383 ++++++++++++++++++++---------------------- main.h | 1 + prefs.cc | 4 +- stats.cc | 17 +- win.cc | 8 +- win.h | 3 +- 15 files changed, 335 insertions(+), 385 deletions(-) delete mode 100644 dbus-server.cc delete mode 100644 dbus.xml diff --git a/Makefile b/Makefile index 40d0827a..950dc134 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,10 @@ DFLAGS = OFLAGS = -O2 AOFLAGS = -O3 STROKEFLAGS = -Wall -std=c99 $(DFLAGS) -CXXFLAGS = -Wall $(DFLAGS) -DLOCALEDIR=\"$(LOCALEDIR)\" `pkg-config gtkmm-2.4 dbus-glib-1 --cflags` +CXXFLAGS = -Wall $(DFLAGS) -DLOCALEDIR=\"$(LOCALEDIR)\" `pkg-config gtkmm-3.0 dbus-glib-1 --cflags` LDFLAGS = $(DFLAGS) -LIBS = $(DFLAGS) -lboost_serialization -lX11 -lXext -lXi -lXfixes -lXtst `pkg-config gtkmm-2.4 dbus-glib-1 --libs` +LIBS = $(DFLAGS) -lboost_serialization -lX11 -lXext -lXi -lXfixes -lXtst `pkg-config gtkmm-3.0 dbus-glib-1 --libs` BINARY = easystroke ICON = easystroke.svg @@ -39,7 +39,7 @@ POFILES = $(wildcard po/*.po) MOFILES = $(patsubst po/%.po,po/%/LC_MESSAGES/easystroke.mo,$(POFILES)) MODIRS = $(patsubst po/%.po,po/%,$(POFILES)) DEPFILES = $(wildcard *.Po) -GENFILES = gui.c desktop.c dbus-server.h po/POTFILES.in easystroke.desktop +GENFILES = gui.c desktop.c po/POTFILES.in easystroke.desktop GZFILES = $(wildcard *.gz) VERSION = $(shell test -e debian/changelog && grep '(.*)' debian/changelog | sed 's/.*(//' | sed 's/).*//' | head -n1 || (test -e version && cat version || git describe)) @@ -83,11 +83,6 @@ desktop.c: easystroke.desktop sed 's/Exec=easystroke/Exec=%s/' $< | sed 's/"/\\"/g' | sed 's/.*/&\\n\\/' >> $@ echo "\";" >> $@ -dbus-server.cc: dbus-server.h - -dbus-server.h: dbus.xml - dbus-binding-tool --prefix=server --mode=glib-server --output=$@ $< - po/POTFILES.in: $(CCFILES) $(HFILES) $(RM) $@ for f in `grep -El "\<_\(" $^`; do echo $$f >> $@; done diff --git a/actions.cc b/actions.cc index c8d8f8ae..bc4145b9 100644 --- a/actions.cc +++ b/actions.cc @@ -46,7 +46,7 @@ void TreeViewMulti::on_drag_begin(const Glib::RefPtr &context) pending = false; if (get_selection()->count_selected_rows() <= 1) return Gtk::TreeView::on_drag_begin(context); - Glib::RefPtr pb = render_icon(Gtk::Stock::DND_MULTIPLE, Gtk::ICON_SIZE_DND); + Glib::RefPtr pb = render_icon_pixbuf(Gtk::Stock::DND_MULTIPLE, Gtk::ICON_SIZE_DND); context->set_icon(pb, pb->get_width(), pb->get_height()); } @@ -67,15 +67,18 @@ class CellEditableAccel : public Gtk::EventBox, public Gtk::CellEditable { WIDGET(Gtk::Label, label, _("Key combination...")); label.set_alignment(0.0, 0.5); add(label); - modify_bg(Gtk::STATE_NORMAL, widget.get_style()->get_bg(Gtk::STATE_SELECTED)); - label.modify_fg(Gtk::STATE_NORMAL, widget.get_style()->get_fg(Gtk::STATE_SELECTED)); + override_background_color(widget.get_style_context()->get_background_color(Gtk::STATE_FLAG_SELECTED), Gtk::STATE_FLAG_NORMAL); + label.override_color(widget.get_style_context()->get_color(Gtk::STATE_FLAG_SELECTED), Gtk::STATE_FLAG_NORMAL); show_all(); } protected: virtual void start_editing_vfunc(GdkEvent *event) { add_modal_grab(); - get_window()->keyboard_grab(false, gdk_event_get_time(event)); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + gdk_keyboard_grab(get_window()->gobj(), false, gdk_event_get_time(event)); +#pragma GCC diagnostic pop signal_key_press_event().connect(sigc::mem_fun(*this, &CellEditableAccel::on_key)); } @@ -83,10 +86,10 @@ class CellEditableAccel : public Gtk::EventBox, public Gtk::CellEditable { if (event->is_modifier) return true; switch (event->keyval) { - case GDK_Super_L: - case GDK_Super_R: - case GDK_Hyper_L: - case GDK_Hyper_R: + case GDK_KEY_Super_L: + case GDK_KEY_Super_R: + case GDK_KEY_Hyper_L: + case GDK_KEY_Hyper_R: return true; } guint mods = event->state & gtk_accelerator_get_default_mod_mask(); @@ -101,12 +104,15 @@ class CellEditableAccel : public Gtk::EventBox, public Gtk::CellEditable { virtual void on_editing_done() { remove_modal_grab(); - get_window()->keyboard_ungrab(CurrentTime); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + gdk_keyboard_ungrab(CurrentTime); +#pragma GCC diagnostic pop Gtk::CellEditable::on_editing_done(); } }; -class CellEditableCombo : public Gtk::ComboBoxText, public Gtk::CellEditable { +class CellEditableCombo : public Gtk::ComboBoxText { CellRendererTextish *parent; Glib::ustring path; public: @@ -115,7 +121,7 @@ class CellEditableCombo : public Gtk::ComboBoxText, public Gtk::CellEditable { parent(parent_), path(path_) { while (*items) - append_text(_(*(items++))); + append(_(*(items++))); } protected: virtual void on_changed() { @@ -362,7 +368,7 @@ bool Actions::AppsStore::row_drop_possible_vfunc(const Gtk::TreeModel::Path &des if (expecting && expected != dest) expecting = false; if (!expecting) { - if (dest.get_depth() < 2 || dest.back() != 0) + if (gtk_tree_path_get_depth((GtkTreePath *)dest.gobj()) < 2 || dest.back() != 0) return false; expected = dest; expected.up(); @@ -437,7 +443,7 @@ bool Actions::Store::row_draggable_vfunc(const Gtk::TreeModel::Path &path) const bool Actions::Store::row_drop_possible_vfunc(const Gtk::TreeModel::Path &dest, const Gtk::SelectionData &selection) const { static bool ignore_next = false; - if (dest.get_depth() > 1) { + if (gtk_tree_path_get_depth((GtkTreePath *)dest.gobj()) > 1) { ignore_next = true; return false; } diff --git a/composite.cc b/composite.cc index e043dab3..ec70ad10 100644 --- a/composite.cc +++ b/composite.cc @@ -25,20 +25,19 @@ Popup::Popup(int x1, int y1, int x2, int y2) : Gtk::Window(Gtk::WINDOW_POPUP), r if (!is_composited()) throw std::runtime_error(_("'composite' not available")); - Glib::RefPtr colormap = get_screen()->get_rgba_colormap(); - if (colormap) - set_colormap(colormap); - signal_expose_event().connect(sigc::mem_fun(*this, &Popup::on_expose)); + Glib::RefPtr visual = get_screen()->get_rgba_visual(); + gtk_widget_set_visual(Widget::gobj(), visual->gobj()); + signal_draw().connect(sigc::mem_fun(*this, &Popup::on_draw)); realize(); move(x1, y1); resize(x2-x1, y2-y1); - get_window()->input_shape_combine_region(Gdk::Region(), 0, 0); + get_window()->input_shape_combine_region(Cairo::Region::create(), 0, 0); // tell compiz to leave this window the hell alone get_window()->set_type_hint(Gdk::WINDOW_TYPE_HINT_DESKTOP); } void Popup::invalidate(int x1, int y1, int x2, int y2) { - if (is_mapped()) { + if (get_mapped()) { Gdk::Rectangle inv(x1 - rect.get_x(), y1 - rect.get_y(), x2-x1, y2-y1); get_window()->invalidate_rect(inv, false); } else @@ -109,17 +108,10 @@ void Popup::draw_line(Cairo::RefPtr ctx) { } -bool Popup::on_expose(GdkEventExpose* event) { - Cairo::RefPtr ctx = get_window()->create_cairo_context(); +bool Popup::on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& ctx) { ctx->set_operator(Cairo::OPERATOR_SOURCE); - - Gdk::Region region(event->region, true); - Gdk::Cairo::add_region_to_path(ctx, region); - ctx->clip(); - - Gdk::Cairo::add_region_to_path(ctx, region); ctx->set_source_rgba(0.0, 0.0, 0.0, 0.0); - ctx->fill(); + ctx->paint(); ctx->translate(-rect.get_x(), -rect.get_y()); draw_line(ctx); diff --git a/composite.h b/composite.h index 8d972e53..a9c4cdb9 100644 --- a/composite.h +++ b/composite.h @@ -21,7 +21,7 @@ #include class Popup : public Gtk::Window { - bool on_expose(GdkEventExpose* event); + bool on_draw(const ::Cairo::RefPtr< ::Cairo::Context>& ctx); void draw_line(Cairo::RefPtr ctx); Gdk::Rectangle rect; public: diff --git a/dbus-server.cc b/dbus-server.cc deleted file mode 100644 index 98c99f67..00000000 --- a/dbus-server.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2008-2009, Thomas Jaeger - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include - -#include -#include "win.h" - -#define SERVER_OBJECT_TYPE (server_object_get_type()) - -typedef struct _ServerObject { - GObject object; -} ServerObject; - -typedef struct _ServerObjectClass { - GObjectClass object_class; -} ServerObjectClass; - -void run_by_name(const char *str); - -static gboolean server_send(ServerObject *obj, const char *str, GError **error) { - run_by_name(str); - return TRUE; -} - -extern Source disabled; -static gboolean server_enable(ServerObject *obj, GError **error) { - disabled.set(!disabled.get()); - return TRUE; -} - -static gboolean server_about(ServerObject *obj, GError **error) { - win->show_about(); - return TRUE; -} - -extern void quit(); -static gboolean server_quit(ServerObject *obj, GError **error) { - quit(); - return TRUE; -} - -#include "dbus-server.h" - -static void server_object_class_init(ServerObjectClass *klass) { - dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(klass), &dbus_glib_server_object_info); -} - -static void server_object_init(ServerObject *obj) {} - -G_DEFINE_TYPE(ServerObject, server_object, G_TYPE_OBJECT); - -int start_dbus() { - DBusGConnection *connection; - DBusGProxy *proxy; - GError *error = NULL; - ServerObject *obj; - guint32 request_name_ret; - - connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (!connection) - return false; - - proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); - if (!org_freedesktop_DBus_request_name(proxy, "org.easystroke", 0, &request_name_ret, &error)) - return false; - - if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) - return -1; - - g_object_unref(proxy); - - obj =(ServerObject *)g_object_new(SERVER_OBJECT_TYPE, NULL); - dbus_g_connection_register_g_object(connection, "/org/easystroke", G_OBJECT(obj)); - return true; -} diff --git a/dbus.xml b/dbus.xml deleted file mode 100644 index 8055b4d6..00000000 --- a/dbus.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/easystroke.desktop.in b/easystroke.desktop.in index d8f34654..1257b05f 100644 --- a/easystroke.desktop.in +++ b/easystroke.desktop.in @@ -6,6 +6,7 @@ Terminal=false Exec=easystroke Icon=easystroke Categories=GTK;Utility;Accessibility; +Actions=About;Enable;Disable;Quit _Comment=Control your desktop using mouse gestures [Desktop Action About] @@ -13,9 +14,13 @@ _Name=About Exec=easystroke about [Desktop Action Enable] -_Name=Enable/Disable +_Name=Enable Exec=easystroke enable +[Desktop Action Disable] +_Name=Disable +Exec=easystroke disable + [Desktop Action Quit] _Name=Quit Exec=easystroke quit diff --git a/gesture.h b/gesture.h index 10ab84a2..accecdfe 100644 --- a/gesture.h +++ b/gesture.h @@ -17,7 +17,7 @@ #define __GESTURE_H__ #include "stroke.h" -#include +#include #include #include #include diff --git a/gui.glade b/gui.glade index c146fbdb..704bca45 100644 --- a/gui.glade +++ b/gui.glade @@ -1,7 +1,6 @@ - - + False 5 @@ -35,12 +34,13 @@ Jesus Vera (Spanish) Martín V. (Spanish) Van Diep Duong (Vietnamese) - + True False + vertical 2 - + True False end @@ -92,18 +92,19 @@ Van Diep Duong (Vietnamese) warning cancel - + True False 2 - + True False end gtk-delete + False True True True @@ -139,12 +140,12 @@ Van Diep Duong (Vietnamese) main ok - + True False 2 - + True False end @@ -166,18 +167,19 @@ Van Diep Duong (Vietnamese) True main - + True False 2 - + True False end gtk-cancel + False True True True @@ -194,6 +196,7 @@ Van Diep Duong (Vietnamese) _Delete Current + False True True True @@ -229,18 +232,20 @@ Van Diep Duong (Vietnamese) True main - + True False + vertical 6 - + True False end gtk-cancel + False True True True @@ -256,6 +261,7 @@ Van Diep Duong (Vietnamese) gtk-ok + False True True True @@ -271,6 +277,7 @@ Van Diep Duong (Vietnamese) _Default + False True True True @@ -301,10 +308,12 @@ Van Diep Duong (Vietnamese) Timeout + False True True False False + 0.5 True True @@ -317,10 +326,12 @@ Van Diep Duong (Vietnamese) Instant Gestures + False True True False False + 0.5 True True radio_timeout_default @@ -334,10 +345,12 @@ Van Diep Duong (Vietnamese) Click & Hold + False True True False False + 0.5 True True radio_timeout_default @@ -368,6 +381,7 @@ Van Diep Duong (Vietnamese) _Control + False True True True @@ -382,6 +396,7 @@ Van Diep Duong (Vietnamese) _Shift + False True True True @@ -392,6 +407,7 @@ Van Diep Duong (Vietnamese) _Alt + False True True True @@ -406,6 +422,7 @@ Van Diep Duong (Vietnamese) S_uper + False True True True @@ -422,6 +439,7 @@ Van Diep Duong (Vietnamese) An_y Modifier + False True True True @@ -589,12 +607,13 @@ Van Diep Duong (Vietnamese) True True - automatic - automatic True True + + + @@ -602,10 +621,12 @@ Van Diep Duong (Vietnamese) Show deleted rows + False True True False False + 0 True @@ -624,6 +645,7 @@ Van Diep Duong (Vietnamese) Add Application + False True True True @@ -639,6 +661,7 @@ Van Diep Duong (Vietnamese) Remove Application/Group + False True True True @@ -654,6 +677,7 @@ Van Diep Duong (Vietnamese) Add Group + False True True True @@ -678,6 +702,7 @@ Van Diep Duong (Vietnamese) Reset Action(s) + False True True True @@ -713,8 +738,6 @@ Van Diep Duong (Vietnamese) True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - automatic - automatic @@ -741,6 +764,7 @@ Van Diep Duong (Vietnamese) _Record Stroke + False True True True @@ -758,6 +782,7 @@ Van Diep Duong (Vietnamese) _Add Action + False True True True @@ -775,6 +800,7 @@ Van Diep Duong (Vietnamese) _Delete Action(s) + False True True True @@ -792,6 +818,7 @@ Van Diep Duong (Vietnamese) _Hide + False True True True @@ -863,6 +890,7 @@ Van Diep Duong (Vietnamese) _Gesture Button + False True True True @@ -911,6 +939,7 @@ Van Diep Duong (Vietnamese) gtk-add + False True True True @@ -926,6 +955,7 @@ Van Diep Duong (Vietnamese) gtk-edit + False True True True @@ -941,6 +971,7 @@ Van Diep Duong (Vietnamese) gtk-remove + False True True True @@ -964,8 +995,6 @@ Van Diep Duong (Vietnamese) True True - automatic - automatic 120 @@ -994,7 +1023,7 @@ Van Diep Duong (Vietnamese) - True + False False 1 @@ -1184,6 +1213,7 @@ Van Diep Duong (Vietnamese) + False True True True @@ -1234,10 +1264,12 @@ Van Diep Duong (Vietnamese) Show popups ( + False True True False False + 0 True @@ -1249,10 +1281,12 @@ Van Diep Duong (Vietnamese) to the right of the cursor) + False True True False False + 0 True @@ -1276,10 +1310,12 @@ Van Diep Duong (Vietnamese) Show tray icon + False True True False False + 0 True @@ -1291,10 +1327,12 @@ Van Diep Duong (Vietnamese) Show last gesture in tray + False True True False False + 0 True @@ -1306,10 +1344,12 @@ Van Diep Duong (Vietnamese) Autostart easystroke + False True True False False + 0 True @@ -1363,13 +1403,14 @@ Van Diep Duong (Vietnamese) True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - automatic - automatic True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + @@ -1402,6 +1443,7 @@ Van Diep Duong (Vietnamese) _Add Exception + False True True True @@ -1419,6 +1461,7 @@ Van Diep Duong (Vietnamese) _Remove Exception + False True True True @@ -1436,6 +1479,7 @@ Van Diep Duong (Vietnamese) _Hide + False True True True @@ -1524,10 +1568,12 @@ Van Diep Duong (Vietnamese) Timeout Gestures + False True True False False + 0 True @@ -1542,10 +1588,12 @@ Van Diep Duong (Vietnamese) Ignore strokes leading up to advanced gestures + False True True False False + 0 True @@ -1557,6 +1605,7 @@ Van Diep Duong (Vietnamese) (See Documentation) + False True True True @@ -1586,10 +1635,12 @@ Van Diep Duong (Vietnamese) Show popups on advanced gestures + False True True False False + 0 True @@ -1601,10 +1652,12 @@ Van Diep Duong (Vietnamese) Show OSD + False True True False False + 0 True @@ -1615,7 +1668,7 @@ Van Diep Duong (Vietnamese) - True + False True 3 @@ -1628,10 +1681,12 @@ Van Diep Duong (Vietnamese) Invert Scroll Direction + False True True False False + 0 True @@ -1667,7 +1722,7 @@ Van Diep Duong (Vietnamese) - True + False True 6 4 @@ -1676,14 +1731,16 @@ Van Diep Duong (Vietnamese) Move the cursor back to the original position after each gesture + False True True False False + 0 True - True + False True 5 @@ -1729,10 +1786,12 @@ Van Diep Duong (Vietnamese) Stay in 'scroll' and 'ignore' mode as long as the pen is within range + False True True False False + 0 True @@ -1779,13 +1838,14 @@ Van Diep Duong (Vietnamese) True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - automatic - automatic True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + @@ -1818,6 +1878,7 @@ Van Diep Duong (Vietnamese) _Hide + False True True True @@ -1872,13 +1933,14 @@ Van Diep Duong (Vietnamese) True False - automatic - automatic True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + @@ -1891,13 +1953,14 @@ Van Diep Duong (Vietnamese) True False - automatic - automatic True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + @@ -1923,6 +1986,7 @@ Van Diep Duong (Vietnamese) _Hide + False True True True @@ -1940,6 +2004,7 @@ Van Diep Duong (Vietnamese) _Matrix + False True True True diff --git a/main.cc b/main.cc index a03e5abf..0bb26171 100644 --- a/main.cc +++ b/main.cc @@ -59,12 +59,6 @@ Grabber::XiDevice *current_dev = 0; std::set xinput_pressed; // TODO get rid of guint modifiers; -static bool show_gui = false; -static bool no_dbus = false; - -static int argc; -static char **argv; - static Window ping_window = 0; static boost::shared_ptr trace; static std::map core_inv_map; @@ -192,8 +186,8 @@ class OSD : public Gtk::Window { set_border_width(15); WIDGET(Gtk::Label, label, "" + txt + ""); label.set_use_markup(); - label.modify_fg(Gtk::STATE_NORMAL, Gdk::Color("White")); - modify_bg(Gtk::STATE_NORMAL, Gdk::Color("RoyalBlue3")); + label.override_color(Gdk::RGBA("White"), Gtk::STATE_FLAG_NORMAL); + override_background_color(Gdk::RGBA("RoyalBlue3"), Gtk::STATE_FLAG_NORMAL); set_opacity(0.75); add(label); label.show(); @@ -201,7 +195,7 @@ class OSD : public Gtk::Window { get_size(w,h); do_move(); show(); - get_window()->input_shape_combine_region(Gdk::Region(), 0, 0); + get_window()->input_shape_combine_region(Cairo::Region::create(), 0, 0); } static void do_move() { int left = gdk_screen_width() - 10; @@ -325,12 +319,8 @@ static int xErrorHandler(Display *dpy2, XErrorEvent *e) { static int xIOErrorHandler(Display *dpy2) { if (dpy != dpy2) return oldIOHandler(dpy2); - printf(_("Fatal Error: Connection to X server lost, restarting...\n")); - char *args[argc+1]; - for (int i = 0; irun(); } -void run_by_name(const char *str) { - if (!strcmp(str, "")) { - win->show_hide(); - return; - } +static void run_by_name(const char *str, const Glib::RefPtr &cmd_line) { for (ActionDB::const_iterator i = actions.begin(); i != actions.end(); i++) { if (i->second.name == std::string(str)) { if (i->second.action) @@ -1062,7 +1048,10 @@ void run_by_name(const char *str) { return; } } - printf(_("Warning: No action \"%s\" defined\n"), str); + char *msg; + asprintf(&msg, _("Warning: No action \"%s\" defined\n"), str); + cmd_line->print(msg); + free(msg); } void icon_warning() { @@ -1091,27 +1080,28 @@ void quit() { queue(sigc::ptr_fun(&Gtk::Main::quit)); } -static void quit(int) { quit(); } - -class Main { - std::string parse_args_and_init_gtk(); - void create_config_dir(); - char* next_event(); - void usage(char *me, bool good); +class App : public Gtk::Application { +public: + App(int& argc, char**& argv, const Glib::ustring& application_id, Gio::ApplicationFlags flags=Gio::APPLICATION_FLAGS_NONE) : + Gtk::Application(argc, argv, application_id, flags), remote(false) {} + ~App(); +private: + void on_activate(); + virtual bool local_command_line_vfunc (char**& arguments, int& exit_status); + int on_command_line(const Glib::RefPtr &); + + void usage(const char *me); void version(); - std::string display; - Gtk::Main *kit; -public: - Main(); - void run(); + void create_config_dir(); bool handle(Glib::IOCondition); void handle_enter_leave(XEvent &ev); void handle_event(XEvent &ev); void handle_xi2_event(XIDeviceEvent *event); void handle_raw_motion(XIRawEvent *event); void report_xi2_event(XIDeviceEvent *event, const char *type); - ~Main(); + + bool remote; }; class ReloadTrace : public Timeout { @@ -1125,76 +1115,139 @@ class ReloadTrace : public Timeout { static void schedule_reload_trace() { reload_trace.set_timeout(1000); } -static void xdg_open(const Glib::ustring str) { - if (!fork()) { - execlp("xdg-open", "xdg-open", str.c_str(), NULL); - exit(EXIT_FAILURE); +extern const char *gui_buffer; + +bool App::local_command_line_vfunc (char**& arg, int& exit_status) { + int i = 1; + while (arg[i] && arg[i][0] == '-') { + if (arg[i][1] == '-') { + if (!strcmp(arg[i], "--experimental")) { + experimental = true; + } else if (!strcmp(arg[i], "--verbose")) { + verbosity++; + } else if (!strcmp(arg[i], "--help")) { + usage(arg[0]); + exit_status = EXIT_SUCCESS; + return true; + } else if (!strcmp(arg[i], "--version")) { + version(); + exit_status = EXIT_SUCCESS; + return true; + } else if (!strcmp(arg[i], "--config-dir")) { + if (!arg[++i]) { + printf("Error: Option --config-dir requires an argument.\n"); + exit_status = EXIT_FAILURE; + return true; + } + config_dir = arg[i]; + } else { + printf("Error: Unknown option %s\n", arg[i]); + exit_status = EXIT_FAILURE; + return true; + } + } else { + for (int j = 1; arg[i][j]; j++) + switch (arg[i][j]) { + case 'c': + if (arg[i][j+1] || !arg[i+1]) { + printf("Error: Option -c requires an argument.\n"); + exit_status = EXIT_FAILURE; + return true; + } + config_dir = arg[++i]; + break; + case 'e': + experimental = true; + break; + case 'v': + verbosity++; + break; + case 'h': + usage(arg[0]); + exit_status = EXIT_SUCCESS; + return true; + default: + printf("Error: Unknown option -%c\n", arg[i][j]); + exit_status = EXIT_FAILURE; + return true; + } + } + i++; } -} -static void link_button_hook(Gtk::LinkButton *, const Glib::ustring& uri) { xdg_open(uri); } -static void about_dialog_hook(Gtk::AboutDialog &, const Glib::ustring& url) { xdg_open(url); } + if (i > 1) { + for (int j = 1; j < i; j++) { + g_free(arg[j]); + arg[j] = 0; + } + for (int j = 0; arg[j+i]; j++) { + arg[j+1] = arg[j+i]; + arg[j+i] = 0; + } + } -// dbus-send --type=method_call --dest=org.easystroke /org/easystroke org.easystroke.send string:"foo" -static void send_dbus(bool action, const char *str) { - GError *error = 0; - DBusGConnection *bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error); - if (!bus) { - printf(_("Error initializing D-BUS\n")); - exit(EXIT_FAILURE); + if (!register_application()) { + printf("Failed to register the application\n"); + exit_status = EXIT_FAILURE; + return true; } - DBusGProxy *proxy = dbus_g_proxy_new_for_name(bus, "org.easystroke", "/org/easystroke", "org.easystroke"); - if (action) - dbus_g_proxy_call_no_reply(proxy, "send", G_TYPE_STRING, str, G_TYPE_INVALID); - else - dbus_g_proxy_call_no_reply(proxy, str, G_TYPE_INVALID); + activate(); + return false; } -int start_dbus(); -Main::Main() : kit(0) { +int App::on_command_line(const Glib::RefPtr &command_line) { + int argc; + char **arg = command_line->get_arguments(argc); + for (int i = 1; arg[i]; i++) + if (!strcmp(arg[i], "send")) { + if (!arg[++i]) + printf("Warning: Send requires an argument\n"); + else + run_by_name(arg[i], command_line); + } else if (!strcmp(arg[i], "show")) { + win->show(); + } else if (!strcmp(arg[i], "hide")) { + win->hide(); + } else if (!strcmp(arg[i], "disable")) { + disabled.set(true); + } else if (!strcmp(arg[i], "enable")) { + disabled.set(false); + } else if (!strcmp(arg[i], "about")) { + win->show_about(); + } else if (!strcmp(arg[i], "quit")) { + quit(); + } else { + char *msg; + asprintf(&msg, "Warning: Unknown command \"%s\".\n", arg[i]); + command_line->print(msg); + free(msg); + } + if (!arg[1] && remote) + win->show_hide(); + remote = true; + return true; +} + +void App::on_activate() { + if (win) + return; + bindtextdomain("easystroke", is_dir("po") ? "po" : LOCALEDIR); bind_textdomain_codeset("easystroke", "UTF-8"); textdomain("easystroke"); - if (0) { - RStroke trefoil = Stroke::trefoil(); - trefoil->draw_svg("easystroke.svg"); - exit(EXIT_SUCCESS); - } - if (argc > 1 && !strcmp(argv[1], "send")) { - if (argc == 2) - usage(argv[0], false); - gtk_init(&argc, &argv); - send_dbus(true, argv[2]); - exit(EXIT_SUCCESS); - } - if (argc > 1 && (!strcmp(argv[1], "enable") || !strcmp(argv[1], "about") || !strcmp(argv[1], "quit"))) { - gtk_init(&argc, &argv); - send_dbus(false, argv[1]); - exit(EXIT_SUCCESS); - } + oldHandler = XSetErrorHandler(xErrorHandler); + oldIOHandler = XSetIOErrorHandler(xIOErrorHandler); - display = parse_args_and_init_gtk(); create_config_dir(); unsetenv("DESKTOP_AUTOSTART_ID"); - - signal(SIGINT, &quit); - signal(SIGCHLD, SIG_IGN); - - Gtk::LinkButton::set_uri_hook(sigc::ptr_fun(&link_button_hook)); - Gtk::AboutDialog::set_url_hook(sigc::ptr_fun(&about_dialog_hook)); - - dpy = XOpenDisplay(display.c_str()); + dpy = XOpenDisplay(NULL); if (!dpy) { printf(_("Couldn't open display.\n")); exit(EXIT_FAILURE); } - if (!no_dbus && start_dbus() < 0) { - printf(_("Easystroke is already running, showing configuration window instead.\n")); - send_dbus(true, ""); - exit(EXIT_SUCCESS); - } + ROOT = DefaultRootWindow(dpy); ping_window = XCreateSimpleWindow(dpy, ROOT, 0, 0, 1, 1, 0, 0, 0); @@ -1220,13 +1273,8 @@ Main::Main() : kit(0) { handler->init(); XTestGrabControl(dpy, True); -} - -extern const char *gui_buffer; - -void Main::run() { Glib::RefPtr io = Glib::IOSource::create(ConnectionNumber(dpy), Glib::IO_IN); - io->connect(sigc::mem_fun(*this, &Main::handle)); + io->connect(sigc::mem_fun(*this, &App::handle)); io->attach(); try { widgets = Gtk::Builder::create_from_string(gui_buffer); @@ -1235,116 +1283,45 @@ void Main::run() { exit(EXIT_FAILURE); } win = new Win; - if (show_gui || !actions.get_root()->size_rec()) + add_window(win->get_window()); + if (!actions.get_root()->size_rec()) win->get_window().show(); - Gtk::Main::run(); - delete win; + hold(); } -void Main::usage(char *me, bool good) { +void App::usage(const char *me) { printf("The full easystroke documentation is available at the following address:\n"); printf("\n"); printf("http://easystroke.wiki.sourceforge.net/Documentation#content\n"); printf("\n"); - printf("Usage: %s [OPTION]...\n", me); - printf("or: %s send \n", me); - printf(" %s enable\n", me); - printf(" %s about\n", me); - printf(" %s quit\n", me); + printf("Usage: %s [OPTION]... [COMMAND]...\n", me); + printf("\n"); + printf("Commands:\n"); + printf(" send Execute action \n"); + printf(" show Show configuration window\n"); + printf(" hide Hide configuration window\n"); + printf(" disable Disable easystroke\n"); + printf(" enable Enable easystroke\n"); + printf(" about Show about dialog\n"); + printf(" quit Quit easystroke\n"); printf("\n"); printf("Options:\n"); - printf(" -c, --config-dir Directory for config files\n"); - printf(" --display X Server to contact\n"); - printf(" -D --no-dbus Don't try to register as a DBus service\n"); + printf(" -c, --config-dir Directory for config files\n"); printf(" -e --experimental Start in experimental mode\n"); - printf(" -g, --show-gui Show the configuration dialog on startup\n"); - printf(" -x --disable Start disabled\n"); printf(" -v, --verbose Increase verbosity level\n"); printf(" -h, --help Display this help and exit\n"); printf(" --version Output version information and exit\n"); - exit(good ? EXIT_SUCCESS : EXIT_FAILURE); } extern const char *version_string; -void Main::version() { +void App::version() { printf("easystroke %s\n", version_string); printf("\n"); printf("Written by Thomas Jaeger .\n"); exit(EXIT_SUCCESS); } -std::string Main::parse_args_and_init_gtk() { - static struct option long_opts1[] = { - {"display",1,0,'d'}, - {"help",0,0,'h'}, - {"version",0,0,'V'}, - {"show-gui",0,0,'g'}, - {0,0,0,0} - }; - static struct option long_opts2[] = { - {"config-dir",1,0,'c'}, - {"display",1,0,'d'}, - {"experimental",0,0,'e'}, - {"show-gui",0,0,'g'}, - {"verbose",0,0,'v'}, - {"no-dbus",0,0,'D'}, - {"disabled",0,0,'x'}, - {0,0,0,0} - }; - std::string display; - int opt; - // parse --display here, before Gtk::Main(...) takes it away from us - opterr = 0; - while ((opt = getopt_long(argc, argv, "gh", long_opts1, 0)) != -1) - switch (opt) { - case 'd': - display = optarg; - break; - case 'g': - show_gui = true; - break; - case 'h': - usage(argv[0], true); - break; - case 'V': - version(); - break; - } - optind = 1; - opterr = 1; - kit = new Gtk::Main(argc, argv); - oldHandler = XSetErrorHandler(xErrorHandler); - oldIOHandler = XSetIOErrorHandler(xIOErrorHandler); - - while ((opt = getopt_long(argc, argv, "c:egvDx", long_opts2, 0)) != -1) { - switch (opt) { - case 'c': - config_dir = optarg; - break; - case 'e': - experimental = true; - break; - case 'v': - verbosity++; - break; - case 'D': - no_dbus = true; - break; - case 'x': - disabled.set(true); - break; - case 'd': - case 'n': - case 'g': - break; - default: - usage(argv[0], false); - } - } - return display; -} - -void Main::create_config_dir() { +void App::create_config_dir() { if (config_dir == "") { config_dir = getenv("HOME"); config_dir += "/.easystroke"; @@ -1372,7 +1349,7 @@ void Main::create_config_dir() { extern Window get_app_window(Window w); -void Main::handle_enter_leave(XEvent &ev) { +void App::handle_enter_leave(XEvent &ev) { if (ev.xcrossing.mode == NotifyGrab) return; if (ev.xcrossing.detail == NotifyInferior) @@ -1386,7 +1363,7 @@ void Main::handle_enter_leave(XEvent &ev) { } #define H (handler->top()) -void Main::handle_event(XEvent &ev) { +void App::handle_event(XEvent &ev) { switch(ev.type) { case EnterNotify: @@ -1450,7 +1427,7 @@ static void print_coordinates(XIValuatorState *valuators, double *values) { } } -void Main::report_xi2_event(XIDeviceEvent *event, const char *type) { +void App::report_xi2_event(XIDeviceEvent *event, const char *type) { printf("%s (XI2): ", type); if (event->detail) printf("%d ", event->detail); @@ -1459,7 +1436,7 @@ void Main::report_xi2_event(XIDeviceEvent *event, const char *type) { printf(") at t = %ld\n", event->time); } -void Main::handle_xi2_event(XIDeviceEvent *event) { +void App::handle_xi2_event(XIDeviceEvent *event) { switch (event->evtype) { case XI_ButtonPress: if (verbosity >= 3) @@ -1513,7 +1490,7 @@ void Main::handle_xi2_event(XIDeviceEvent *event) { } } -void Main::handle_raw_motion(XIRawEvent *event) { +void App::handle_raw_motion(XIRawEvent *event) { if (!current_dev || current_dev->dev != event->deviceid) return; double x = 0.0, y = 0.0; @@ -1542,7 +1519,7 @@ void Main::handle_raw_motion(XIRawEvent *event) { #undef H -bool Main::handle(Glib::IOCondition) { +bool App::handle(Glib::IOCondition) { while (XPending(dpy)) { try { XEvent ev; @@ -1557,24 +1534,26 @@ bool Main::handle(Glib::IOCondition) { return true; } -Main::~Main() { - trace->end(); - trace.reset(); - delete grabber; - delete kit; - XCloseDisplay(dpy); - prefs.execute_now(); - action_watcher->execute_now(); +App::~App() { + if (win) { + delete win; + trace->end(); + trace.reset(); + delete grabber; + XCloseDisplay(dpy); + prefs.execute_now(); + action_watcher->execute_now(); + } } -int main(int argc_, char **argv_) { - argc = argc_; - argv = argv_; - Main mn; - mn.run(); - if (verbosity >= 2) - printf("Exiting...\n"); - return EXIT_SUCCESS; +int main(int argc, char **argv) { + if (0) { + RStroke trefoil = Stroke::trefoil(); + trefoil->draw_svg("easystroke.svg"); + exit(EXIT_SUCCESS); + } + App app(argc, argv, "org.easystroke.easystroke", Gio::APPLICATION_HANDLES_COMMAND_LINE); + return app.run(argc, argv); } std::string select_window() { diff --git a/main.h b/main.h index 8fe688b4..cbc121d6 100644 --- a/main.h +++ b/main.h @@ -21,6 +21,7 @@ bool is_file(std::string filename); bool is_dir(std::string dirname); +void quit(); extern std::string config_dir; extern const char *prefs_versions[]; diff --git a/prefs.cc b/prefs.cc index efbf0916..f246aa5a 100644 --- a/prefs.cc +++ b/prefs.cc @@ -116,7 +116,7 @@ template class Combo : private Base { combo = Gtk::manage(new Gtk::ComboBoxText); parent->add(*combo); for (const Info *i = info; i->name; i++) - combo->append_text(_(i->name)); + combo->append(_(i->name)); notify(); combo->signal_changed().connect(sigc::mem_fun(*this, &Combo::on_changed)); combo->show(); @@ -468,7 +468,7 @@ SelectButton::SelectButton(ButtonInfo bi, bool def, bool any) { select_button = Gtk::manage(new Gtk::ComboBoxText); box_button->add(*select_button); for (int i = 1; i <= 12; i++) - select_button->append_text(Glib::ustring::compose(_("Button %1"), i)); + select_button->append(Glib::ustring::compose(_("Button %1"), i)); select_button->show(); } select_button->set_active(bi.button-1); diff --git a/stats.cc b/stats.cc index e83517d9..8e56c0c8 100644 --- a/stats.cc +++ b/stats.cc @@ -63,10 +63,14 @@ class Feedback { if (s) { icon.reset(new Gtk::Window(Gtk::WINDOW_POPUP)); icon->set_type_hint(Gdk::WINDOW_TYPE_HINT_TOOLTIP); - icon->set_name("gtk-tooltip"); + icon->get_style_context()->add_class(GTK_STYLE_CLASS_TOOLTIP); + Glib::RefPtr visual = icon->get_screen()->get_rgba_visual(); + gtk_widget_set_visual((GtkWidget *)icon->gobj(), visual->gobj()); + WIDGET(Gtk::Image, image, s->draw(STROKE_SIZE)); icon->set_accept_focus(false); icon->add(image); + image.set_padding(2,2); image.show(); icon->get_size(w,h); icon->move(x - w/2, y - h/2); @@ -76,22 +80,25 @@ class Feedback { if (t != "") { text.reset(new Gtk::Window(Gtk::WINDOW_POPUP)); text->set_type_hint(Gdk::WINDOW_TYPE_HINT_TOOLTIP); - text->set_name("gtk-tooltip"); + text->get_style_context()->add_class(GTK_STYLE_CLASS_TOOLTIP); + Glib::RefPtr visual = text->get_screen()->get_rgba_visual(); + gtk_widget_set_visual((GtkWidget *)text->gobj(), visual->gobj()); + text->set_accept_focus(false); - text->set_border_width(2); WIDGET(Gtk::Label, label, t); text->add(label); + label.set_padding(4,4); label.show(); text->get_size(w,h); text->move(x - w/2, y + h/2); } if (text) { text->show(); - text->get_window()->input_shape_combine_region(Gdk::Region(), 0, 0); + text->get_window()->input_shape_combine_region(Cairo::Region::create(), 0, 0); } if (icon) { icon->show(); - icon->get_window()->input_shape_combine_region(Gdk::Region(), 0, 0); + icon->get_window()->input_shape_combine_region(Cairo::Region::create(), 0, 0); } } }; diff --git a/win.cc b/win.cc index 4190a408..086451f3 100644 --- a/win.cc +++ b/win.cc @@ -164,8 +164,6 @@ class MenuCheck : private Base { } }; -extern void quit(); - Win::Win() : actions(new Actions), prefs_tab(new Prefs), stats(new Stats) { show_hide_icon(); prefs.tray_icon.connect(new Notifier(sigc::mem_fun(*this, &Win::show_hide_icon))); @@ -248,12 +246,16 @@ void Win::show_about() { } void Win::show_hide() { - if (win->is_mapped()) + if (win->get_mapped()) win->hide(); else win->show(); } +void Win::show() { + win->show(); +} + void Win::hide() { win->hide(); } diff --git a/win.h b/win.h index 67730e8a..ada98d02 100644 --- a/win.h +++ b/win.h @@ -57,10 +57,11 @@ class Win : Timeout { boost::shared_ptr actions; boost::shared_ptr prefs_tab; boost::shared_ptr stats; + void show(); + void hide(); void show_hide(); void set_icon(RStroke stroke, bool invert); void show_about(); - void hide(); private: bool on_icon_size_changed(int); virtual void timeout();