← easystroke

Reenable proximity for supported devices

f73ac6f9dca9fb6170972bfb15bed6c1b1484a39 · Thomas Jaeger · Sep 23, 2012 14:19

I'm not aware of any drivers that support this as of now

+49 −19 · 6 files changed

  • grabber.cc +4 −2
  • grabber.h +1 −0
  • gui.glade +1 −2
  • main.cc +37 −12
  • prefs.cc +5 −3
  • prefs.h +1 −0
diff --git a/grabber.cc b/grabber.cc
index 4dcb4de..6b19c9c 100644
--- a/grabber.cc
+++ b/grabber.cc
@@ -277,7 +277,6 @@ bool Grabber::init_xi() {
 		exit(EXIT_FAILURE);
 	}
 
-	// TODO: Proximity
 	device_mask.deviceid = XIAllDevices;
 	device_mask.mask = device_mask_data;
 	device_mask.mask_len = sizeof(device_mask_data);
@@ -371,7 +370,8 @@ void Grabber::new_device(XIDeviceInfo *info) {
 		}
 }
 
-Grabber::XiDevice::XiDevice(Grabber *parent, XIDeviceInfo *info) : absolute(false), scale_x(1.0), scale_y(1.0), num_buttons(0) {
+Grabber::XiDevice::XiDevice(Grabber *parent, XIDeviceInfo *info) : absolute(false), proximity_axis(-1), scale_x(1.0), scale_y(1.0), num_buttons(0) {
+	static XAtom PROXIMITY(AXIS_LABEL_PROP_ABS_DISTANCE);
 	dev = info->deviceid;
 	name = info->name;
 	master = info->attachment;
@@ -390,6 +390,8 @@ Grabber::XiDevice::XiDevice(Grabber *parent, XIDeviceInfo *info) : absolute(fals
 					scale_y = (double)DisplayHeight(dpy, DefaultScreen(dpy)) / (double)(v->max - v->min);
 
 			}
+			if (v->label == *PROXIMITY)
+				proximity_axis = v->number;
 		}
 	}
 
diff --git a/grabber.h b/grabber.h
index 76ad60b..c187878 100644
--- a/grabber.h
+++ b/grabber.h
@@ -69,6 +69,7 @@ public:
 		std::string name;
 		bool absolute;
 		bool active;
+		int proximity_axis;
 		double scale_x, scale_y;
 		int num_buttons;
 		int master;
diff --git a/gui.glade b/gui.glade
index 704bca4..ac1c552 100644
--- a/gui.glade
+++ b/gui.glade
@@ -1766,8 +1766,7 @@ Van Diep Duong (Vietnamese)</property>
               </packing>
             </child>
             <child>
-              <object class="GtkFrame" id="frame_advanced2">
-                <property name="visible">True</property>
+              <object class="GtkFrame" id="frame_tablet">
                 <property name="can_focus">False</property>
                 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                 <property name="label_xalign">0</property>
diff --git a/main.cc b/main.cc
index fed010b..fac5619 100644
--- a/main.cc
+++ b/main.cc
@@ -135,7 +135,6 @@ public:
 	virtual void press(guint b, RTriple e) {}
 	virtual void release(guint b, RTriple e) {}
 	virtual void press_master(guint b, Time t) {}
-	virtual void proximity_out() {}
 	virtual void pong() {}
 	void replace_child(Handler *c) {
 		if (child)
@@ -214,8 +213,9 @@ std::list<OSD *> OSD::osd_stack;
 
 class IgnoreHandler : public Handler {
 	RModifiers mods;
+	bool proximity;
 public:
-	IgnoreHandler(RModifiers mods_) : mods(mods_) {}
+	IgnoreHandler(RModifiers mods_) : mods(mods_), proximity(in_proximity && prefs.proximity.get()) {}
 	virtual void press(guint b, RTriple e) {
 		if (current_dev->master) {
 			XTestFakeMotionEvent(dpy, DefaultScreen(dpy), e->x, e->y, 0);
@@ -225,14 +225,15 @@ public:
 	virtual void motion(RTriple e) {
 		if (current_dev->master)
 			XTestFakeMotionEvent(dpy, DefaultScreen(dpy), e->x, e->y, 0);
+		if (proximity && !in_proximity)
+			parent->replace_child(NULL);
 	}
-	// TODO: Handle Proximity
 	virtual void release(guint b, RTriple e) {
 		if (current_dev->master) {
 			XTestFakeMotionEvent(dpy, DefaultScreen(dpy), e->x, e->y, 0);
 			XTestFakeButtonEvent(dpy, b, false, CurrentTime);
 		}
-		if (!xinput_pressed.size())
+		if (proximity ? !in_proximity : !xinput_pressed.size())
 			parent->replace_child(NULL);
 	}
 	virtual std::string name() { return "Ignore"; }
@@ -242,8 +243,14 @@ public:
 class ButtonHandler : public Handler {
 	RModifiers mods;
 	guint button, real_button;
+	bool proximity;
 public:
-	ButtonHandler(RModifiers mods_, guint button_) : mods(mods_), button(button_), real_button(0) {}
+	ButtonHandler(RModifiers mods_, guint button_) :
+		mods(mods_),
+		button(button_),
+		real_button(0),
+		proximity(in_proximity && prefs.proximity.get())
+	{}
 	virtual void press(guint b, RTriple e) {
 		if (current_dev->master) {
 			if (!real_button)
@@ -257,8 +264,9 @@ public:
 	virtual void motion(RTriple e) {
 		if (current_dev->master)
 			XTestFakeMotionEvent(dpy, DefaultScreen(dpy), e->x, e->y, 0);
+		if (proximity && !in_proximity)
+			parent->replace_child(NULL);
 	}
-	// TODO: Handle Proximity
 	virtual void release(guint b, RTriple e) {
 		if (current_dev->master) {
 			if (real_button == b)
@@ -266,7 +274,7 @@ public:
 			XTestFakeMotionEvent(dpy, DefaultScreen(dpy), e->x, e->y, 0);
 			XTestFakeButtonEvent(dpy, b, false, CurrentTime);
 		}
-		if (!xinput_pressed.size())
+		if (proximity ? !in_proximity : !xinput_pressed.size())
 			parent->replace_child(NULL);
 	}
 	virtual std::string name() { return "Button"; }
@@ -453,12 +461,18 @@ class ScrollHandler : public AbstractScrollHandler {
 	RModifiers mods;
 	std::map<guint, guint> map;
 	int orig_x, orig_y;
+	bool proximity;
 public:
 	ScrollHandler(RModifiers mods_) : mods(mods_) {
 		// If you want to use buttons > 9, you're on your own..
 		map[1] = 0; map[2] = 0; map[3] = 0; map[8] = 0; map[9] = 0;
+		proximity = in_proximity && prefs.proximity.get();
 	}
 	virtual void raw_motion(RTriple e, bool abs_x, bool abs_y) {
+		if (proximity && !in_proximity) {
+			parent->replace_child(NULL);
+			move_back();
+		}
 		if (xinput_pressed.size())
 			AbstractScrollHandler::raw_motion(e, abs_x, abs_y);
 	}
@@ -466,15 +480,11 @@ public:
 		fake_core_button(b, false);
 	}
 	virtual void release(guint b, RTriple e) {
-		if (in_proximity || xinput_pressed.size())
+		if ((proximity && in_proximity) || xinput_pressed.size())
 			return;
 		parent->replace_child(0);
 		move_back();
 	}
-	virtual void proximity_out() {
-		parent->replace_child(0);
-		move_back();
-	}
 	virtual std::string name() { return "Scroll"; }
 	virtual Grabber::State grab_mode() { return Grabber::RAW; }
 };
@@ -1467,6 +1477,16 @@ static void print_coordinates(XIValuatorState *valuators, double *values) {
 	}
 }
 
+static double get_axis(XIValuatorState &valuators, int axis) {
+	if (axis < 0 || !XIMaskIsSet(valuators.mask, axis))
+		return 0.0;
+	double *val = valuators.values;
+	for (int i = 0; i < axis; i++)
+		if (XIMaskIsSet(valuators.mask, i))
+			val++;
+	return *val;
+}
+
 void App::report_xi2_event(XIDeviceEvent *event, const char *type) {
 	printf("%s (XI2): ", type);
 	if (event->detail)
@@ -1504,6 +1524,7 @@ void App::handle_xi2_event(XIDeviceEvent *event) {
 					modifiers = event->mods.base;
 			}
 			xinput_pressed.insert(event->detail);
+			in_proximity = get_axis(event->valuators, current_dev->proximity_axis);
 			H->press(event->detail, create_triple(event->root_x, event->root_y, event->time));
 			break;
 		case XI_ButtonRelease:
@@ -1512,6 +1533,7 @@ void App::handle_xi2_event(XIDeviceEvent *event) {
 			if (!current_dev || current_dev->dev != event->deviceid)
 				break;
 			xinput_pressed.erase(event->detail);
+			in_proximity = get_axis(event->valuators, current_dev->proximity_axis);
 			H->release(event->detail, create_triple(event->root_x, event->root_y, event->time));
 			break;
 		case XI_Motion:
@@ -1522,6 +1544,9 @@ void App::handle_xi2_event(XIDeviceEvent *event) {
 			H->motion(create_triple(event->root_x, event->root_y, event->time));
 			break;
 		case XI_RawMotion:
+			if (!current_dev)
+				break;
+			in_proximity = get_axis(((XIRawEvent *)event)->valuators, current_dev->proximity_axis);
 			handle_raw_motion((XIRawEvent *)event);
 			break;
 		case XI_HierarchyChanged:
diff --git a/prefs.cc b/prefs.cc
index 9928d1c..14ed52e 100644
--- a/prefs.cc
+++ b/prefs.cc
@@ -281,6 +281,7 @@ Prefs::Prefs() {
 	widgets->get_widget("treeview_exceptions", tv);
 	widgets->get_widget("treeview_devices", dtv);
 	widgets->get_widget("treeview_extra", etv);
+	widgets->get_widget("frame_tablet", frame_tablet);
 
 	new Sensitive(*fun(&is_custom, prefs.timeout_profile), "hbox_timeout");
 	new Sensitive(*fun(&draw_trace, prefs.trace), "button_color");
@@ -348,9 +349,6 @@ Prefs::Prefs() {
 		widgets->get_widget("hbox_timeout", hbox);
 		hbox->hide();
 	}
-	Gtk::Frame *tablet_frame;
-	widgets->get_widget("frame_advanced2", tablet_frame);
-	tablet_frame->hide();
 
 	set_button_label();
 
@@ -364,10 +362,13 @@ Prefs::Prefs() {
 }
 
 void Prefs::update_device_list() {
+	bool proximity = false;
 	ignore_device_toggled = true;
 	dtm->clear();
 	std::set<std::string> names;
 	for (Grabber::DeviceMap::iterator i = grabber->xi_devs.begin(); i != grabber->xi_devs.end(); ++i) {
+		if (i->second->proximity_axis >= 0)
+			proximity = true;
 		std::string name = i->second->name;
 		if (names.count(name))
 			continue;
@@ -385,6 +386,7 @@ void Prefs::update_device_list() {
 					row[dcs.timeout] = i->name;
 	}
 	ignore_device_toggled = false;
+	frame_tablet->set_visible(proximity);
 }
 
 void Prefs::update_extra_buttons() {
diff --git a/prefs.h b/prefs.h
index c76cc47..40b5905 100644
--- a/prefs.h
+++ b/prefs.h
@@ -79,6 +79,7 @@ private:
 
 	Gtk::SpinButton *spin_radius;
 	Gtk::Label* blabel;
+	Gtk::Frame *frame_tablet;
 	bool ignore_device_toggled;
 };