Fix #1677510 (part 1): Added the capability of saving and restoring the input devices...
authorgballintijn <gballintijn@1f10aa63-cdf2-0310-b900-c93c546f37ac>
Sun, 12 Apr 2009 13:59:11 +0000 (13:59 +0000)
committerCarlos Lopez <carlos@pcnuevo.(none)>
Fri, 12 Jun 2009 14:27:35 +0000 (16:27 +0200)
git-svn-id: https://synfig.svn.sourceforge.net/svnroot/synfig@2360 1f10aa63-cdf2-0310-b900-c93c546f37ac

synfig-studio/trunk/AUTHORS
synfig-studio/trunk/README
synfig-studio/trunk/src/gtkmm/app.cpp
synfig-studio/trunk/src/gtkmm/devicetracker.cpp
synfig-studio/trunk/src/gtkmm/devicetracker.h
synfig-studio/trunk/src/synfigapp/inputdevice.cpp
synfig-studio/trunk/src/synfigapp/inputdevice.h

index abdd35e..5c60ae2 100644 (file)
@@ -19,6 +19,7 @@ Timo Paulssen (timonator)
 IL'dar AKHmetgaleev (AkhIL)
 Gerald Young (Yoyobuae)
 Cyril Brulebois (KiBi)
+Gerco Ballintijn
 
 Translators:
 
index 1db6ecf..6bd0973 100644 (file)
@@ -33,7 +33,7 @@ Copyright 2008 Gerald Young
 Copyright 2008 David Roden
 Copyright 2008 Daniel Hornung
 Copyright 2008 Carlos López
-Copyright 2008 Gerco Ballintijn
+Copyright 2008-2009 Gerco Ballintijn
 
 Some of the icons are placed in the Public Domain by Chris Norman
 Some of the icons are placed in the Public Domain by Carlos López González
index ee4459b..58d6c61 100644 (file)
@@ -1272,7 +1272,7 @@ App::App(int *argc, char ***argv):
                studio_init_cb.task(_("Init Input Dialog..."));
                dialog_input=new Gtk::InputDialog();
                dialog_input->get_close_button()->signal_clicked().connect( sigc::mem_fun( *dialog_input, &Gtk::InputDialog::hide ) );
-               dialog_input->get_save_button()->signal_clicked().connect( sigc::ptr_fun(studio::App::dialog_not_implemented) );
+               dialog_input->get_save_button()->signal_clicked().connect( sigc::mem_fun( *device_tracker, &DeviceTracker::save_preferences) );
 
                studio_init_cb.task(_("Init auto recovery..."));
                auto_recover=new AutoRecover();
index 6d2d516..2f661dd 100644 (file)
@@ -6,6 +6,7 @@
 **
 **     \legal
 **     Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
+**  Copyright (c) 2009 Gerco Ballintijn
 **
 **     This package is free software; you can redistribute it and/or
 **     modify it under the terms of the GNU General Public License as
 */
 /* ========================================================================= */
 
+// FIXME: The code here doesn't use the GTKmm layer but uses GTK+ directly
+// since the GTKmm wrapper for Gdk::Device is incomplete. When the wrapper
+// gets fixed, this code should be updated accoordingly.
+
 /* === H E A D E R S ======================================================= */
 
 #ifdef USING_PCH
@@ -30,7 +35,8 @@
 #endif
 
 #include "devicetracker.h"
-#include <gdkmm/device.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
 #include <synfigapp/main.h>
 
 #include "general.h"
@@ -42,6 +48,7 @@
 using namespace std;
 using namespace etl;
 using namespace synfig;
+using namespace synfigapp;
 using namespace studio;
 
 /* === M A C R O S ========================================================= */
@@ -54,23 +61,19 @@ using namespace studio;
 
 DeviceTracker::DeviceTracker()
 {
-       // FIXME: We no longer do this, but we should figure out why this was being done
-       // By default, set the input mode on devices to
-       // GDK_MODE_SCREEN.
+       GList*  device_list;
+       GList*  iter;
+       device_list=gdk_devices_list();
+
+       for(iter=device_list;iter;iter=g_list_next(iter))
        {
-               GList*  device_list;
-               GList*  iter;
-               device_list=gdk_devices_list();
-
-               for(iter=device_list;iter;iter=g_list_next(iter))
-               {
-                       GdkDevice* device=reinterpret_cast<GdkDevice*>(iter->data);
-                       //gdk_device_set_mode(device,GDK_MODE_SCREEN);
-
-                       synfigapp::InputDevice::Handle input_device;
-                       input_device=synfigapp::Main::add_input_device(device->name,synfigapp::InputDevice::Type(device->source));
-                       if(input_device->get_type()==synfigapp::InputDevice::TYPE_MOUSE)
-                               synfigapp::Main::select_input_device(input_device);
+               GdkDevice* device=reinterpret_cast<GdkDevice*>(iter->data);
+
+               synfigapp::InputDevice::Handle input_device;
+               input_device=synfigapp::Main::add_input_device(device->name,synfigapp::InputDevice::Type(device->source));
+               if(input_device->get_type()==synfigapp::InputDevice::TYPE_MOUSE) {
+                       input_device->set_mode(synfigapp::InputDevice::MODE_SCREEN);
+                       synfigapp::Main::select_input_device(input_device);
                }
        }
 }
@@ -78,3 +81,77 @@ DeviceTracker::DeviceTracker()
 DeviceTracker::~DeviceTracker()
 {
 }
+
+void
+DeviceTracker::save_preferences()
+{
+       GList * device_list = gdk_devices_list();
+       for (GList * itr = device_list; itr; itr = g_list_next(itr))
+       {
+               GdkDevice * gdk_device = reinterpret_cast<GdkDevice*>(itr->data);
+
+               InputDevice::Handle synfig_device = synfigapp::Main::find_input_device(gdk_device->name);
+               if (synfig_device == NULL)
+                       continue;
+
+               synfig_device->set_mode(InputDevice::Mode(gdk_device->mode));
+               if (gdk_device->num_axes > 0) {
+                       vector<synfigapp::InputDevice::AxisUse> axes;
+                       axes.resize(gdk_device->num_axes);
+                       for (int i = 0; i < gdk_device->num_axes; i++)
+                               axes[i] = InputDevice::AxisUse(gdk_device->axes[i].use);
+                       synfig_device->set_axes(axes);
+               }
+
+               if (gdk_device->num_keys > 0) {
+                       vector<synfigapp::InputDevice::DeviceKey> keys;
+                       keys.resize(gdk_device->num_keys);
+                       for (int i = 0; i < gdk_device->num_keys; i++) {
+                               keys[i].keyval = gdk_device->keys[i].keyval;
+                               keys[i].modifiers = gdk_device->keys[i].modifiers;
+                       }
+                       synfig_device->set_keys(keys);
+               }
+       }
+}
+
+void
+DeviceTracker::set_device_mode(const synfig::String & id,
+               InputDevice::Mode mode)
+{
+       for (GList * itr = gdk_devices_list(); itr; itr = g_list_next(itr))
+       {
+               GdkDevice * device = reinterpret_cast<GdkDevice*>(itr->data);
+               if (id == device->name)
+                       gdk_device_set_mode(device, GdkInputMode(mode));
+       }
+}
+
+void
+DeviceTracker::set_device_axes(const synfig::String & id,
+               const std::vector<synfigapp::InputDevice::AxisUse> axes)
+{
+       for (GList * itr = gdk_devices_list(); itr; itr = g_list_next(itr))
+       {
+               GdkDevice * device = reinterpret_cast<GdkDevice*>(itr->data);
+               if (id == device->name) {
+                       for (int axis = 0; axis < (int) axes.size(); axis++)
+                               gdk_device_set_axis_use(device, axis, GdkAxisUse(axes[axis]));
+               }
+       }
+}
+
+void
+DeviceTracker::set_device_keys(const synfig::String & id,
+               const std::vector<synfigapp::InputDevice::DeviceKey> keys)
+{
+       for (GList * itr = gdk_devices_list(); itr; itr = g_list_next(itr))
+       {
+               GdkDevice * device = reinterpret_cast<GdkDevice*>(itr->data);
+               if (id == device->name) {
+                       for (int key = 0; key < (int) keys.size(); key++)
+                               gdk_device_set_key(device, key, keys[key].keyval,
+                                               GdkModifierType(keys[key].modifiers));
+               }
+       }
+}
index 5113e26..c3608de 100644 (file)
@@ -27,6 +27,9 @@
 
 /* === H E A D E R S ======================================================= */
 
+#include <synfig/string.h>
+#include <synfigapp/inputdevice.h>
+
 /* === M A C R O S ========================================================= */
 
 /* === T Y P E D E F S ===================================================== */
@@ -41,7 +44,15 @@ public:
        DeviceTracker();
        ~DeviceTracker();
 
-}; // END of class ToolTracker
+       void save_preferences();
+
+       static void set_device_mode(const synfig::String & id,
+                       synfigapp::InputDevice::Mode mode);
+       static void set_device_axes(const synfig::String & id,
+                       const std::vector<synfigapp::InputDevice::AxisUse> axes);
+       static void set_device_keys(const synfig::String & id,
+                       const std::vector<synfigapp::InputDevice::DeviceKey> keys);
+}; // END of class DeviceTracker
 
 }; // END of namespace studio
 
index f575469..110f0cd 100644 (file)
@@ -34,6 +34,7 @@
 #include <cstdio>
 #include <ETL/stringf>
 #include "main.h"
+#include <gtkmm/devicetracker.h>
 
 #include "general.h"
 
@@ -45,6 +46,7 @@ using namespace std;
 using namespace etl;
 using namespace synfig;
 using namespace synfigapp;
+using namespace studio;
 
 /* === M A C R O S ========================================================= */
 
@@ -94,10 +96,53 @@ public:
 
                        return true;
                }
+               if(key=="mode")
+               {
+                       get_mode_value(value);
+                       return true;
+               }
+               if(key=="axes")
+               {
+                       get_axes_value(value);
+                       return true;
+               }
+               if(key=="keys")
+               {
+                       get_keys_value(value);
+                       return true;
+               }
 
                return Settings::get_value(key, value);
        }
 
+       void get_mode_value(synfig::String & value) const
+       {
+               if (input_device->get_mode() == InputDevice::MODE_SCREEN)
+                       value = "screen";
+               else if (input_device->get_mode() == InputDevice::MODE_WINDOW)
+                       value = "window";
+               else
+                       value = "disabled";
+       }
+
+       void get_axes_value(synfig::String & value) const
+       {
+               vector<InputDevice::AxisUse> axes = input_device->get_axes();
+               value = strprintf("%u", axes.size());
+               vector<InputDevice::AxisUse>::const_iterator itr;
+               for (itr = axes.begin(); itr != axes.end(); itr++)
+                       value += strprintf(" %u", (unsigned int) *itr);
+       }
+
+       void get_keys_value(synfig::String & value) const
+       {
+               vector<InputDevice::DeviceKey> keys = input_device->get_keys();
+               value = strprintf("%u", keys.size());
+               vector<InputDevice::DeviceKey>::const_iterator itr;
+               for (itr = keys.begin(); itr != keys.end(); itr++)
+                       value += strprintf(" %u %u", itr->keyval, itr->modifiers);
+       }
+
        virtual bool set_value(const synfig::String& key,const synfig::String& value)
        {
                if(key=="state")
@@ -136,10 +181,82 @@ public:
                        input_device->set_background_color(synfig::Color(r,g,b,a));
                        return true;
                }
+               if(key=="mode")
+               {
+                       set_mode_value(value);
+                       return true;
+               }
+               if(key=="axes")
+               {
+                       set_axes_value(value);
+                       return true;
+               }
+               if(key=="keys")
+               {
+                       set_keys_value(value);
+                       return true;
+               }
 
                return Settings::set_value(key, value);
        }
 
+       void set_mode_value(const synfig::String & value)
+       {
+               InputDevice::Mode mode;
+               if (value == "screen")
+                       mode = InputDevice::MODE_SCREEN;
+               else if (value == "window")
+                       mode = InputDevice::MODE_WINDOW;
+               else
+                       mode = InputDevice::MODE_DISABLED;
+
+               input_device->set_mode(mode);
+               DeviceTracker::set_device_mode(input_device->get_id(), mode);
+       }
+
+       void set_axes_value(const synfig::String & value)
+       {
+               std::vector<InputDevice::AxisUse> axes;
+
+               unsigned pos = value.find(' ', 0);
+               if (pos < value.size()) {
+                       int num_axes = atoi(value.substr(0, pos).c_str());
+                       axes.resize(num_axes);
+
+                       for (int axis = 0; axis < num_axes; axis++) {
+                               int last = pos;
+                               pos = value.find(' ', pos + 1);
+                               axes[axis] = InputDevice::AxisUse(atoi(value.substr(last, pos).c_str()));
+                       }
+               }
+
+               input_device->set_axes(axes);
+               DeviceTracker::set_device_axes(input_device->get_id(), axes);
+       }
+
+       void set_keys_value(const synfig::String & value)
+       {
+               std::vector<InputDevice::DeviceKey> keys;
+
+               unsigned pos = value.find(' ', 0);
+               if (pos < value.size()) {
+                       int num_keys = atoi(value.substr(0, pos).c_str());
+                       keys.resize(num_keys);
+
+                       for (int key = 0; key < num_keys; key++) {
+                               int last = pos;
+                               pos = value.find(' ', pos + 1);
+                               keys[key].keyval = (unsigned int) atol(value.substr(last, pos).c_str());
+                               last = pos;
+                               pos = value.find(' ', pos + 1);
+                               keys[key].modifiers = (unsigned int) atol(value.substr(last, pos).c_str());
+                       }
+               }
+
+               input_device->set_keys(keys);
+               DeviceTracker::set_device_keys(input_device->get_id(), keys);
+       }
+
        virtual KeyList get_key_list()const
        {
                KeyList ret(Settings::get_key_list());
@@ -149,6 +266,9 @@ public:
                ret.push_back("bline_width");
                ret.push_back("blend_method");
                ret.push_back("opacity");
+               ret.push_back("mode");
+               ret.push_back("axes");
+               ret.push_back("keys");
                return ret;
        }
 };
@@ -165,7 +285,8 @@ InputDevice::InputDevice(const synfig::String id_, Type type_):
        background_color_(Color::white()),
        bline_width_(Distance(1,Distance::SYSTEM_POINTS)),
        opacity_(1.0f),
-       blend_method_(Color::BLEND_COMPOSITE)
+       blend_method_(Color::BLEND_COMPOSITE),
+       mode_(MODE_DISABLED)
 {
        device_settings=new DeviceSettings(this);
        Main::settings().add_domain(device_settings,"input_device."+id_);
index 2ea0e10..e8c41a1 100644 (file)
@@ -27,6 +27,7 @@
 
 /* === H E A D E R S ======================================================= */
 
+#include <vector>
 #include <synfig/color.h>
 #include <synfig/vector.h>
 #include <synfig/distance.h>
@@ -45,6 +46,16 @@ namespace synfigapp {
 class Settings;
 
 
+/*!    \class  InputDevice  inputdevice.h  "synfigapp/inputdevice.h"
+**     \brief  This class provides a device independent representation the state
+**             of an input device.
+**  \see  studio::DeviceTracker
+**  \see  synfigapp::Settings
+**
+**   The represenation includes both the GDK state (e.g., mode) and synfigstudio
+**   state (e.g., foreground color). An object of this class can be saved and
+**   restored using its Settings object, provided by the settings method.
+*/
 class InputDevice : public etl::shared_object
 {
 public:
@@ -56,6 +67,31 @@ public:
                TYPE_CURSOR
        };
 
+       enum Mode
+       {
+               MODE_DISABLED,
+               MODE_SCREEN,
+               MODE_WINDOW
+       };
+
+       enum AxisUse
+       {
+         AXIS_IGNORE,
+         AXIS_X,
+         AXIS_Y,
+         AXIS_PRESSURE,
+         AXIS_XTILT,
+         AXIS_YTILT,
+         AXIS_WHEEL,
+         AXIS_LAST
+       };
+
+       struct DeviceKey
+       {
+         unsigned int keyval;
+         unsigned int modifiers;
+       };
+
        typedef etl::handle<InputDevice> Handle;
 
 private:
@@ -67,6 +103,9 @@ private:
        synfig::Distance        bline_width_;
        synfig::Real opacity_;
        synfig::Color::BlendMethod blend_method_;
+       Mode mode_;
+       std::vector<AxisUse> axes_;
+       std::vector<DeviceKey> keys_;
 
        DeviceSettings* device_settings;
 
@@ -82,6 +121,9 @@ public:
        const synfig::Real& get_opacity()const { return opacity_; }
        const synfig::Color::BlendMethod& get_blend_method()const { return blend_method_; }
        Type get_type()const { return type_; }
+       Mode get_mode()const { return mode_; }
+       const std::vector<AxisUse> & get_axes()const { return axes_; }
+       const std::vector<DeviceKey> & get_keys()const { return keys_; }
 
        void set_state(const synfig::String& x) { state_=x; }
        void set_foreground_color(const synfig::Color& x) { foreground_color_=x; }
@@ -90,6 +132,9 @@ public:
        void set_blend_method(const synfig::Color::BlendMethod& x) { blend_method_=x; }
        void set_opacity(const synfig::Real& x) { opacity_=x; }
        void set_type(Type x) { type_=x; }
+       void set_mode(Mode x) { mode_=x; }
+       void set_axes(const std::vector<AxisUse>& x) { axes_=x; }
+       void set_keys(const std::vector<DeviceKey>& x) { keys_=x; }
 
        Settings& settings();
        const Settings& settings()const;