chiark / gitweb /
Button zones: Export bottom_edge_zones in MTRACK_PROP_BUTTON_EMULATE_SETTINGS
[xf86-input-mtrack.git] / driver / mprops.c
1 /***************************************************************************
2  *
3  * Multitouch X driver
4  * Copyright (C) 2011 Ryan Bourgeois <bluedragonx@gmail.com>
5  *
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.
10  *
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.
15  *
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
19  *
20  **************************************************************************/
21
22 #include "mprops.h"
23 #include "common.h"
24 #include "mtouch.h"
25
26 #define MAX_INT_VALUES 4
27 #define MAX_FLOAT_VALUES 4
28
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)
32
33 struct MProps mprops;
34
35 Atom atom_init_integer(DeviceIntPtr dev, char* name, int nvalues, int* values, int size) {
36         Atom atom;
37         int i;
38         uint8_t uvals8[MAX_INT_VALUES];
39         uint16_t uvals16[MAX_INT_VALUES];
40         uint32_t uvals32[MAX_INT_VALUES];
41         pointer uvals;
42         nvalues = MINVAL(MAX_INT_VALUES, nvalues);
43
44         switch(size) {
45         case 8:
46                 for (i = 0; i < nvalues; i++) {
47                         uvals8[i] = values[i];
48                 }
49                 uvals = uvals8;
50                 break;
51         case 16:
52                 for (i = 0; i < nvalues; i++) {
53                         uvals16[i] = values[i];
54                 }
55                 uvals = uvals16;
56                 break;
57         default:
58                 for (i = 0; i < nvalues; i++) {
59                         uvals32[i] = values[i];
60                 }
61                 uvals = uvals32;
62                 break;
63         }
64
65         atom = MakeAtom(name, strlen(name), TRUE);
66         XIChangeDeviceProperty(dev, atom, XA_INTEGER, size, PropModeReplace, nvalues, uvals, FALSE);
67         XISetDevicePropertyDeletable(dev, atom, FALSE);
68         return atom;
69 }
70
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);
75         return atom;
76 }
77
78 void mprops_init(struct MConfig* cfg, InputInfoPtr local) {
79         int ivals[MAX_INT_VALUES];
80         float fvals[MAX_FLOAT_VALUES];
81
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);
87                         return;
88                 }
89         }
90
91         ivals[0] = cfg->trackpad_disable;
92         mprops.trackpad_disable = atom_init_integer(local->dev, MTRACK_PROP_TRACKPAD_DISABLE, 1, ivals, 8);
93
94         fvals[0] = (float)cfg->sensitivity;
95         mprops.sensitivity = atom_init_float(local->dev, MTRACK_PROP_SENSITIVITY, 1, fvals, mprops.float_type);
96
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);
100
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);
104
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);
110
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);
115
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);
120
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);
126
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);
130
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);
134
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);
138
139         ivals[0] = cfg->palm_size;
140         mprops.palm_size = atom_init_integer(local->dev, MTRACK_PROP_PALM_SIZE, 1, ivals, 32);
141
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);
145
146         ivals[0] = cfg->scroll_dist;
147         mprops.scroll_dist = atom_init_integer(local->dev, MTRACK_PROP_SCROLL_DIST, 1, ivals, 32);
148
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);
154
155         ivals[0] = cfg->swipe_dist;
156         mprops.swipe_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE_DIST, 1, ivals, 32);
157
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);
163
164         ivals[0] = cfg->swipe4_dist;
165         mprops.swipe4_dist = atom_init_integer(local->dev, MTRACK_PROP_SWIPE4_DIST, 1, ivals, 32);
166
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);
172
173         ivals[0] = cfg->scale_dist;
174         mprops.scale_dist = atom_init_integer(local->dev, MTRACK_PROP_SCALE_DIST, 1, ivals, 32);
175
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);
179
180         ivals[0] = cfg->rotate_dist;
181         mprops.rotate_dist = atom_init_integer(local->dev, MTRACK_PROP_ROTATE_DIST, 1, ivals, 32);
182
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);
186
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);
192
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);
196 }
197
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;
201
202         uint8_t* ivals8;
203         uint16_t* ivals16;
204         uint32_t* ivals32;
205         float* fvals;
206
207         if (property == mprops.trackpad_disable) {
208                 if (prop->size != 1 || prop->format != 8 || prop->type != XA_INTEGER)
209                         return BadMatch;
210
211                 ivals8 = (uint8_t*)prop->data;
212                 if (ivals8[0] < 0 || ivals8[0] > 3)
213                         return BadMatch;
214
215                 if (!checkonly) {
216                         cfg->trackpad_disable = ivals8[0];
217 #ifdef DEBUG_PROPS
218                         if (cfg->trackpad_disable)
219                                 xf86Msg(X_INFO, "mtrack: trackpad input disabled\n");
220                         else
221                                 xf86Msg(X_INFO, "mtrack: trackpad input enabled\n");
222 #endif
223                 }
224         }
225         else if (property == mprops.sensitivity) {
226                 if (prop->size != 1 || prop->format != 32 || prop->type != mprops.float_type)
227                         return BadMatch;
228
229                 fvals = (float*)prop->data;
230                 if (fvals[0] < 0)
231                         return BadMatch;
232
233                 if (!checkonly) {
234                         cfg->sensitivity = fvals[0];
235 #ifdef DEBUG_PROPS
236                         xf86Msg(X_INFO, "mtrack: set sensitivity to %f\n", cfg->sensitivity);
237 #endif
238                 }
239         }
240         else if (property == mprops.pressure) {
241                 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) 
242                         return BadMatch;
243
244                 ivals8 = (uint8_t*)prop->data;
245                 if (!VALID_PCNT(ivals8[0]) || !VALID_PCNT(ivals8[1]))
246                         return BadMatch;
247
248                 if (!checkonly) {
249                         cfg->touch_down = ivals8[0];
250                         cfg->touch_up = ivals8[1];
251 #ifdef DEBUG_PROPS
252                         xf86Msg(X_INFO, "mtrack: set touch pressure to %d %d\n",
253                                 cfg->touch_down, cfg->touch_up);
254 #endif
255                 }
256         }
257         else if (property == mprops.button_settings) {
258                 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER) 
259                         return BadMatch;
260
261                 ivals8 = (uint8_t*)prop->data;
262                 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]))
263                         return BadMatch;
264
265                 if (!checkonly) {
266                         cfg->button_enable = ivals8[0];
267                         cfg->button_integrated = ivals8[1];
268 #ifdef DEBUG_PROPS
269                         xf86Msg(X_INFO, "mtrack: set button settings to %d %d\n",
270                                 cfg->button_enable, cfg->button_integrated);
271 #endif
272                 }
273         }
274         else if (property == mprops.button_emulate_settings) {
275                 if (prop->size < 3 || prop->size > 4 || prop->format != 16 || prop->type != XA_INTEGER)
276                         return BadMatch;
277
278                 ivals16 = (uint16_t*)prop->data;
279                 if (!VALID_BOOL(ivals16[0]) || !VALID_BOOL(ivals16[1]) || ivals16[2] < 0)
280                         return BadMatch;
281
282                 if (prop->size >= 4) {
283                         if (!VALID_BOOL(ivals16[3]))
284                                 return BadMatch;
285                 }
286
287                 if (!checkonly) {
288                         cfg->button_zones = ivals16[0];
289                         cfg->button_move = ivals16[1];
290                         cfg->button_expire = ivals16[2];
291                         if (prop->size >= 4)
292                                 cfg->bottom_edge_zones = ivals16[3];
293 #ifdef DEBUG_PROPS
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);
296 #endif
297                 }
298         }
299         else if (property == mprops.button_emulate_values) {
300                 if (prop->size != 3 || prop->format != 8 || prop->type != XA_INTEGER)
301                         return BadMatch;
302
303                 ivals8 = (uint8_t*)prop->data;
304                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]))
305                         return BadMatch;
306
307                 if (!checkonly) {
308                         cfg->button_1touch = ivals8[0];
309                         cfg->button_2touch = ivals8[1];
310                         cfg->button_3touch = ivals8[2];
311 #ifdef DEBUG_PROPS
312                         xf86Msg(X_INFO, "mtrack: set button emulation to %d %d %s\n",
313                                 cfg->button_1touch, cfg->button_2touch, cfg->button_3touch);
314 #endif
315                 }
316         }
317         else if (property == mprops.tap_settings) {
318                 if (prop->size != 3 || prop->format != 32 || prop->type != XA_INTEGER)
319                         return BadMatch;
320
321                 ivals32 = (uint32_t*)prop->data;
322                 if (ivals32[0] < 1 || ivals32[1] < 1 || ivals32[2] < 1)
323                         return BadMatch;
324
325                 if (!checkonly) {
326                         cfg->tap_hold = ivals32[0];
327                         cfg->tap_timeout = ivals32[1];
328                         cfg->tap_dist = ivals32[2];
329 #ifdef DEBUG_PROPS
330                         xf86Msg(X_INFO, "mtrack: set tap settings to %d %d %d\n",
331                                 cfg->tap_hold, cfg->tap_timeout, cfg->tap_dist);
332 #endif
333                 }
334         }
335         else if (property == mprops.tap_emulate) {
336                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
337                         return BadMatch;
338
339                 ivals8 = (uint8_t*)prop->data;
340                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
341                         return BadMatch;
342
343                 if (!checkonly) {                       
344                         cfg->tap_1touch = ivals8[0];
345                         cfg->tap_2touch = ivals8[1];
346                         cfg->tap_3touch = ivals8[2];
347                         cfg->tap_4touch = ivals8[3];
348 #ifdef DEBUG_PROPS
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);
351 #endif
352                 }
353         }
354         else if (property == mprops.thumb_detect) {
355                 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
356                         return BadMatch;
357
358                 ivals8 = (uint8_t*)prop->data;
359                 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
360                         return BadMatch;
361
362                 if (!checkonly) {
363                         cfg->ignore_thumb = ivals8[0];
364                         cfg->disable_on_thumb = ivals8[1];
365 #ifdef DEBUG_PROPS
366                         xf86Msg(X_INFO, "mtrack: set thumb detect to %d %d\n",
367                                 cfg->ignore_thumb, cfg->disable_on_thumb);
368 #endif
369                 }
370         }
371         else if (property == mprops.thumb_size) {
372                 if (prop->size != 2 || prop->format != 32 || prop->type != XA_INTEGER)
373                         return BadMatch;
374
375                 ivals32 = (uint32_t*)prop->data;
376                 if (ivals32[0] < 0 || !VALID_PCNT(ivals32[1]))
377                         return BadMatch;
378
379                 if (!checkonly) {
380                         cfg->thumb_size = ivals32[0];
381                         cfg->thumb_ratio = ivals32[0];
382 #ifdef DEBUG_PROPS
383                         xf86Msg(X_INFO, "mtrack: set thumb size to %d %d\n",
384                                 cfg->thumb_size, cfg->thumb_ratio);
385 #endif
386                 }
387         }
388         else if (property == mprops.palm_detect) {
389                 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
390                         return BadMatch;
391
392                 ivals8 = (uint8_t*)prop->data;
393                 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
394                         return BadMatch;
395
396                 if (!checkonly) {
397                         cfg->ignore_palm = ivals8[0];
398                         cfg->disable_on_palm = ivals8[1];
399 #ifdef DEBUG_PROPS
400                         xf86Msg(X_INFO, "mtrack: set palm detect to %d %d\n",
401                                 cfg->ignore_palm, cfg->disable_on_palm);
402 #endif
403                 }
404         }
405         else if (property == mprops.palm_size) {
406                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
407                         return BadMatch;
408
409                 ivals32 = (uint32_t*)prop->data;
410                 if (ivals32[0] < 0)
411                         return BadMatch;
412
413                 if (!checkonly) {
414                         cfg->palm_size = ivals32[0];
415 #ifdef DEBUG_PROPS
416                         xf86Msg(X_INFO, "mtrack: set palm size to %d\n",
417                                 cfg->palm_size);
418 #endif
419                 }
420         }
421         else if (property == mprops.gesture_settings) {
422                 if (prop->size != 2 || prop->format != 16 || prop->type != XA_INTEGER)
423                         return BadMatch;
424
425                 ivals16 = (uint16_t*)prop->data;
426                 if (ivals16[0] < 1 || ivals16[1] < 0)
427                         return BadMatch;
428
429                 if (!checkonly) {
430                         cfg->gesture_hold = ivals16[0];
431                         cfg->gesture_wait = ivals16[1];
432 #ifdef DEBUG_PROPS
433                         xf86Msg(X_INFO, "mtrack: set gesture settings to %d %d\n",
434                                 cfg->gesture_hold, cfg->gesture_wait);
435 #endif
436                 }
437         }
438         else if (property == mprops.scroll_dist) {
439                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
440                         return BadMatch;
441
442                 ivals32 = (uint32_t*)prop->data;
443                 if (ivals32[0] < 1)
444                         return BadMatch;
445
446                 if (!checkonly) {
447                         cfg->scroll_dist = ivals32[0];
448 #ifdef DEBUG_PROPS
449                         xf86Msg(X_INFO, "mtrack: set scroll distance to %d\n",
450                                 cfg->scroll_dist);
451 #endif
452                 }
453         }
454         else if (property == mprops.scroll_buttons) {
455                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
456                         return BadMatch;
457
458                 ivals8 = (uint8_t*)prop->data;
459                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
460                         return BadMatch;
461
462                 if (!checkonly) {
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];
467 #ifdef DEBUG_PROPS
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);
470 #endif
471                 }
472         }
473         else if (property == mprops.swipe_dist) {
474                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
475                         return BadMatch;
476
477                 ivals32 = (uint32_t*)prop->data;
478                 if (ivals32[0] < 1)
479                         return BadMatch;
480
481                 if (!checkonly) {
482                         cfg->swipe_dist = ivals32[0];
483 #ifdef DEBUG_PROPS
484                         xf86Msg(X_INFO, "mtrack: set swipe distance to %d\n",
485                                 cfg->swipe_dist);
486 #endif
487                 }
488         }
489         else if (property == mprops.swipe_buttons) {
490                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
491                         return BadMatch;
492
493                 ivals8 = (uint8_t*)prop->data;
494                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
495                         return BadMatch;
496
497                 if (!checkonly) {
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];
502 #ifdef DEBUG_PROPS
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);
505 #endif
506                 }
507         }
508         else if (property == mprops.swipe4_dist) {
509                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
510                         return BadMatch;
511
512                 ivals32 = (uint32_t*)prop->data;
513                 if (ivals32[0] < 1)
514                         return BadMatch;
515
516                 if (!checkonly) {
517                         cfg->swipe4_dist = ivals32[0];
518 #ifdef DEBUG_PROPS
519                         xf86Msg(X_INFO, "mtrack: set swipe4 distance to %d\n",
520                                 cfg->swipe4_dist);
521 #endif
522                 }
523         }
524         else if (property == mprops.swipe4_buttons) {
525                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
526                         return BadMatch;
527
528                 ivals8 = (uint8_t*)prop->data;
529                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
530                         return BadMatch;
531
532                 if (!checkonly) {
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];
537 #ifdef DEBUG_PROPS
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);
540 #endif
541                 }
542         }
543         else if (property == mprops.scale_dist) {
544                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
545                         return BadMatch;
546
547                 ivals32 = (uint32_t*)prop->data;
548                 if (ivals32[0] < 1)
549                         return BadMatch;
550
551                 if (!checkonly) {
552                         cfg->scale_dist = ivals32[0];
553 #ifdef DEBUG_PROPS
554                         xf86Msg(X_INFO, "mtrack: set scale distance to %d\n",
555                                 cfg->scale_dist);
556 #endif
557                 }
558         }
559         else if (property == mprops.scale_buttons) {
560                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
561                         return BadMatch;
562
563                 ivals8 = (uint8_t*)prop->data;
564                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
565                         return BadMatch;
566
567                 if (!checkonly) {
568                         cfg->scale_up_btn = ivals8[0];
569                         cfg->scale_dn_btn = ivals8[1];
570 #ifdef DEBUG_PROPS
571                         xf86Msg(X_INFO, "mtrack: set scale buttons to %d %d\n",
572                                 cfg->scale_up_btn, cfg->scale_dn_btn);
573 #endif
574                 }
575         }
576         else if (property == mprops.rotate_dist) {
577                 if (prop->size != 1 || prop->format != 32 || prop->type != XA_INTEGER)
578                         return BadMatch;
579
580                 ivals32 = (uint32_t*)prop->data;
581                 if (ivals32[0] < 1)
582                         return BadMatch;
583
584                 if (!checkonly) {
585                         cfg->rotate_dist = ivals32[0];
586 #ifdef DEBUG_PROPS
587                         xf86Msg(X_INFO, "mtrack: set rotate distance to %d\n",
588                                 cfg->rotate_dist);
589 #endif
590                 }
591         }
592         else if (property == mprops.rotate_buttons) {
593                 if (prop->size != 4 || prop->format != 8 || prop->type != XA_INTEGER)
594                         return BadMatch;
595
596                 ivals8 = (uint8_t*)prop->data;
597                 if (!VALID_BUTTON(ivals8[0]) || !VALID_BUTTON(ivals8[1]) || !VALID_BUTTON(ivals8[2]) || !VALID_BUTTON(ivals8[3]))
598                         return BadMatch;
599
600                 if (!checkonly) {
601                         cfg->rotate_lt_btn = ivals8[0];
602                         cfg->rotate_rt_btn = ivals8[1];
603 #ifdef DEBUG_PROPS
604                         xf86Msg(X_INFO, "mtrack: set rotate buttons to %d %d\n",
605                                 cfg->rotate_lt_btn, cfg->rotate_rt_btn);
606 #endif
607                 }
608         }
609         else if (property == mprops.drag_settings) {
610                 if (prop->size != 4 || prop->format != 32 || prop->type != XA_INTEGER)
611                         return BadMatch;
612
613                 ivals32 = (uint32_t*)prop->data;
614                 if (!VALID_BOOL(ivals32[0]) || ivals32[1] < 1 || ivals32[2] < 0 || ivals32[3] < 0)
615                         return BadMatch;
616
617                 if (!checkonly) {
618                         cfg->drag_enable = ivals32[0];
619                         cfg->drag_timeout = ivals32[1];
620                         cfg->drag_wait = ivals32[2];
621                         cfg->drag_dist = ivals32[3];
622 #ifdef DEBUG_PROPS
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);
625 #endif
626                 }
627         }
628         else if (property == mprops.axis_invert) {
629                 if (prop->size != 2 || prop->format != 8 || prop->type != XA_INTEGER)
630                         return BadMatch;
631
632                 ivals8 = (uint8_t*)prop->data;
633                 if (!VALID_BOOL(ivals8[0]) || !VALID_BOOL(ivals8[1]))
634                         return BadMatch;
635
636                 if (!checkonly) {
637                         cfg->axis_x_invert = ivals8[0];
638                         cfg->axis_y_invert = ivals8[1];
639 #ifdef DEBUG_PROPS
640                         xf86Msg(X_INFO, "mtrack: set axis inversion to %d %d\n",
641                                 cfg->axis_x_invert, cfg->axis_y_invert);
642 #endif
643                 }
644         }
645
646         return Success;
647 }
648