Allow different timeout settings for individual devices
+105 −49 · 5 files changed
-
main.cc+39 −2 -
prefdb.cc+2 −42 -
prefdb.h+4 −3 -
prefs.cc+50 −1 -
prefs.h+10 −1
@@ -752,6 +752,36 @@ void Trace::end() { end_(); } +static void get_timeouts(TimeoutType type, int *init, int *final) { + switch (type) { + case TimeoutOff: + *init = 0; + *final = 0; + break; + case TimeoutConservative: + *init = 750; + *final = 750; + break; + case TimeoutDefault: + *init = 250; + *final = 250; + break; + case TimeoutMedium: + *init = 100; + *final = 100; + break; + case TimeoutAggressive: + *init = 50; + *final = 75; + break; + case TimeoutFlick: + *init = 30; + *final = 50; + break; + default:; + } +} + class StrokeHandler : public Handler, public sigc::trackable { guint button; RPreStroke cur; @@ -905,8 +935,15 @@ protected: } public: StrokeHandler(guint b, RTriple e) : button(b), is_gesture(false), drawing(false), last(e), orig(e), - use_timeout(prefs.init_timeout.get()), - init_timeout(prefs.init_timeout.get()), final_timeout(prefs.final_timeout.get()), radius(16) {} + init_timeout(prefs.init_timeout.get()), final_timeout(prefs.final_timeout.get()), radius(16) { + const std::map<std::string, TimeoutType> &dt = prefs.device_timeout.ref(); + std::map<std::string, TimeoutType>::const_iterator j = dt.find(current_dev->name); + if (j != dt.end()) + get_timeouts(j->second, &init_timeout, &final_timeout); + else + get_timeouts(prefs.timeout_profile.get(), &init_timeout, &final_timeout); + use_timeout = init_timeout; + } virtual void init() { if (grabber->is_instant(button)) return do_instant(); @@ -131,6 +131,8 @@ template<class Archive> void PrefDB::serialize(Archive & ar, const unsigned int ar & show_osd.unsafe_ref(); if (version < 16) return; ar & move_back.unsafe_ref(); + if (version < 17) return; + ar & device_timeout.unsafe_ref(); } void PrefDB::timeout() { @@ -167,45 +169,6 @@ bool ButtonInfo::overlap(const ButtonInfo &bi) const { return !((state ^ bi.state) & ~LockMask & ~Mod2Mask); } -class TimeoutProfile : private Base { - Out<TimeoutType> ∈ -public: - virtual void notify() { - switch (in.get()) { - case TimeoutOff: - prefs.init_timeout.set(0); - prefs.final_timeout.set(0); - break; - case TimeoutConservative: - prefs.init_timeout.set(750); - prefs.final_timeout.set(750); - break; - case TimeoutDefault: - prefs.init_timeout.set(250); - prefs.final_timeout.set(250); - break; - case TimeoutMedium: - prefs.init_timeout.set(100); - prefs.final_timeout.set(100); - break; - case TimeoutAggressive: - prefs.init_timeout.set(50); - prefs.final_timeout.set(75); - break; - case TimeoutFlick: - prefs.init_timeout.set(30); - prefs.final_timeout.set(50); - break; - case TimeoutCustom: - break; - } - } - TimeoutProfile(Out<TimeoutType> &in_) : in(in_) { - in.connect(this); - notify(); - } -}; - void PrefDB::init() { std::string filename = config_dir+"preferences"; for (const char **v = prefs_versions; *v; v++) { @@ -231,9 +194,6 @@ void PrefDB::init() { exceptions.unsafe_ref().erase(i); exceptions.unsafe_ref()[""] = bi; } - new TimeoutProfile(timeout_profile); - watch(init_timeout); - watch(final_timeout); } PrefDB prefs; @@ -119,8 +119,8 @@ public: PrefSource<bool> proximity; PrefSource<bool> feedback; PrefSource<bool> left_handed; - Source<int> init_timeout; - Source<int> final_timeout; + PrefSource<int> init_timeout; + PrefSource<int> final_timeout; PrefSource<TimeoutType> timeout_profile; PrefSource<bool> timeout_gestures; PrefSource<bool> tray_icon; @@ -134,12 +134,13 @@ public: PrefSource<bool> tray_feedback; PrefSource<bool> show_osd; PrefSource<bool> move_back; + PrefSource<std::map<std::string, TimeoutType> > device_timeout; void init(); virtual void timeout(); }; -BOOST_CLASS_VERSION(PrefDB, 16) +BOOST_CLASS_VERSION(PrefDB, 17) extern PrefDB prefs; @@ -314,7 +314,30 @@ Prefs::Prefs() { dtm = Gtk::ListStore::create(dcs); dtv->set_model(dtm); dtv->append_column_editable(_("Enabled"), dcs.enabled); - dtv->append_column(_("Device"), dcs.name); + int n = dtv->append_column(_("Device"), dcs.name); + Gtk::TreeView::Column *col_device = dtv->get_column(n-1); + col_device->set_expand(); + + Glib::RefPtr<Gtk::ListStore> timeout_model = Gtk::ListStore::create(timeout_columns); + { + Gtk::TreeModel::Row row = *(timeout_model->append()); + row[timeout_columns.name] = _("<unchanged>"); + } + for (const Combo<TimeoutType>::Info *i = timeout_info; i->name; i++) { + Gtk::TreeModel::Row row = *(timeout_model->append()); + row[timeout_columns.name] = i->name; + } + + Gtk::CellRendererCombo *timeout_renderer = Gtk::manage(new Gtk::CellRendererCombo); + timeout_renderer->property_model() = timeout_model; + timeout_renderer->property_editable() = true; + timeout_renderer->property_text_column() = 0; + timeout_renderer->property_has_entry() = false; + timeout_renderer->signal_edited().connect(sigc::mem_fun(*this, &Prefs::on_device_timeout_changed)); + n = dtv->append_column(_("Timeout profile"), *timeout_renderer); + Gtk::TreeView::Column *col_timeout = dtv->get_column(n-1); + col_timeout->add_attribute(timeout_renderer->property_text(), dcs.timeout); + dtm->signal_row_changed().connect(sigc::mem_fun(*this, &Prefs::on_device_toggled)); update_device_list(); @@ -355,6 +378,14 @@ void Prefs::update_device_list() { Gtk::TreeModel::Row row = *(dtm->append()); row[dcs.enabled] = !prefs.excluded_devices.get().count(name); row[dcs.name] = name; + row[dcs.timeout] = _("<unchanged>"); + + const std::map<std::string, TimeoutType> &dt = prefs.device_timeout.ref(); + std::map<std::string, TimeoutType>::const_iterator j = dt.find(name); + if (j != dt.end()) + for (const Combo<TimeoutType>::Info *i = timeout_info; i->name; i++) + if (j->second == i->value) + row[dcs.timeout] = i->name; } ignore_device_toggled = false; } @@ -645,6 +676,24 @@ void Prefs::on_device_toggled(const Gtk::TreeModel::Path& path, const Gtk::TreeM ex.insert(device); } +void Prefs::on_device_timeout_changed(const Glib::ustring& path, const Glib::ustring& new_text) { + Gtk::TreeRow row(*dtm->get_iter(path)); + row[dcs.timeout] = new_text; + Glib::ustring device = row[dcs.name]; + Atomic a; + + for (const Combo<TimeoutType>::Info *i = timeout_info; i->name; i++) { + if (Glib::ustring(i->name) == new_text) { + std::map<std::string, TimeoutType> &dt = prefs.device_timeout.write_ref(a); + dt[device] = i->value; + return; + } + } + + std::map<std::string, TimeoutType> &dt = prefs.device_timeout.write_ref(a); + dt.erase(device); +} + void Prefs::set_button_label() { blabel->set_text(prefs.button.ref().get_button_text()); } @@ -36,6 +36,7 @@ private: void on_select_button(); void on_button_editing_started(Gtk::CellEditable* editable, const Glib::ustring& path); void on_device_toggled(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter); + void on_device_timeout_changed(const Glib::ustring& path, const Glib::ustring& new_text); bool select_row(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, std::string name); class ExceptionColumns : public Gtk::TreeModel::ColumnRecord { @@ -48,11 +49,19 @@ private: Glib::RefPtr<Gtk::ListStore> tm; Gtk::TreeView* tv; + class Single : public Gtk::TreeModel::ColumnRecord { + public: + Single() { add(name); } + Gtk::TreeModelColumn<Glib::ustring> name; + }; + Single timeout_columns; + class DeviceColumns : public Gtk::TreeModel::ColumnRecord { public: - DeviceColumns() { add(enabled); add(name); } + DeviceColumns() { add(enabled); add(name); add(timeout); } Gtk::TreeModelColumn<bool> enabled; Gtk::TreeModelColumn<Glib::ustring> name; + Gtk::TreeModelColumn<Glib::ustring> timeout; }; DeviceColumns dcs; Gtk::TreeView* dtv;