1 /***************************************************************************
4 * Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 **************************************************************************/
26 #define MAX_INT_VALUES 4
27 #define MAX_FLOAT_VALUES 4
29 #define VALID_BUTTON(x) (x >= 0 && x <= 32)
30 #define VALID_BOOL(x) (x == 0 || x == 1)
31 #define VALID_PCNT(x) (x >= 0 && x <= 100)
35 Atom atom_init_integer(DeviceIntPtr dev, char* name, int nvalues, int* values, int size) {
38 uint8_t uvals8[MAX_INT_VALUES];
39 uint16_t uvals16[MAX_INT_VALUES];
40 uint32_t uvals32[MAX_INT_VALUES];
42 nvalues = MINVAL(MAX_INT_VALUES, nvalues);
46 for (i = 0; i < nvalues; i++) {
47 uvals8[i] = values[i];
52 for (i = 0; i < nvalues; i++) {
53 uvals16[i] = values[i];
58 for (i = 0; i < nvalues; i++) {
59 uvals32[i] = values[i];
65 atom = MakeAtom(name, strlen(name), TRUE);
66 XIChangeDeviceProperty(dev, atom, XA_INTEGER, size, PropModeReplace, nvalues, uvals, FALSE);
67 XISetDevicePropertyDeletable(dev, atom, FALSE);
71 Atom atom_init_float(DeviceIntPtr dev, char* name, int nvalues, float* values, Atom float_type) {
72 Atom atom = MakeAtom(name, strlen(name), TRUE);
73 XIChangeDeviceProperty(dev, atom, float_type, 32, PropModeReplace, nvalues, values, FALSE);
74 XISetDevicePropertyDeletable(dev, atom, FALSE);
78 void mprops_init(struct MConfig* cfg, InputInfoPtr local) {
79 int ivals[MAX_INT_VALUES];
80 float fvals[MAX_FLOAT_VALUES];
82 mprops.float_type = XIGetKnownProperty(XATOM_FLOAT);
83 if (!mprops.float_type) {
84 mprops.float_type = MakeAtom(XATOM_FLOAT, strlen(XATOM_FLOAT), TRUE);
85 if (!mprops.float_type) {
86 xf86Msg(X_ERROR, "mtrack: %s: Failed to init float atom. Property support is disabled.\n", local->name);
91 ivals[0] = cfg->trackpad_disable;
92 mprops.trackpad_disable = atom_init_integer(local->dev, MTRACK_PROP_TRACKPAD_DISABLE, 1, ivals, 8);
94 fvals[0] = (float)cfg->sensitivity;
95 mprops.sensitivity = atom_init_float(local->dev, MTRACK_PROP_SENSITIVITY, 1, fvals, mprops.float_type);
97 ivals[0] = cfg->touch_down;
98 ivals[1] = cfg->touch_up;
99 mprops.pressure = atom_init_integer(local->dev, MTRACK_PROP_PRESSURE, 2, ivals, 8);
101 ivals[0] = cfg->button_enable;
102 ivals[1] = cfg->button_integrated;
103 mprops.button_settings = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_SETTINGS, 2, ivals, 8);
105 ivals[0] = cfg->button_zones;
106 ivals[1] = cfg->button_move;
107 ivals[2] = cfg->button_expire;
108 mprops.button_emulate_settings = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_SETTINGS, 3, ivals, 16);
110 ivals[0] = cfg->button_1touch;
111 ivals[1] = cfg->button_2touch;
112 ivals[2] = cfg->button_3touch;
113 mprops.button_emulate_values = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_VALUES, 3, ivals, 8);
115 ivals[0] = cfg->tap_hold;
116 ivals[1] = cfg->tap_timeout;
117 ivals[2] = cfg->tap_dist;
118 mprops.tap_settings = atom_init_integer(local->dev, MTRACK_PROP_TAP_SETTINGS, 3, ivals, 32);
120 ivals[0] = cfg->tap_1touch;
121 ivals[1] = cfg->tap_2touch;
122 ivals[2] = cfg->tap_3touch;
123 ivals[3] = cfg->tap_4touch;
124 mprops.tap_emulate = atom_init_integer(local->dev, MTRACK_PROP_TAP_EMULATE, 4, ivals, 8);
126 ivals[0] = cfg->ignore_thumb;
127 ivals[1] = cfg->disable_on_thumb;
128 mprops.thumb_detect = atom_init_integer(local->dev, MTRACK_PROP_THUMB_DETECT, 2, ivals, 8);
130 ivals[0] = cfg->thumb_size;
131 ivals[1] = cfg->thumb_ratio;
132 mprops.thumb_size = atom_init_integer(local->dev, MTRACK_PROP_THUMB_SIZE, 2, ivals, 32);
134 ivals[0] = cfg->ignore_palm;
135 ivals[1] = cfg->disable_on_palm;
136 mprops.palm_detect = atom_init_integer(local->dev, MTRACK_PROP_PALM_DETECT, 2, ivals, 8);
138 ivals[0] = cfg->palm_size;
139 mprops.palm_size = atom_init_integer(local->dev, MTRACK_PROP_PALM_SIZE, 1, ivals, 32);
141 ivals[0] = cfg->gesture_hold;
142 ivals[1] = cfg->gesture_wait;
143 mprops.gesture_settings = atom_init_integer(local->dev, MTRACK_PROP_GESTURE_SETTINGS, 2, ivals, 16);
145 ivals[0] = cfg->scroll_dist;
146 mprops.scroll_dist = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_DIST, 1, ivals, 32);
148 ivals[0] = cfg->scroll_up_btn;
149 ivals[1] = cfg->scroll_dn_btn;
150 ivals[2] = cfg->scroll_lt_btn;
151 ivals[3] = cfg->scroll_rt_btn;
152 mprops.scroll_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_BUTTONS, 4, ivals, 8);
154 ivals[0] = cfg->swipe_dist;
155 mprops.swipe_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_DIST, 1, ivals, 32);
157 ivals[0] = cfg->swipe_up_btn;
158 ivals[1] = cfg->swipe_dn_btn;
159 ivals[2] = cfg->swipe_lt_btn;
160 ivals[3] = cfg->swipe_rt_btn;
161 mprops.swipe_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_BUTTONS, 4, ivals, 8);
163 ivals[0] = cfg->swipe4_dist;
164 mprops.swipe4_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_DIST, 1, ivals, 32);
166 ivals[0] = cfg->swipe4_up_btn;
167 ivals[1] = cfg->swipe4_dn_btn;
168 ivals[2] = cfg->swipe4_lt_btn;
169 ivals[3] = cfg->swipe4_rt_btn;
170 mprops.swipe4_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_BUTTONS, 4, ivals, 8);
172 ivals[0] = cfg->scale_dist;
173 mprops.scale_dist = atom_init_integer(local->dev, MTRACK_PROP_SCALE_DIST, 1, ivals, 32);
175 ivals[0] = cfg->scale_up_btn;
176 ivals[1] = cfg->scale_dn_btn;
177 mprops.scale_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCALE_BUTTONS, 2, ivals, 8);
179 ivals[0] = cfg->rotate_dist;
180 mprops.rotate_dist = atom_init_integer(local->dev, MTRACK_PROP_ROTATE_DIST, 1, ivals, 32);
182 ivals[0] = cfg->rotate_lt_btn;
183 ivals[1] = cfg->rotate_rt_btn;
184 mprops.rotate_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCALE_BUTTONS, 2, ivals, 8);
186 ivals[0] = cfg->drag_enable;
187 ivals[1] = cfg->drag_timeout;
188 ivals[2] = cfg->drag_wait;
189 ivals[3] = cfg->drag_dist;
190 mprops.drag_settings = atom_init_integer(local->dev, MTRACK_PROP_DRAG_SETTINGS, 4, ivals, 32);
192 ivals[0] = cfg->axis_x_invert;
193 ivals[1] = cfg->axis_y_invert;
194 mprops.axis_invert = atom_init_integer(local->dev, MTRACK_PROP_AXIS_INVERT, 2, ivals, 8);
197 int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly) {
198 InputInfoPtr local = dev->public.devicePrivate;
199 struct MConfig* cfg = &((struct MTouch*)local->private)->cfg;
206 if (property == mprops.trackpad_disable) {
207 if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
210 ivals8 = (uint8_t*)prop->data;
211 if (ivals8[0] < 0 || ivals8[0] > 3)
215 cfg->trackpad_disable = ivals8[0];
217 if (cfg->trackpad_disable)
218 xf86Msg(X_INFO, "mtrack: trackpad input disabled\n");
220 xf86Msg(X_INFO, "mtrack: trackpad input enabled\n");
224 else if (property == mprops.sensitivity) {
225 if (prop->size != 1 || prop->format != 32 || prop->type != mprops.float_type)
228 fvals = (float*)prop->data;
233 cfg->sensitivity = fvals[0];
235 xf86Msg(X_INFO, "mtrack: set sensitivity to %f\n", cfg->sensitivity);
239 else if (property == mprops.pressure) {
240 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
243 ivals8 = (uint8_t*)prop->data;
244 if (!VALID_PCNT(ivals8[0]) || !VALID_PCNT(ivals8[1]))
248 cfg->touch_down = ivals8[0];
249 cfg->touch_up = ivals8[1];
251 xf86Msg(X_INFO, "mtrack: set touch pressure to %d %d\n",
252 cfg->touch_down, cfg->touch_up);
256 else if (property == mprops.button_settings) {
257 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
260 ivals8 = (uint8_t*)prop->data;
261 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]))
265 cfg->button_enable = ivals8[0];
266 cfg->button_integrated = ivals8[1];
268 xf86Msg(X_INFO, "mtrack: set button settings to %d %d\n",
269 cfg->button_enable, cfg->button_integrated);
273 else if (property == mprops.button_emulate_settings) {
274 if (prop->size != 3 || prop->format != 16 || prop->type != XA_INTEGER)
277 ivals16 = (uint16_t*)prop->data;
278 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]) || ivals16[2] < 0)
282 cfg->button_zones = ivals16[0];
283 cfg->button_move = ivals16[1];
284 cfg->button_expire = ivals16[2];
286 xf86Msg(X_INFO, "mtrack: set button emulate settings to %d %d %d\n",
287 cfg->button_zones, cfg->button_move, cfg->button_expire);
291 else if (property == mprops.button_emulate_values) {
292 if (prop->size != 3 || prop->format != 8 || prop->type != XA_INTEGER)
295 ivals8 = (uint8_t*)prop->data;
296 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]))
300 cfg->button_1touch = ivals8[0];
301 cfg->button_2touch = ivals8[1];
302 cfg->button_3touch = ivals8[2];
304 xf86Msg(X_INFO, "mtrack: set button emulation to %d %d %s\n",
305 cfg->button_1touch, cfg->button_2touch, cfg->button_3touch);
309 else if (property == mprops.tap_settings) {
310 if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
313 ivals32 = (uint32_t*)prop->data;
314 if (ivals32[0] < 1 || ivals32[1] < 1 || ivals32[2] < 1)
318 cfg->tap_hold = ivals32[0];
319 cfg->tap_timeout = ivals32[1];
320 cfg->tap_dist = ivals32[2];
322 xf86Msg(X_INFO, "mtrack: set tap settings to %d %d %d\n",
323 cfg->tap_hold, cfg->tap_timeout, cfg->tap_dist);
327 else if (property == mprops.tap_emulate) {
328 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
331 ivals8 = (uint8_t*)prop->data;
332 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
336 cfg->tap_1touch = ivals8[0];
337 cfg->tap_2touch = ivals8[1];
338 cfg->tap_3touch = ivals8[2];
339 cfg->tap_4touch = ivals8[3];
341 xf86Msg(X_INFO, "mtrack: set tap emulation to %d %d %d %d\n",
342 cfg->tap_1touch, cfg->tap_2touch, cfg->tap_3touch, cfg->tap_4touch);
346 else if (property == mprops.thumb_detect) {
347 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
350 ivals8 = (uint8_t*)prop->data;
351 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
355 cfg->ignore_thumb = ivals8[0];
356 cfg->disable_on_thumb = ivals8[1];
358 xf86Msg(X_INFO, "mtrack: set thumb detect to %d %d\n",
359 cfg->ignore_thumb, cfg->disable_on_thumb);
363 else if (property == mprops.thumb_size) {
364 if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
367 ivals32 = (uint32_t*)prop->data;
368 if (ivals32[0] < 0 || !VALID_PCNT(ivals32[1]))
372 cfg->thumb_size = ivals32[0];
373 cfg->thumb_ratio = ivals32[0];
375 xf86Msg(X_INFO, "mtrack: set thumb size to %d %d\n",
376 cfg->thumb_size, cfg->thumb_ratio);
380 else if (property == mprops.palm_detect) {
381 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
384 ivals8 = (uint8_t*)prop->data;
385 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
389 cfg->ignore_palm = ivals8[0];
390 cfg->disable_on_palm = ivals8[1];
392 xf86Msg(X_INFO, "mtrack: set palm detect to %d %d\n",
393 cfg->ignore_palm, cfg->disable_on_palm);
397 else if (property == mprops.palm_size) {
398 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
401 ivals32 = (uint32_t*)prop->data;
406 cfg->palm_size = ivals32[0];
408 xf86Msg(X_INFO, "mtrack: set palm size to %d\n",
413 else if (property == mprops.gesture_settings) {
414 if (prop->size != 2 || prop->format != 16 || prop->type != XA_INTEGER)
417 ivals16 = (uint16_t*)prop->data;
418 if (ivals16[0] < 1 || ivals16[1] < 0)
422 cfg->gesture_hold = ivals16[0];
423 cfg->gesture_wait = ivals16[1];
425 xf86Msg(X_INFO, "mtrack: set gesture settings to %d %d\n",
426 cfg->gesture_hold, cfg->gesture_wait);
430 else if (property == mprops.scroll_dist) {
431 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
434 ivals32 = (uint32_t*)prop->data;
439 cfg->scroll_dist = ivals32[0];
441 xf86Msg(X_INFO, "mtrack: set scroll distance to %d\n",
446 else if (property == mprops.scroll_buttons) {
447 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
450 ivals8 = (uint8_t*)prop->data;
451 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
455 cfg->scroll_up_btn = ivals8[0];
456 cfg->scroll_dn_btn = ivals8[1];
457 cfg->scroll_lt_btn = ivals8[2];
458 cfg->scroll_rt_btn = ivals8[3];
460 xf86Msg(X_INFO, "mtrack: set scroll buttons to %d %d %d %d\n",
461 cfg->scroll_up_btn, cfg->scroll_dn_btn, cfg->scroll_lt_btn, cfg->scroll_rt_btn);
465 else if (property == mprops.swipe_dist) {
466 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
469 ivals32 = (uint32_t*)prop->data;
474 cfg->swipe_dist = ivals32[0];
476 xf86Msg(X_INFO, "mtrack: set swipe distance to %d\n",
481 else if (property == mprops.swipe_buttons) {
482 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
485 ivals8 = (uint8_t*)prop->data;
486 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
490 cfg->swipe_up_btn = ivals8[0];
491 cfg->swipe_dn_btn = ivals8[1];
492 cfg->swipe_lt_btn = ivals8[2];
493 cfg->swipe_rt_btn = ivals8[3];
495 xf86Msg(X_INFO, "mtrack: set swipe buttons to %d %d %d %d\n",
496 cfg->swipe_up_btn, cfg->swipe_dn_btn, cfg->swipe_lt_btn, cfg->swipe_rt_btn);
500 else if (property == mprops.swipe4_dist) {
501 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
504 ivals32 = (uint32_t*)prop->data;
509 cfg->swipe4_dist = ivals32[0];
511 xf86Msg(X_INFO, "mtrack: set swipe4 distance to %d\n",
516 else if (property == mprops.swipe4_buttons) {
517 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
520 ivals8 = (uint8_t*)prop->data;
521 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
525 cfg->swipe4_up_btn = ivals8[0];
526 cfg->swipe4_dn_btn = ivals8[1];
527 cfg->swipe4_lt_btn = ivals8[2];
528 cfg->swipe4_rt_btn = ivals8[3];
530 xf86Msg(X_INFO, "mtrack: set swipe4 buttons to %d %d %d %d\n",
531 cfg->swipe4_up_btn, cfg->swipe4_dn_btn, cfg->swipe4_lt_btn, cfg->swipe4_rt_btn);
535 else if (property == mprops.scale_dist) {
536 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
539 ivals32 = (uint32_t*)prop->data;
544 cfg->scale_dist = ivals32[0];
546 xf86Msg(X_INFO, "mtrack: set scale distance to %d\n",
551 else if (property == mprops.scale_buttons) {
552 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
555 ivals8 = (uint8_t*)prop->data;
556 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
560 cfg->scale_up_btn = ivals8[0];
561 cfg->scale_dn_btn = ivals8[1];
563 xf86Msg(X_INFO, "mtrack: set scale buttons to %d %d\n",
564 cfg->scale_up_btn, cfg->scale_dn_btn);
568 else if (property == mprops.rotate_dist) {
569 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
572 ivals32 = (uint32_t*)prop->data;
577 cfg->rotate_dist = ivals32[0];
579 xf86Msg(X_INFO, "mtrack: set rotate distance to %d\n",
584 else if (property == mprops.rotate_buttons) {
585 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
588 ivals8 = (uint8_t*)prop->data;
589 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
593 cfg->rotate_lt_btn = ivals8[0];
594 cfg->rotate_rt_btn = ivals8[1];
596 xf86Msg(X_INFO, "mtrack: set rotate buttons to %d %d\n",
597 cfg->rotate_lt_btn, cfg->rotate_rt_btn);
601 else if (property == mprops.drag_settings) {
602 if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
605 ivals32 = (uint32_t*)prop->data;
606 if (!VALID_BOOL(ivals32[0]) || ivals32[1] < 1 || ivals32[2] < 0 || ivals32[3] < 0)
610 cfg->drag_enable = ivals32[0];
611 cfg->drag_timeout = ivals32[1];
612 cfg->drag_wait = ivals32[2];
613 cfg->drag_dist = ivals32[3];
615 xf86Msg(X_INFO, "mtrack: set drag settings to %d %d %d %d\n",
616 cfg->drag_enable, cfg->drag_timeout, cfg->drag_wait, cfg->drag_dist);
620 else if (property == mprops.axis_invert) {
621 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
624 ivals8 = (uint8_t*)prop->data;
625 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
629 cfg->axis_x_invert = ivals8[0];
630 cfg->axis_y_invert = ivals8[1];
632 xf86Msg(X_INFO, "mtrack: set axis inversion to %d %d\n",
633 cfg->axis_x_invert, cfg->axis_y_invert);