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)mconfig_get_sensitivity(cfg);
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 ivals[3] = cfg->bottom_edge_zones;
109 mprops.button_emulate_settings = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_SETTINGS, 4, ivals, 16);
111 ivals[0] = cfg->button_1touch;
112 ivals[1] = cfg->button_2touch;
113 ivals[2] = cfg->button_3touch;
114 mprops.button_emulate_values = atom_init_integer(local->dev, MTRACK_PROP_BUTTON_EMULATE_VALUES, 3, ivals, 8);
116 ivals[0] = cfg->tap_hold;
117 ivals[1] = cfg->tap_timeout;
118 ivals[2] = cfg->tap_dist;
119 mprops.tap_settings = atom_init_integer(local->dev, MTRACK_PROP_TAP_SETTINGS, 3, ivals, 32);
121 ivals[0] = cfg->tap_1touch;
122 ivals[1] = cfg->tap_2touch;
123 ivals[2] = cfg->tap_3touch;
124 ivals[3] = cfg->tap_4touch;
125 mprops.tap_emulate = atom_init_integer(local->dev, MTRACK_PROP_TAP_EMULATE, 4, ivals, 8);
127 ivals[0] = cfg->ignore_thumb;
128 ivals[1] = cfg->disable_on_thumb;
129 mprops.thumb_detect = atom_init_integer(local->dev, MTRACK_PROP_THUMB_DETECT, 2, ivals, 8);
131 ivals[0] = cfg->thumb_size;
132 ivals[1] = cfg->thumb_ratio;
133 mprops.thumb_size = atom_init_integer(local->dev, MTRACK_PROP_THUMB_SIZE, 2, ivals, 32);
135 ivals[0] = cfg->ignore_palm;
136 ivals[1] = cfg->disable_on_palm;
137 mprops.palm_detect = atom_init_integer(local->dev, MTRACK_PROP_PALM_DETECT, 2, ivals, 8);
139 ivals[0] = cfg->palm_size;
140 mprops.palm_size = atom_init_integer(local->dev, MTRACK_PROP_PALM_SIZE, 1, ivals, 32);
142 ivals[0] = cfg->gesture_hold;
143 ivals[1] = cfg->gesture_wait;
144 mprops.gesture_settings = atom_init_integer(local->dev, MTRACK_PROP_GESTURE_SETTINGS, 2, ivals, 16);
146 ivals[0] = cfg->scroll_dist;
147 mprops.scroll_dist = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_DIST, 1, ivals, 32);
149 ivals[0] = cfg->scroll_up_btn;
150 ivals[1] = cfg->scroll_dn_btn;
151 ivals[2] = cfg->scroll_lt_btn;
152 ivals[3] = cfg->scroll_rt_btn;
153 mprops.scroll_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_BUTTONS, 4, ivals, 8);
155 ivals[0] = cfg->swipe_dist;
156 mprops.swipe_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_DIST, 1, ivals, 32);
158 ivals[0] = cfg->swipe_up_btn;
159 ivals[1] = cfg->swipe_dn_btn;
160 ivals[2] = cfg->swipe_lt_btn;
161 ivals[3] = cfg->swipe_rt_btn;
162 mprops.swipe_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_BUTTONS, 4, ivals, 8);
164 ivals[0] = cfg->swipe4_dist;
165 mprops.swipe4_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_DIST, 1, ivals, 32);
167 ivals[0] = cfg->swipe4_up_btn;
168 ivals[1] = cfg->swipe4_dn_btn;
169 ivals[2] = cfg->swipe4_lt_btn;
170 ivals[3] = cfg->swipe4_rt_btn;
171 mprops.swipe4_buttons = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_BUTTONS, 4, ivals, 8);
173 ivals[0] = cfg->scale_dist;
174 mprops.scale_dist = atom_init_integer(local->dev, MTRACK_PROP_SCALE_DIST, 1, ivals, 32);
176 ivals[0] = cfg->scale_up_btn;
177 ivals[1] = cfg->scale_dn_btn;
178 mprops.scale_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCALE_BUTTONS, 2, ivals, 8);
180 ivals[0] = cfg->rotate_dist;
181 mprops.rotate_dist = atom_init_integer(local->dev, MTRACK_PROP_ROTATE_DIST, 1, ivals, 32);
183 ivals[0] = cfg->rotate_lt_btn;
184 ivals[1] = cfg->rotate_rt_btn;
185 mprops.rotate_buttons = atom_init_integer(local->dev, MTRACK_PROP_SCALE_BUTTONS, 2, ivals, 8);
187 ivals[0] = cfg->drag_enable;
188 ivals[1] = cfg->drag_timeout;
189 ivals[2] = cfg->drag_wait;
190 ivals[3] = cfg->drag_dist;
191 mprops.drag_settings = atom_init_integer(local->dev, MTRACK_PROP_DRAG_SETTINGS, 4, ivals, 32);
193 ivals[0] = cfg->axis_x_invert;
194 ivals[1] = cfg->axis_y_invert;
195 mprops.axis_invert = atom_init_integer(local->dev, MTRACK_PROP_AXIS_INVERT, 2, ivals, 8);
198 int mprops_set_property(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly) {
199 InputInfoPtr local = dev->public.devicePrivate;
200 struct MConfig* cfg = &((struct MTouch*)local->private)->cfg;
207 if (property == mprops.trackpad_disable) {
208 if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
211 ivals8 = (uint8_t*)prop->data;
212 if (ivals8[0] < 0 || ivals8[0] > 3)
216 cfg->trackpad_disable = ivals8[0];
218 if (cfg->trackpad_disable)
219 xf86Msg(X_INFO, "mtrack: trackpad input disabled\n");
221 xf86Msg(X_INFO, "mtrack: trackpad input enabled\n");
225 else if (property == mprops.sensitivity) {
226 if (prop->size != 1 || prop->format != 32 || prop->type != mprops.float_type)
229 fvals = (float*)prop->data;
234 mconfig_set_sensitivity(cfg, fvals[0]);
236 xf86Msg(X_INFO, "mtrack: set sensitivity to %f\n", mconfig_get_sensitivity(cfg));
240 else if (property == mprops.pressure) {
241 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
244 ivals8 = (uint8_t*)prop->data;
245 if (!VALID_PCNT(ivals8[0]) || !VALID_PCNT(ivals8[1]))
249 cfg->touch_down = ivals8[0];
250 cfg->touch_up = ivals8[1];
252 xf86Msg(X_INFO, "mtrack: set touch pressure to %d %d\n",
253 cfg->touch_down, cfg->touch_up);
257 else if (property == mprops.button_settings) {
258 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
261 ivals8 = (uint8_t*)prop->data;
262 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]))
266 cfg->button_enable = ivals8[0];
267 cfg->button_integrated = ivals8[1];
269 xf86Msg(X_INFO, "mtrack: set button settings to %d %d\n",
270 cfg->button_enable, cfg->button_integrated);
274 else if (property == mprops.button_emulate_settings) {
275 if (prop->size < 3 || prop->size > 4 || prop->format != 16 || prop->type != XA_INTEGER)
278 ivals16 = (uint16_t*)prop->data;
279 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]) || ivals16[2] < 0)
282 if (prop->size >= 4) {
283 if (!VALID_BOOL(ivals16[3]))
288 cfg->button_zones = ivals16[0];
289 cfg->button_move = ivals16[1];
290 cfg->button_expire = ivals16[2];
292 cfg->bottom_edge_zones = ivals16[3];
294 xf86Msg(X_INFO, "mtrack: set button emulate settings to %d %d %d %d\n",
295 cfg->button_zones, cfg->button_move, cfg->button_expire, cfg->bottom_edge_zones);
299 else if (property == mprops.button_emulate_values) {
300 if (prop->size != 3 || prop->format != 8 || prop->type != XA_INTEGER)
303 ivals8 = (uint8_t*)prop->data;
304 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]))
308 cfg->button_1touch = ivals8[0];
309 cfg->button_2touch = ivals8[1];
310 cfg->button_3touch = ivals8[2];
312 xf86Msg(X_INFO, "mtrack: set button emulation to %d %d %s\n",
313 cfg->button_1touch, cfg->button_2touch, cfg->button_3touch);
317 else if (property == mprops.tap_settings) {
318 if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
321 ivals32 = (uint32_t*)prop->data;
322 if (ivals32[0] < 1 || ivals32[1] < 1 || ivals32[2] < 1)
326 cfg->tap_hold = ivals32[0];
327 cfg->tap_timeout = ivals32[1];
328 cfg->tap_dist = ivals32[2];
330 xf86Msg(X_INFO, "mtrack: set tap settings to %d %d %d\n",
331 cfg->tap_hold, cfg->tap_timeout, cfg->tap_dist);
335 else if (property == mprops.tap_emulate) {
336 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
339 ivals8 = (uint8_t*)prop->data;
340 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
344 cfg->tap_1touch = ivals8[0];
345 cfg->tap_2touch = ivals8[1];
346 cfg->tap_3touch = ivals8[2];
347 cfg->tap_4touch = ivals8[3];
349 xf86Msg(X_INFO, "mtrack: set tap emulation to %d %d %d %d\n",
350 cfg->tap_1touch, cfg->tap_2touch, cfg->tap_3touch, cfg->tap_4touch);
354 else if (property == mprops.thumb_detect) {
355 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
358 ivals8 = (uint8_t*)prop->data;
359 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
363 cfg->ignore_thumb = ivals8[0];
364 cfg->disable_on_thumb = ivals8[1];
366 xf86Msg(X_INFO, "mtrack: set thumb detect to %d %d\n",
367 cfg->ignore_thumb, cfg->disable_on_thumb);
371 else if (property == mprops.thumb_size) {
372 if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
375 ivals32 = (uint32_t*)prop->data;
376 if (ivals32[0] < 0 || !VALID_PCNT(ivals32[1]))
380 cfg->thumb_size = ivals32[0];
381 cfg->thumb_ratio = ivals32[0];
383 xf86Msg(X_INFO, "mtrack: set thumb size to %d %d\n",
384 cfg->thumb_size, cfg->thumb_ratio);
388 else if (property == mprops.palm_detect) {
389 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
392 ivals8 = (uint8_t*)prop->data;
393 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
397 cfg->ignore_palm = ivals8[0];
398 cfg->disable_on_palm = ivals8[1];
400 xf86Msg(X_INFO, "mtrack: set palm detect to %d %d\n",
401 cfg->ignore_palm, cfg->disable_on_palm);
405 else if (property == mprops.palm_size) {
406 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
409 ivals32 = (uint32_t*)prop->data;
414 cfg->palm_size = ivals32[0];
416 xf86Msg(X_INFO, "mtrack: set palm size to %d\n",
421 else if (property == mprops.gesture_settings) {
422 if (prop->size != 2 || prop->format != 16 || prop->type != XA_INTEGER)
425 ivals16 = (uint16_t*)prop->data;
426 if (ivals16[0] < 1 || ivals16[1] < 0)
430 cfg->gesture_hold = ivals16[0];
431 cfg->gesture_wait = ivals16[1];
433 xf86Msg(X_INFO, "mtrack: set gesture settings to %d %d\n",
434 cfg->gesture_hold, cfg->gesture_wait);
438 else if (property == mprops.scroll_dist) {
439 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
442 ivals32 = (uint32_t*)prop->data;
447 cfg->scroll_dist = ivals32[0];
449 xf86Msg(X_INFO, "mtrack: set scroll distance to %d\n",
454 else if (property == mprops.scroll_buttons) {
455 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
458 ivals8 = (uint8_t*)prop->data;
459 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
463 cfg->scroll_up_btn = ivals8[0];
464 cfg->scroll_dn_btn = ivals8[1];
465 cfg->scroll_lt_btn = ivals8[2];
466 cfg->scroll_rt_btn = ivals8[3];
468 xf86Msg(X_INFO, "mtrack: set scroll buttons to %d %d %d %d\n",
469 cfg->scroll_up_btn, cfg->scroll_dn_btn, cfg->scroll_lt_btn, cfg->scroll_rt_btn);
473 else if (property == mprops.swipe_dist) {
474 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
477 ivals32 = (uint32_t*)prop->data;
482 cfg->swipe_dist = ivals32[0];
484 xf86Msg(X_INFO, "mtrack: set swipe distance to %d\n",
489 else if (property == mprops.swipe_buttons) {
490 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
493 ivals8 = (uint8_t*)prop->data;
494 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
498 cfg->swipe_up_btn = ivals8[0];
499 cfg->swipe_dn_btn = ivals8[1];
500 cfg->swipe_lt_btn = ivals8[2];
501 cfg->swipe_rt_btn = ivals8[3];
503 xf86Msg(X_INFO, "mtrack: set swipe buttons to %d %d %d %d\n",
504 cfg->swipe_up_btn, cfg->swipe_dn_btn, cfg->swipe_lt_btn, cfg->swipe_rt_btn);
508 else if (property == mprops.swipe4_dist) {
509 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
512 ivals32 = (uint32_t*)prop->data;
517 cfg->swipe4_dist = ivals32[0];
519 xf86Msg(X_INFO, "mtrack: set swipe4 distance to %d\n",
524 else if (property == mprops.swipe4_buttons) {
525 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
528 ivals8 = (uint8_t*)prop->data;
529 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
533 cfg->swipe4_up_btn = ivals8[0];
534 cfg->swipe4_dn_btn = ivals8[1];
535 cfg->swipe4_lt_btn = ivals8[2];
536 cfg->swipe4_rt_btn = ivals8[3];
538 xf86Msg(X_INFO, "mtrack: set swipe4 buttons to %d %d %d %d\n",
539 cfg->swipe4_up_btn, cfg->swipe4_dn_btn, cfg->swipe4_lt_btn, cfg->swipe4_rt_btn);
543 else if (property == mprops.scale_dist) {
544 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
547 ivals32 = (uint32_t*)prop->data;
552 cfg->scale_dist = ivals32[0];
554 xf86Msg(X_INFO, "mtrack: set scale distance to %d\n",
559 else if (property == mprops.scale_buttons) {
560 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
563 ivals8 = (uint8_t*)prop->data;
564 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
568 cfg->scale_up_btn = ivals8[0];
569 cfg->scale_dn_btn = ivals8[1];
571 xf86Msg(X_INFO, "mtrack: set scale buttons to %d %d\n",
572 cfg->scale_up_btn, cfg->scale_dn_btn);
576 else if (property == mprops.rotate_dist) {
577 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
580 ivals32 = (uint32_t*)prop->data;
585 cfg->rotate_dist = ivals32[0];
587 xf86Msg(X_INFO, "mtrack: set rotate distance to %d\n",
592 else if (property == mprops.rotate_buttons) {
593 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
596 ivals8 = (uint8_t*)prop->data;
597 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
601 cfg->rotate_lt_btn = ivals8[0];
602 cfg->rotate_rt_btn = ivals8[1];
604 xf86Msg(X_INFO, "mtrack: set rotate buttons to %d %d\n",
605 cfg->rotate_lt_btn, cfg->rotate_rt_btn);
609 else if (property == mprops.drag_settings) {
610 if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
613 ivals32 = (uint32_t*)prop->data;
614 if (!VALID_BOOL(ivals32[0]) || ivals32[1] < 1 || ivals32[2] < 0 || ivals32[3] < 0)
618 cfg->drag_enable = ivals32[0];
619 cfg->drag_timeout = ivals32[1];
620 cfg->drag_wait = ivals32[2];
621 cfg->drag_dist = ivals32[3];
623 xf86Msg(X_INFO, "mtrack: set drag settings to %d %d %d %d\n",
624 cfg->drag_enable, cfg->drag_timeout, cfg->drag_wait, cfg->drag_dist);
628 else if (property == mprops.axis_invert) {
629 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
632 ivals8 = (uint8_t*)prop->data;
633 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
637 cfg->axis_x_invert = ivals8[0];
638 cfg->axis_y_invert = ivals8[1];
640 xf86Msg(X_INFO, "mtrack: set axis inversion to %d %d\n",
641 cfg->axis_x_invert, cfg->axis_y_invert);