~jderose/ubuntu/raring/xserver-xorg-input-synaptics/clickpad

« back to all changes in this revision

Viewing changes to src/synaptics.c

  • Committer: Package Import Robot
  • Author(s): Cyril Brulebois, Julien Cristau, Cyril Brulebois
  • Date: 2012-05-20 16:50:18 UTC
  • mfrom: (0.4.9)
  • mto: (61.1.1 quantal)
  • mto: This revision was merged to the branch mainline in revision 60.
  • Revision ID: package-import@ubuntu.com-20120520165018-ap60y9jh84nv75vp
Tags: 1.6.1-1
[ Julien Cristau ]
* The mtdev build-dep is linux-only (closes: #672572).  Thanks, Pino
  Toscano!

[ Cyril Brulebois ]
* New upstream release, from the 1.6 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
55
55
 * Trademarks are the property of their respective owners.
56
56
 */
57
57
 
58
 
 
59
58
#ifdef HAVE_CONFIG_H
60
59
#include "config.h"
61
60
#endif
118
117
#endif
119
118
 
120
119
#ifndef M_SQRT1_2
121
 
#define M_SQRT1_2  0.70710678118654752440  /* 1/sqrt(2) */
 
120
#define M_SQRT1_2  0.70710678118654752440       /* 1/sqrt(2) */
122
121
#endif
123
122
 
124
123
#define INPUT_BUFFER_SIZE 200
129
128
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
130
129
static int SynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
131
130
#else
132
 
static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
 
131
static InputInfoPtr SynapticsPreInit(InputDriverPtr drv, IDevPtr dev,
 
132
                                     int flags);
133
133
#endif
134
134
static void SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
135
135
static Bool DeviceControl(DeviceIntPtr, int);
136
136
static void ReadInput(InputInfoPtr);
137
 
static int HandleState(InputInfoPtr, struct SynapticsHwState*, CARD32 now,
 
137
static int HandleState(InputInfoPtr, struct SynapticsHwState *, CARD32 now,
138
138
                       Bool from_timer);
139
 
static int ControlProc(InputInfoPtr, xDeviceCtl*);
 
139
static int ControlProc(InputInfoPtr, xDeviceCtl *);
140
140
static int SwitchMode(ClientPtr, DeviceIntPtr, int);
141
141
static Bool DeviceInit(DeviceIntPtr);
142
142
static Bool DeviceOn(DeviceIntPtr);
144
144
static Bool DeviceClose(DeviceIntPtr);
145
145
static Bool QueryHardware(InputInfoPtr);
146
146
static void ReadDevDimensions(InputInfoPtr);
147
 
static void ScaleCoordinates(SynapticsPrivate *priv, struct SynapticsHwState *hw);
148
 
static void CalculateScalingCoeffs(SynapticsPrivate *priv);
 
147
static void ScaleCoordinates(SynapticsPrivate * priv,
 
148
                             struct SynapticsHwState *hw);
 
149
static void CalculateScalingCoeffs(SynapticsPrivate * priv);
149
150
static void SanitizeDimensions(InputInfoPtr pInfo);
150
151
 
151
152
void InitDeviceProperties(InputInfoPtr pInfo);
157
158
    struct SynapticsProtocolOperations *proto_ops;
158
159
} protocols[] = {
159
160
#ifdef BUILD_EVENTCOMM
160
 
    {"event", &event_proto_operations},
 
161
    {
 
162
    "event", &event_proto_operations},
161
163
#endif
162
164
#ifdef BUILD_PSMCOMM
163
 
    {"psm", &psm_proto_operations},
 
165
    {
 
166
    "psm", &psm_proto_operations},
164
167
#endif
165
168
#ifdef BUILD_PS2COMM
166
 
    {"psaux", &psaux_proto_operations},
167
 
    {"alps", &alps_proto_operations},
 
169
    {
 
170
    "psaux", &psaux_proto_operations}, {
 
171
    "alps", &alps_proto_operations},
168
172
#endif
169
 
    {NULL, NULL}
 
173
    {
 
174
    NULL, NULL}
170
175
};
171
176
 
172
177
InputDriverRec SYNAPTICS = {
204
209
    NULL
205
210
};
206
211
 
207
 
 
208
212
/*****************************************************************************
209
213
 *      Function Definitions
210
214
 ****************************************************************************/
220
224
static void
221
225
SanitizeDimensions(InputInfoPtr pInfo)
222
226
{
223
 
    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
224
 
 
225
 
    if (priv->minx >= priv->maxx)
226
 
    {
227
 
        priv->minx = 1615;
228
 
        priv->maxx = 5685;
229
 
        priv->resx = 0;
230
 
 
231
 
        xf86IDrvMsg(pInfo, X_PROBED,
232
 
                    "invalid x-axis range.  defaulting to %d - %d\n",
233
 
                    priv->minx, priv->maxx);
234
 
    }
235
 
 
236
 
    if (priv->miny >= priv->maxy)
237
 
    {
238
 
        priv->miny = 1729;
239
 
        priv->maxy = 4171;
240
 
        priv->resy = 0;
241
 
 
242
 
        xf86IDrvMsg(pInfo, X_PROBED,
243
 
                    "invalid y-axis range.  defaulting to %d - %d\n",
244
 
                    priv->miny, priv->maxy);
245
 
    }
246
 
 
247
 
    if (priv->minp >= priv->maxp)
248
 
    {
249
 
        priv->minp = 0;
250
 
        priv->maxp = 255;
251
 
 
252
 
        xf86IDrvMsg(pInfo, X_PROBED,
253
 
                    "invalid pressure range.  defaulting to %d - %d\n",
254
 
                    priv->minp, priv->maxp);
255
 
    }
256
 
 
257
 
    if (priv->minw >= priv->maxw)
258
 
    {
259
 
        priv->minw = 0;
260
 
        priv->maxw = 15;
261
 
 
262
 
        xf86IDrvMsg(pInfo, X_PROBED,
263
 
                    "invalid finger width range.  defaulting to %d - %d\n",
264
 
                    priv->minw, priv->maxw);
 
227
    SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
 
228
 
 
229
    if (priv->minx >= priv->maxx) {
 
230
        priv->minx = 1615;
 
231
        priv->maxx = 5685;
 
232
        priv->resx = 0;
 
233
 
 
234
        xf86IDrvMsg(pInfo, X_PROBED,
 
235
                    "invalid x-axis range.  defaulting to %d - %d\n",
 
236
                    priv->minx, priv->maxx);
 
237
    }
 
238
 
 
239
    if (priv->miny >= priv->maxy) {
 
240
        priv->miny = 1729;
 
241
        priv->maxy = 4171;
 
242
        priv->resy = 0;
 
243
 
 
244
        xf86IDrvMsg(pInfo, X_PROBED,
 
245
                    "invalid y-axis range.  defaulting to %d - %d\n",
 
246
                    priv->miny, priv->maxy);
 
247
    }
 
248
 
 
249
    if (priv->minp >= priv->maxp) {
 
250
        priv->minp = 0;
 
251
        priv->maxp = 255;
 
252
 
 
253
        xf86IDrvMsg(pInfo, X_PROBED,
 
254
                    "invalid pressure range.  defaulting to %d - %d\n",
 
255
                    priv->minp, priv->maxp);
 
256
    }
 
257
 
 
258
    if (priv->minw >= priv->maxw) {
 
259
        priv->minw = 0;
 
260
        priv->maxw = 15;
 
261
 
 
262
        xf86IDrvMsg(pInfo, X_PROBED,
 
263
                    "invalid finger width range.  defaulting to %d - %d\n",
 
264
                    priv->minw, priv->maxw);
265
265
    }
266
266
}
267
267
 
309
309
    SynapticsPrivate *priv = pInfo->private;
310
310
 
311
311
    if (priv->synshm)
312
 
        return TRUE;                        /* Already allocated */
 
312
        return TRUE;            /* Already allocated */
313
313
 
314
314
    if (priv->shm_config) {
315
 
        if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
316
 
            shmctl(shmid, IPC_RMID, NULL);
317
 
        if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
318
 
                                0774 | IPC_CREAT)) == -1) {
319
 
            xf86IDrvMsg(pInfo, X_ERROR, "error shmget\n");
320
 
            return FALSE;
321
 
        }
322
 
        if ((priv->synshm = (SynapticsSHM*)shmat(shmid, NULL, 0)) == NULL) {
323
 
            xf86IDrvMsg(pInfo, X_ERROR, "error shmat\n");
324
 
            return FALSE;
325
 
        }
326
 
    } else {
327
 
        priv->synshm = calloc(1, sizeof(SynapticsSHM));
328
 
        if (!priv->synshm)
329
 
            return FALSE;
 
315
        if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
 
316
            shmctl(shmid, IPC_RMID, NULL);
 
317
        if ((shmid = shmget(SHM_SYNAPTICS, sizeof(SynapticsSHM),
 
318
                            0774 | IPC_CREAT)) == -1) {
 
319
            xf86IDrvMsg(pInfo, X_ERROR, "error shmget\n");
 
320
            return FALSE;
 
321
        }
 
322
        if ((priv->synshm = (SynapticsSHM *) shmat(shmid, NULL, 0)) == NULL) {
 
323
            xf86IDrvMsg(pInfo, X_ERROR, "error shmat\n");
 
324
            return FALSE;
 
325
        }
 
326
    }
 
327
    else {
 
328
        priv->synshm = calloc(1, sizeof(SynapticsSHM));
 
329
        if (!priv->synshm)
 
330
            return FALSE;
330
331
    }
331
332
 
332
333
    return TRUE;
336
337
 * Free SynapticsParameters data previously allocated by alloc_shm_data().
337
338
 */
338
339
static void
339
 
free_shm_data(SynapticsPrivate *priv)
 
340
free_shm_data(SynapticsPrivate * priv)
340
341
{
341
342
    int shmid;
342
343
 
343
344
    if (!priv->synshm)
344
 
        return;
 
345
        return;
345
346
 
346
347
    if (priv->shm_config) {
347
 
        if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
348
 
            shmctl(shmid, IPC_RMID, NULL);
349
 
    } else {
350
 
        free(priv->synshm);
 
348
        if ((shmid = shmget(SHM_SYNAPTICS, 0, 0)) != -1)
 
349
            shmctl(shmid, IPC_RMID, NULL);
 
350
    }
 
351
    else {
 
352
        free(priv->synshm);
351
353
    }
352
354
 
353
355
    priv->synshm = NULL;
354
356
}
355
357
 
356
358
static void
357
 
calculate_edge_widths(SynapticsPrivate *priv, int *l, int *r, int *t, int *b)
 
359
calculate_edge_widths(SynapticsPrivate * priv, int *l, int *r, int *t, int *b)
358
360
{
359
361
    int width, height;
360
 
    int ewidth, eheight; /* edge width/height */
 
362
    int ewidth, eheight;        /* edge width/height */
361
363
 
362
364
    width = abs(priv->maxx - priv->minx);
363
365
    height = abs(priv->maxy - priv->miny);
364
366
 
365
 
    if (priv->model == MODEL_SYNAPTICS)
366
 
    {
 
367
    if (priv->model == MODEL_SYNAPTICS) {
367
368
        ewidth = width * .07;
368
369
        eheight = height * .07;
369
 
    } else if (priv->model == MODEL_ALPS)
370
 
    {
 
370
    }
 
371
    else if (priv->model == MODEL_ALPS) {
371
372
        ewidth = width * .15;
372
373
        eheight = height * .15;
373
 
    } else if (priv->model == MODEL_APPLETOUCH)
374
 
    {
 
374
    }
 
375
    else if (priv->model == MODEL_APPLETOUCH) {
375
376
        ewidth = width * .085;
376
377
        eheight = height * .085;
377
 
    } else
378
 
    {
 
378
    }
 
379
    else {
379
380
        ewidth = width * .04;
380
381
        eheight = height * .054;
381
382
    }
387
388
}
388
389
 
389
390
static void
390
 
calculate_tap_hysteresis(SynapticsPrivate *priv, int range,
 
391
calculate_tap_hysteresis(SynapticsPrivate * priv, int range,
391
392
                         int *fingerLow, int *fingerHigh, int *fingerPress)
392
393
{
393
394
    if (priv->model == MODEL_ELANTECH) {
395
396
         * number of fingers correctly. See Documentation/elantech.txt
396
397
         * in the kernel.
397
398
         */
398
 
        *fingerLow  = priv->minp + 1;
 
399
        *fingerLow = priv->minp + 1;
399
400
        *fingerHigh = priv->minp + 1;
400
 
    } else {
401
 
        *fingerLow  = priv->minp + range * (25.0/256);
402
 
        *fingerHigh = priv->minp + range * (30.0/256);
 
401
    }
 
402
    else {
 
403
        *fingerLow = priv->minp + range * (25.0 / 256);
 
404
        *fingerHigh = priv->minp + range * (30.0 / 256);
403
405
    }
404
406
 
405
407
    *fingerPress = priv->minp + range * 1.000;
411
413
 * int. So - check first for percent, then call xf86Set* again to get
412
414
 * the log message.
413
415
 */
414
 
static int set_percent_option(pointer options, const char* optname,
415
 
                              const int range, const int offset,
416
 
                              const int default_value)
 
416
static int
 
417
set_percent_option(pointer options, const char *optname,
 
418
                   const int range, const int offset, const int default_value)
417
419
{
418
420
    int result;
 
421
 
419
422
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 11
420
423
    double percent = xf86CheckPercentOption(options, optname, -1);
421
424
 
422
425
    if (percent >= 0.0) {
423
426
        percent = xf86SetPercentOption(options, optname, -1);
424
 
        result = percent/100.0 * range + offset;
425
 
    } else
 
427
        result = percent / 100.0 * range + offset;
 
428
    }
 
429
    else
426
430
#endif
427
431
        result = xf86SetIntOption(options, optname, default_value);
428
432
 
429
433
    return result;
430
434
}
431
435
 
432
 
Bool SynapticsIsSoftButtonAreasValid(int *values)
 
436
Bool
 
437
SynapticsIsSoftButtonAreasValid(int *values)
433
438
{
434
439
    Bool right_disabled = FALSE;
435
440
    Bool middle_disabled = FALSE;
451
456
        middle_disabled = TRUE;
452
457
 
453
458
    if (!right_disabled &&
454
 
            ((values[0] && values[0] == values[1]) ||
455
 
             (values[2] && values[2] == values[3])))
 
459
        ((values[0] && values[0] == values[1]) ||
 
460
         (values[2] && values[2] == values[3])))
456
461
        return FALSE;
457
462
 
458
463
    if (!middle_disabled &&
461
466
        return FALSE;
462
467
 
463
468
    /* Check for overlapping button areas */
464
 
    if (!right_disabled && !middle_disabled)
465
 
    {
 
469
    if (!right_disabled && !middle_disabled) {
466
470
        int right_left = values[0] ? values[0] : INT_MIN;
467
471
        int right_right = values[1] ? values[1] : INT_MAX;
468
472
        int right_top = values[2] ? values[2] : INT_MIN;
474
478
 
475
479
        /* If areas overlap in the Y axis */
476
480
        if ((right_bottom <= middle_bottom && right_bottom >= middle_top) ||
477
 
            (right_top <= middle_bottom && right_top >= middle_top))
478
 
        {
 
481
            (right_top <= middle_bottom && right_top >= middle_top)) {
479
482
            /* Check for overlapping left edges */
480
483
            if ((right_left < middle_left && right_right >= middle_left) ||
481
484
                (middle_left < right_left && middle_right >= right_left))
489
492
 
490
493
        /* If areas overlap in the X axis */
491
494
        if ((right_left >= middle_left && right_left <= middle_right) ||
492
 
            (right_right >= middle_left && right_right <= middle_right))
493
 
        {
 
495
            (right_right >= middle_left && right_right <= middle_right)) {
494
496
            /* Check for overlapping top edges */
495
497
            if ((right_top < middle_top && right_bottom >= middle_top) ||
496
498
                (middle_top < right_top && middle_bottom >= right_top))
506
508
    return TRUE;
507
509
}
508
510
 
509
 
static void set_softbutton_areas_option(InputInfoPtr pInfo)
 
511
static void
 
512
set_softbutton_areas_option(InputInfoPtr pInfo)
510
513
{
511
514
    SynapticsPrivate *priv = pInfo->private;
512
515
    SynapticsParameters *pars = &priv->synpara;
513
516
    int values[8];
514
 
    int in_percent = 0; /* bitmask for which ones are in % */
 
517
    int in_percent = 0;         /* bitmask for which ones are in % */
515
518
    char *option_string;
516
519
    char *next_num;
517
520
    char *end_str;
527
530
 
528
531
    next_num = option_string;
529
532
 
530
 
    for (i = 0; i < 8 && *next_num != '\0'; i++)
531
 
    {
 
533
    for (i = 0; i < 8 && *next_num != '\0'; i++) {
532
534
        long int value = strtol(next_num, &end_str, 0);
 
535
 
533
536
        if (value > INT_MAX || value < -INT_MAX)
534
537
            goto fail;
535
538
 
536
539
        values[i] = value;
537
540
 
538
 
        if (next_num != end_str)
539
 
        {
540
 
            if (end_str && *end_str == '%')
541
 
            {
 
541
        if (next_num != end_str) {
 
542
            if (end_str && *end_str == '%') {
542
543
                in_percent |= 1 << i;
543
544
                end_str++;
544
545
            }
545
546
            next_num = end_str;
546
 
        } else
 
547
        }
 
548
        else
547
549
            goto fail;
548
550
    }
549
551
 
553
555
    width = priv->maxx - priv->minx;
554
556
    height = priv->maxy - priv->miny;
555
557
 
556
 
    for (i = 0; in_percent && i < 8; i++)
557
 
    {
 
558
    for (i = 0; in_percent && i < 8; i++) {
558
559
        int base, size;
559
560
 
560
561
        if ((in_percent & (1 << i)) == 0 || values[i] == 0)
562
563
 
563
564
        size = ((i % 4) < 2) ? width : height;
564
565
        base = ((i % 4) < 2) ? priv->minx : priv->miny;
565
 
        values[i] = base + size * values[i]/100.0;
 
566
        values[i] = base + size * values[i] / 100.0;
566
567
    }
567
568
 
568
569
    if (!SynapticsIsSoftButtonAreasValid(values))
573
574
 
574
575
    return;
575
576
 
576
 
fail:
577
 
    xf86IDrvMsg(pInfo, X_ERROR, "invalid SoftButtonAreas value '%s', keeping defaults\n",
 
577
 fail:
 
578
    xf86IDrvMsg(pInfo, X_ERROR,
 
579
                "invalid SoftButtonAreas value '%s', keeping defaults\n",
578
580
                option_string);
579
581
}
580
582
 
581
 
static void set_default_parameters(InputInfoPtr pInfo)
 
583
static void
 
584
set_default_parameters(InputInfoPtr pInfo)
582
585
{
583
 
    SynapticsPrivate *priv = pInfo->private; /* read-only */
584
 
    pointer opts = pInfo->options; /* read-only */
 
586
    SynapticsPrivate *priv = pInfo->private;    /* read-only */
 
587
    pointer opts = pInfo->options;      /* read-only */
585
588
    SynapticsParameters *pars = &priv->synpara; /* modified */
586
589
 
587
 
    int horizScrollDelta, vertScrollDelta;              /* pixels */
588
 
    int tapMove;                                        /* pixels */
589
 
    int l, r, t, b; /* left, right, top, bottom */
590
 
    int edgeMotionMinSpeed, edgeMotionMaxSpeed;         /* pixels/second */
591
 
    double accelFactor;                                 /* 1/pixels */
592
 
    int fingerLow, fingerHigh, fingerPress;             /* pressure */
593
 
    int emulateTwoFingerMinZ;                           /* pressure */
594
 
    int emulateTwoFingerMinW;                           /* width */
595
 
    int edgeMotionMinZ, edgeMotionMaxZ;                 /* pressure */
596
 
    int pressureMotionMinZ, pressureMotionMaxZ;         /* pressure */
597
 
    int palmMinWidth, palmMinZ;                         /* pressure */
 
590
    int horizScrollDelta, vertScrollDelta;      /* pixels */
 
591
    int tapMove;                /* pixels */
 
592
    int l, r, t, b;             /* left, right, top, bottom */
 
593
    int edgeMotionMinSpeed, edgeMotionMaxSpeed; /* pixels/second */
 
594
    double accelFactor;         /* 1/pixels */
 
595
    int fingerLow, fingerHigh, fingerPress;     /* pressure */
 
596
    int emulateTwoFingerMinZ;   /* pressure */
 
597
    int emulateTwoFingerMinW;   /* width */
 
598
    int edgeMotionMinZ, edgeMotionMaxZ; /* pressure */
 
599
    int pressureMotionMinZ, pressureMotionMaxZ; /* pressure */
 
600
    int palmMinWidth, palmMinZ; /* pressure */
598
601
    int tapButton1, tapButton2, tapButton3;
599
602
    int clickFinger1, clickFinger2, clickFinger3;
600
603
    Bool vertEdgeScroll, horizEdgeScroll;
607
610
 
608
611
    /* read the parameters */
609
612
    if (priv->synshm)
610
 
        priv->synshm->version = (PACKAGE_VERSION_MAJOR*10000+PACKAGE_VERSION_MINOR*100+PACKAGE_VERSION_PATCHLEVEL);
 
613
        priv->synshm->version =
 
614
            (PACKAGE_VERSION_MAJOR * 10000 + PACKAGE_VERSION_MINOR * 100 +
 
615
             PACKAGE_VERSION_PATCHLEVEL);
611
616
 
612
617
    /* The synaptics specs specify typical edge widths of 4% on x, and 5.4% on
613
618
     * y (page 7) [Synaptics TouchPad Interfacing Guide, 510-000080 - A
640
645
 
641
646
    range = priv->maxp - priv->minp + 1;
642
647
 
643
 
    calculate_tap_hysteresis(priv, range, &fingerLow, &fingerHigh, &fingerPress);
 
648
    calculate_tap_hysteresis(priv, range, &fingerLow, &fingerHigh,
 
649
                             &fingerPress);
644
650
 
645
651
    /* scaling based on defaults and a pressure of 256 */
646
 
    emulateTwoFingerMinZ = priv->minp + range * (282.0/256);
647
 
    edgeMotionMinZ = priv->minp + range * (30.0/256);
648
 
    edgeMotionMaxZ = priv->minp + range * (160.0/256);
649
 
    pressureMotionMinZ = priv->minp + range * (30.0/256);
650
 
    pressureMotionMaxZ = priv->minp + range * (160.0/256);
651
 
    palmMinZ = priv->minp + range * (200.0/256);
 
652
    emulateTwoFingerMinZ = priv->minp + range * (282.0 / 256);
 
653
    edgeMotionMinZ = priv->minp + range * (30.0 / 256);
 
654
    edgeMotionMaxZ = priv->minp + range * (160.0 / 256);
 
655
    pressureMotionMinZ = priv->minp + range * (30.0 / 256);
 
656
    pressureMotionMaxZ = priv->minp + range * (160.0 / 256);
 
657
    palmMinZ = priv->minp + range * (200.0 / 256);
652
658
 
653
659
    range = priv->maxw - priv->minw + 1;
654
660
 
655
661
    /* scaling based on defaults below and a tool width of 16 */
656
 
    palmMinWidth = priv->minw + range * (10.0/16);
657
 
    emulateTwoFingerMinW = priv->minw + range * (7.0/16);
 
662
    palmMinWidth = priv->minw + range * (10.0 / 16);
 
663
    emulateTwoFingerMinW = priv->minw + range * (7.0 / 16);
658
664
 
659
665
    /* Enable tap if we don't have a phys left button */
660
666
    tapButton1 = priv->has_left ? 0 : 1;
687
693
    pars->top_edge = xf86SetIntOption(opts, "TopEdge", t);
688
694
    pars->bottom_edge = xf86SetIntOption(opts, "BottomEdge", b);
689
695
 
690
 
    pars->area_top_edge = set_percent_option(opts, "AreaTopEdge", height, priv->miny, 0);
691
 
    pars->area_bottom_edge = set_percent_option(opts, "AreaBottomEdge", height, priv->miny, 0);
692
 
    pars->area_left_edge = set_percent_option(opts, "AreaLeftEdge", width, priv->minx, 0);
693
 
    pars->area_right_edge = set_percent_option(opts, "AreaRightEdge", width, priv->minx, 0);
 
696
    pars->area_top_edge =
 
697
        set_percent_option(opts, "AreaTopEdge", height, priv->miny, 0);
 
698
    pars->area_bottom_edge =
 
699
        set_percent_option(opts, "AreaBottomEdge", height, priv->miny, 0);
 
700
    pars->area_left_edge =
 
701
        set_percent_option(opts, "AreaLeftEdge", width, priv->minx, 0);
 
702
    pars->area_right_edge =
 
703
        set_percent_option(opts, "AreaRightEdge", width, priv->minx, 0);
694
704
 
695
 
    pars->hyst_x = set_percent_option(opts, "HorizHysteresis", width, 0, horizHyst);
696
 
    pars->hyst_y = set_percent_option(opts, "VertHysteresis", height, 0, vertHyst);
 
705
    pars->hyst_x =
 
706
        set_percent_option(opts, "HorizHysteresis", width, 0, horizHyst);
 
707
    pars->hyst_y =
 
708
        set_percent_option(opts, "VertHysteresis", height, 0, vertHyst);
697
709
 
698
710
    pars->finger_low = xf86SetIntOption(opts, "FingerLow", fingerLow);
699
711
    pars->finger_high = xf86SetIntOption(opts, "FingerHigh", fingerHigh);
702
714
    pars->tap_move = xf86SetIntOption(opts, "MaxTapMove", tapMove);
703
715
    pars->tap_time_2 = xf86SetIntOption(opts, "MaxDoubleTapTime", 180);
704
716
    pars->click_time = xf86SetIntOption(opts, "ClickTime", 100);
705
 
    pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad); /* Probed */
 
717
    pars->clickpad = xf86SetBoolOption(opts, "ClickPad", pars->clickpad);       /* Probed */
706
718
    pars->fast_taps = xf86SetBoolOption(opts, "FastTaps", FALSE);
707
719
    /* middle mouse button emulation on a clickpad? nah, you're joking */
708
720
    middle_button_timeout = pars->clickpad ? 0 : 75;
709
 
    pars->emulate_mid_button_time = xf86SetIntOption(opts, "EmulateMidButtonTime", middle_button_timeout);
710
 
    pars->emulate_twofinger_z = xf86SetIntOption(opts, "EmulateTwoFingerMinZ", emulateTwoFingerMinZ);
711
 
    pars->emulate_twofinger_w = xf86SetIntOption(opts, "EmulateTwoFingerMinW", emulateTwoFingerMinW);
712
 
    pars->scroll_dist_vert = xf86SetIntOption(opts, "VertScrollDelta", vertScrollDelta);
713
 
    pars->scroll_dist_horiz = xf86SetIntOption(opts, "HorizScrollDelta", horizScrollDelta);
714
 
    pars->scroll_edge_vert = xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll);
715
 
    pars->scroll_edge_horiz = xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll);
 
721
    pars->emulate_mid_button_time =
 
722
        xf86SetIntOption(opts, "EmulateMidButtonTime", middle_button_timeout);
 
723
    pars->emulate_twofinger_z =
 
724
        xf86SetIntOption(opts, "EmulateTwoFingerMinZ", emulateTwoFingerMinZ);
 
725
    pars->emulate_twofinger_w =
 
726
        xf86SetIntOption(opts, "EmulateTwoFingerMinW", emulateTwoFingerMinW);
 
727
    pars->scroll_dist_vert =
 
728
        xf86SetIntOption(opts, "VertScrollDelta", vertScrollDelta);
 
729
    pars->scroll_dist_horiz =
 
730
        xf86SetIntOption(opts, "HorizScrollDelta", horizScrollDelta);
 
731
    pars->scroll_edge_vert =
 
732
        xf86SetBoolOption(opts, "VertEdgeScroll", vertEdgeScroll);
 
733
    pars->scroll_edge_horiz =
 
734
        xf86SetBoolOption(opts, "HorizEdgeScroll", horizEdgeScroll);
716
735
    pars->scroll_edge_corner = xf86SetBoolOption(opts, "CornerCoasting", FALSE);
717
 
    pars->scroll_twofinger_vert = xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll);
718
 
    pars->scroll_twofinger_horiz = xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll);
719
 
    pars->edge_motion_min_z = xf86SetIntOption(opts, "EdgeMotionMinZ", edgeMotionMinZ);
720
 
    pars->edge_motion_max_z = xf86SetIntOption(opts, "EdgeMotionMaxZ", edgeMotionMaxZ);
721
 
    pars->edge_motion_min_speed = xf86SetIntOption(opts, "EdgeMotionMinSpeed", edgeMotionMinSpeed);
722
 
    pars->edge_motion_max_speed = xf86SetIntOption(opts, "EdgeMotionMaxSpeed", edgeMotionMaxSpeed);
723
 
    pars->edge_motion_use_always = xf86SetBoolOption(opts, "EdgeMotionUseAlways", FALSE);
 
736
    pars->scroll_twofinger_vert =
 
737
        xf86SetBoolOption(opts, "VertTwoFingerScroll", vertTwoFingerScroll);
 
738
    pars->scroll_twofinger_horiz =
 
739
        xf86SetBoolOption(opts, "HorizTwoFingerScroll", horizTwoFingerScroll);
 
740
    pars->edge_motion_min_z =
 
741
        xf86SetIntOption(opts, "EdgeMotionMinZ", edgeMotionMinZ);
 
742
    pars->edge_motion_max_z =
 
743
        xf86SetIntOption(opts, "EdgeMotionMaxZ", edgeMotionMaxZ);
 
744
    pars->edge_motion_min_speed =
 
745
        xf86SetIntOption(opts, "EdgeMotionMinSpeed", edgeMotionMinSpeed);
 
746
    pars->edge_motion_max_speed =
 
747
        xf86SetIntOption(opts, "EdgeMotionMaxSpeed", edgeMotionMaxSpeed);
 
748
    pars->edge_motion_use_always =
 
749
        xf86SetBoolOption(opts, "EdgeMotionUseAlways", FALSE);
724
750
    if (priv->has_scrollbuttons) {
725
 
        pars->updown_button_scrolling = xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
726
 
        pars->leftright_button_scrolling = xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
727
 
        pars->updown_button_repeat = xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
728
 
        pars->leftright_button_repeat = xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
 
751
        pars->updown_button_scrolling =
 
752
            xf86SetBoolOption(opts, "UpDownScrolling", TRUE);
 
753
        pars->leftright_button_scrolling =
 
754
            xf86SetBoolOption(opts, "LeftRightScrolling", TRUE);
 
755
        pars->updown_button_repeat =
 
756
            xf86SetBoolOption(opts, "UpDownScrollRepeat", TRUE);
 
757
        pars->leftright_button_repeat =
 
758
            xf86SetBoolOption(opts, "LeftRightScrollRepeat", TRUE);
729
759
    }
730
 
    pars->scroll_button_repeat = xf86SetIntOption(opts,"ScrollButtonRepeat", 100);
 
760
    pars->scroll_button_repeat =
 
761
        xf86SetIntOption(opts, "ScrollButtonRepeat", 100);
731
762
    pars->touchpad_off = xf86SetIntOption(opts, "TouchpadOff", 0);
732
763
    pars->locked_drags = xf86SetBoolOption(opts, "LockedDrags", FALSE);
733
764
    pars->locked_drag_time = xf86SetIntOption(opts, "LockedDragTimeout", 5000);
735
766
    pars->tap_action[RB_TAP] = xf86SetIntOption(opts, "RBCornerButton", 0);
736
767
    pars->tap_action[LT_TAP] = xf86SetIntOption(opts, "LTCornerButton", 0);
737
768
    pars->tap_action[LB_TAP] = xf86SetIntOption(opts, "LBCornerButton", 0);
738
 
    pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1",     tapButton1);
739
 
    pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2",     tapButton2);
740
 
    pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3",     tapButton3);
741
 
    pars->click_action[F1_CLICK1] = xf86SetIntOption(opts, "ClickFinger1", clickFinger1);
742
 
    pars->click_action[F2_CLICK1] = xf86SetIntOption(opts, "ClickFinger2", clickFinger2);
743
 
    pars->click_action[F3_CLICK1] = xf86SetIntOption(opts, "ClickFinger3", clickFinger3);
744
 
    pars->circular_scrolling = xf86SetBoolOption(opts, "CircularScrolling", FALSE);
745
 
    pars->circular_trigger   = xf86SetIntOption(opts, "CircScrollTrigger", 0);
746
 
    pars->circular_pad       = xf86SetBoolOption(opts, "CircularPad", FALSE);
747
 
    pars->palm_detect        = xf86SetBoolOption(opts, "PalmDetect", FALSE);
748
 
    pars->palm_min_width     = xf86SetIntOption(opts, "PalmMinWidth", palmMinWidth);
749
 
    pars->palm_min_z         = xf86SetIntOption(opts, "PalmMinZ", palmMinZ);
 
769
    pars->tap_action[F1_TAP] = xf86SetIntOption(opts, "TapButton1", tapButton1);
 
770
    pars->tap_action[F2_TAP] = xf86SetIntOption(opts, "TapButton2", tapButton2);
 
771
    pars->tap_action[F3_TAP] = xf86SetIntOption(opts, "TapButton3", tapButton3);
 
772
    pars->click_action[F1_CLICK1] =
 
773
        xf86SetIntOption(opts, "ClickFinger1", clickFinger1);
 
774
    pars->click_action[F2_CLICK1] =
 
775
        xf86SetIntOption(opts, "ClickFinger2", clickFinger2);
 
776
    pars->click_action[F3_CLICK1] =
 
777
        xf86SetIntOption(opts, "ClickFinger3", clickFinger3);
 
778
    pars->circular_scrolling =
 
779
        xf86SetBoolOption(opts, "CircularScrolling", FALSE);
 
780
    pars->circular_trigger = xf86SetIntOption(opts, "CircScrollTrigger", 0);
 
781
    pars->circular_pad = xf86SetBoolOption(opts, "CircularPad", FALSE);
 
782
    pars->palm_detect = xf86SetBoolOption(opts, "PalmDetect", FALSE);
 
783
    pars->palm_min_width = xf86SetIntOption(opts, "PalmMinWidth", palmMinWidth);
 
784
    pars->palm_min_z = xf86SetIntOption(opts, "PalmMinZ", palmMinZ);
750
785
    pars->single_tap_timeout = xf86SetIntOption(opts, "SingleTapTimeout", 180);
751
 
    pars->press_motion_min_z = xf86SetIntOption(opts, "PressureMotionMinZ", pressureMotionMinZ);
752
 
    pars->press_motion_max_z = xf86SetIntOption(opts, "PressureMotionMaxZ", pressureMotionMaxZ);
 
786
    pars->press_motion_min_z =
 
787
        xf86SetIntOption(opts, "PressureMotionMinZ", pressureMotionMinZ);
 
788
    pars->press_motion_max_z =
 
789
        xf86SetIntOption(opts, "PressureMotionMaxZ", pressureMotionMaxZ);
753
790
 
754
791
    pars->min_speed = xf86SetRealOption(opts, "MinSpeed", 0.4);
755
792
    pars->max_speed = xf86SetRealOption(opts, "MaxSpeed", 0.7);
758
795
    pars->scroll_dist_circ = xf86SetRealOption(opts, "CircScrollDelta", 0.1);
759
796
    pars->coasting_speed = xf86SetRealOption(opts, "CoastingSpeed", 20.0);
760
797
    pars->coasting_friction = xf86SetRealOption(opts, "CoastingFriction", 50);
761
 
    pars->press_motion_min_factor = xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0);
762
 
    pars->press_motion_max_factor = xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0);
 
798
    pars->press_motion_min_factor =
 
799
        xf86SetRealOption(opts, "PressureMotionMinFactor", 1.0);
 
800
    pars->press_motion_max_factor =
 
801
        xf86SetRealOption(opts, "PressureMotionMaxFactor", 1.0);
763
802
    pars->grab_event_device = xf86SetBoolOption(opts, "GrabEventDevice", TRUE);
764
 
    pars->tap_and_drag_gesture = xf86SetBoolOption(opts, "TapAndDragGesture", TRUE);
765
 
    pars->resolution_horiz = xf86SetIntOption(opts, "HorizResolution", horizResolution);
766
 
    pars->resolution_vert = xf86SetIntOption(opts, "VertResolution", vertResolution);
 
803
    pars->tap_and_drag_gesture =
 
804
        xf86SetBoolOption(opts, "TapAndDragGesture", TRUE);
 
805
    pars->resolution_horiz =
 
806
        xf86SetIntOption(opts, "HorizResolution", horizResolution);
 
807
    pars->resolution_vert =
 
808
        xf86SetIntOption(opts, "VertResolution", vertResolution);
767
809
 
768
810
    /* Warn about (and fix) incorrectly configured TopEdge/BottomEdge parameters */
769
811
    if (pars->top_edge > pars->bottom_edge) {
770
 
        int tmp = pars->top_edge;
771
 
        pars->top_edge = pars->bottom_edge;
772
 
        pars->bottom_edge = tmp;
773
 
        xf86IDrvMsg(pInfo, X_WARNING, "TopEdge is bigger than BottomEdge. Fixing.\n");
 
812
        int tmp = pars->top_edge;
 
813
 
 
814
        pars->top_edge = pars->bottom_edge;
 
815
        pars->bottom_edge = tmp;
 
816
        xf86IDrvMsg(pInfo, X_WARNING,
 
817
                    "TopEdge is bigger than BottomEdge. Fixing.\n");
774
818
    }
775
819
 
776
820
    set_softbutton_areas_option(pInfo);
777
821
}
778
822
 
779
823
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 14
780
 
static double SynapticsAccelerationProfile(DeviceIntPtr dev,
781
 
                                           DeviceVelocityPtr vel,
782
 
                                           double velocity,
783
 
                                           double thr,
784
 
                                           double acc) {
 
824
static double
 
825
SynapticsAccelerationProfile(DeviceIntPtr dev,
 
826
                             DeviceVelocityPtr vel,
 
827
                             double velocity, double thr, double acc)
 
828
{
785
829
#else
786
 
static float SynapticsAccelerationProfile(DeviceIntPtr dev,
787
 
                                          DeviceVelocityPtr vel,
788
 
                                          float velocity_f,
789
 
                                          float thr_f,
790
 
                                          float acc_f) {
 
830
static float
 
831
SynapticsAccelerationProfile(DeviceIntPtr dev,
 
832
                             DeviceVelocityPtr vel,
 
833
                             float velocity_f, float thr_f, float acc_f)
 
834
{
791
835
    double velocity = velocity_f;
792
836
    double acc = acc_f;
793
837
#endif
794
838
    InputInfoPtr pInfo = dev->public.devicePrivate;
795
839
    SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
796
 
    SynapticsParameters* para = &priv->synpara;
 
840
    SynapticsParameters *para = &priv->synpara;
797
841
 
798
842
    double accelfct;
799
843
 
808
852
 
809
853
    /* clip acceleration factor */
810
854
    if (accelfct > para->max_speed * acc)
811
 
        accelfct = para->max_speed * acc;
 
855
        accelfct = para->max_speed * acc;
812
856
    else if (accelfct < para->min_speed)
813
 
        accelfct = para->min_speed;
 
857
        accelfct = para->min_speed;
814
858
 
815
859
    /* modify speed according to pressure */
816
860
    if (priv->moving_state == MS_TOUCHPAD_RELATIVE) {
817
 
        int minZ = para->press_motion_min_z;
818
 
        int maxZ = para->press_motion_max_z;
819
 
        double minFctr = para->press_motion_min_factor;
820
 
        double maxFctr = para->press_motion_max_factor;
821
 
        if (priv->hwState->z <= minZ) {
822
 
            accelfct *= minFctr;
823
 
        } else if (priv->hwState->z >= maxZ) {
824
 
            accelfct *= maxFctr;
825
 
        } else {
826
 
            accelfct *= minFctr + (priv->hwState->z - minZ) * (maxFctr - minFctr) / (maxZ - minZ);
827
 
        }
 
861
        int minZ = para->press_motion_min_z;
 
862
        int maxZ = para->press_motion_max_z;
 
863
        double minFctr = para->press_motion_min_factor;
 
864
        double maxFctr = para->press_motion_max_factor;
 
865
 
 
866
        if (priv->hwState->z <= minZ) {
 
867
            accelfct *= minFctr;
 
868
        }
 
869
        else if (priv->hwState->z >= maxZ) {
 
870
            accelfct *= maxFctr;
 
871
        }
 
872
        else {
 
873
            accelfct *=
 
874
                minFctr + (priv->hwState->z - minZ) * (maxFctr -
 
875
                                                       minFctr) / (maxZ - minZ);
 
876
        }
828
877
    }
829
878
 
830
879
    return accelfct;
832
881
 
833
882
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
834
883
static int
835
 
NewSynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
 
884
 NewSynapticsPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
 
885
 
836
886
/*
837
887
 *  called by the module loader for initialization
838
888
 */
844
894
    /* Allocate a new InputInfoRec and add it to the head xf86InputDevs. */
845
895
    pInfo = xf86AllocateInput(drv, 0);
846
896
    if (!pInfo) {
847
 
        return NULL;
 
897
        return NULL;
848
898
    }
849
899
 
850
900
    /* initialize the InputInfoRec */
851
 
    pInfo->name                    = dev->identifier;
 
901
    pInfo->name = dev->identifier;
852
902
    pInfo->reverse_conversion_proc = NULL;
853
 
    pInfo->dev                     = NULL;
854
 
    pInfo->private_flags           = 0;
855
 
    pInfo->flags                   = XI86_SEND_DRAG_EVENTS;
856
 
    pInfo->conf_idev               = dev;
857
 
    pInfo->always_core_feedback    = 0;
 
903
    pInfo->dev = NULL;
 
904
    pInfo->private_flags = 0;
 
905
    pInfo->flags = XI86_SEND_DRAG_EVENTS;
 
906
    pInfo->conf_idev = dev;
 
907
    pInfo->always_core_feedback = 0;
858
908
 
859
909
    xf86CollectInputOptions(pInfo, NULL, NULL);
860
910
 
878
928
    /* allocate memory for SynapticsPrivateRec */
879
929
    priv = calloc(1, sizeof(SynapticsPrivate));
880
930
    if (!priv)
881
 
        return BadAlloc;
 
931
        return BadAlloc;
882
932
 
883
 
    pInfo->type_name               = XI_TOUCHPAD;
884
 
    pInfo->device_control          = DeviceControl;
885
 
    pInfo->read_input              = ReadInput;
886
 
    pInfo->control_proc            = ControlProc;
887
 
    pInfo->switch_mode             = SwitchMode;
888
 
    pInfo->private                 = priv;
 
933
    pInfo->type_name = XI_TOUCHPAD;
 
934
    pInfo->device_control = DeviceControl;
 
935
    pInfo->read_input = ReadInput;
 
936
    pInfo->control_proc = ControlProc;
 
937
    pInfo->switch_mode = SwitchMode;
 
938
    pInfo->private = priv;
889
939
 
890
940
    /* allocate now so we don't allocate in the signal handler */
891
941
    priv->timer = TimerSet(NULL, 0, 0, NULL, NULL);
892
942
    if (!priv->timer) {
893
 
        free(priv);
894
 
        return BadAlloc;
 
943
        free(priv);
 
944
        return BadAlloc;
895
945
    }
896
946
 
897
947
    /* may change pInfo->options */
898
948
    if (!SetDeviceAndProtocol(pInfo)) {
899
 
        xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to detect protocol\n");
 
949
        xf86IDrvMsg(pInfo, X_ERROR,
 
950
                    "Synaptics driver unable to detect protocol\n");
900
951
        goto SetupProc_fail;
901
952
    }
902
953
 
905
956
    /* open the touchpad device */
906
957
    pInfo->fd = xf86OpenSerial(pInfo->options);
907
958
    if (pInfo->fd == -1) {
908
 
        xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to open device\n");
909
 
        goto SetupProc_fail;
 
959
        xf86IDrvMsg(pInfo, X_ERROR, "Synaptics driver unable to open device\n");
 
960
        goto SetupProc_fail;
910
961
    }
911
962
    xf86ErrorFVerb(6, "port opened successfully\n");
912
963
 
932
983
    CalculateScalingCoeffs(priv);
933
984
 
934
985
    if (!alloc_shm_data(pInfo))
935
 
        goto SetupProc_fail;
 
986
        goto SetupProc_fail;
936
987
 
937
988
    priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
938
989
 
939
990
    if (!QueryHardware(pInfo)) {
940
 
        xf86IDrvMsg(pInfo, X_ERROR, "Unable to query/initialize Synaptics hardware.\n");
941
 
        goto SetupProc_fail;
 
991
        xf86IDrvMsg(pInfo, X_ERROR,
 
992
                    "Unable to query/initialize Synaptics hardware.\n");
 
993
        goto SetupProc_fail;
942
994
    }
943
995
 
944
996
    xf86ProcessCommonOptions(pInfo, pInfo->options);
945
997
 
946
998
    if (pInfo->fd != -1) {
947
 
        if (priv->comm.buffer) {
948
 
            XisbFree(priv->comm.buffer);
949
 
            priv->comm.buffer = NULL;
950
 
        }
951
 
        xf86CloseSerial(pInfo->fd);
 
999
        if (priv->comm.buffer) {
 
1000
            XisbFree(priv->comm.buffer);
 
1001
            priv->comm.buffer = NULL;
 
1002
        }
 
1003
        xf86CloseSerial(pInfo->fd);
952
1004
    }
953
1005
    pInfo->fd = -1;
954
1006
 
956
1008
 
957
1009
 SetupProc_fail:
958
1010
    if (pInfo->fd >= 0) {
959
 
        xf86CloseSerial(pInfo->fd);
960
 
        pInfo->fd = -1;
 
1011
        xf86CloseSerial(pInfo->fd);
 
1012
        pInfo->fd = -1;
961
1013
    }
962
1014
 
963
1015
    if (priv->comm.buffer)
964
 
        XisbFree(priv->comm.buffer);
 
1016
        XisbFree(priv->comm.buffer);
965
1017
    free_shm_data(priv);
966
1018
    free(priv->proto_data);
967
1019
    free(priv->timer);
970
1022
    return BadAlloc;
971
1023
}
972
1024
 
973
 
 
974
1025
/*
975
1026
 *  Uninitialize the device.
976
1027
 */
977
 
static void SynapticsUnInit(InputDriverPtr drv,
978
 
                            InputInfoPtr   pInfo,
979
 
                            int            flags)
 
1028
static void
 
1029
SynapticsUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
980
1030
{
981
 
    SynapticsPrivate *priv = ((SynapticsPrivate *)pInfo->private);
 
1031
    SynapticsPrivate *priv = ((SynapticsPrivate *) pInfo->private);
 
1032
 
982
1033
    if (priv && priv->timer)
983
1034
        free(priv->timer);
984
1035
    if (priv && priv->proto_data)
996
1047
    xf86DeleteInput(pInfo, 0);
997
1048
}
998
1049
 
999
 
 
1000
1050
/*
1001
1051
 *  Alter the control parameters for the mouse. Note that all special
1002
1052
 *  protocol values are handled by dix.
1003
1053
 */
1004
1054
static void
1005
 
SynapticsCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
 
1055
SynapticsCtrl(DeviceIntPtr device, PtrCtrl * ctrl)
1006
1056
{
1007
1057
}
1008
1058
 
1013
1063
 
1014
1064
    switch (mode) {
1015
1065
    case DEVICE_INIT:
1016
 
        RetValue = DeviceInit(dev);
1017
 
        break;
 
1066
        RetValue = DeviceInit(dev);
 
1067
        break;
1018
1068
    case DEVICE_ON:
1019
 
        RetValue = DeviceOn(dev);
1020
 
        break;
 
1069
        RetValue = DeviceOn(dev);
 
1070
        break;
1021
1071
    case DEVICE_OFF:
1022
 
        RetValue = DeviceOff(dev);
1023
 
        break;
 
1072
        RetValue = DeviceOff(dev);
 
1073
        break;
1024
1074
    case DEVICE_CLOSE:
1025
 
        RetValue = DeviceClose(dev);
1026
 
        break;
 
1075
        RetValue = DeviceClose(dev);
 
1076
        break;
1027
1077
    default:
1028
 
        RetValue = BadValue;
 
1078
        RetValue = BadValue;
1029
1079
    }
1030
1080
 
1031
1081
    return RetValue;
1041
1091
 
1042
1092
    pInfo->fd = xf86OpenSerial(pInfo->options);
1043
1093
    if (pInfo->fd == -1) {
1044
 
        xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n");
1045
 
        return !Success;
 
1094
        xf86IDrvMsg(pInfo, X_WARNING, "cannot open input device\n");
 
1095
        return !Success;
1046
1096
    }
1047
1097
 
1048
1098
    if (priv->proto_ops->DeviceOnHook &&
1051
1101
 
1052
1102
    priv->comm.buffer = XisbNew(pInfo->fd, INPUT_BUFFER_SIZE);
1053
1103
    if (!priv->comm.buffer) {
1054
 
        xf86CloseSerial(pInfo->fd);
1055
 
        pInfo->fd = -1;
1056
 
        return !Success;
 
1104
        xf86CloseSerial(pInfo->fd);
 
1105
        pInfo->fd = -1;
 
1106
        return !Success;
1057
1107
    }
1058
1108
 
1059
1109
    xf86FlushInput(pInfo->fd);
1060
1110
 
1061
1111
    /* reinit the pad */
1062
 
    if (!QueryHardware(pInfo))
1063
 
    {
 
1112
    if (!QueryHardware(pInfo)) {
1064
1113
        XisbFree(priv->comm.buffer);
1065
1114
        priv->comm.buffer = NULL;
1066
1115
        xf86CloseSerial(pInfo->fd);
1075
1124
}
1076
1125
 
1077
1126
static void
1078
 
SynapticsReset(SynapticsPrivate *priv)
 
1127
SynapticsReset(SynapticsPrivate * priv)
1079
1128
{
1080
1129
    SynapticsResetHwState(priv->hwState);
1081
1130
    SynapticsResetHwState(priv->local_hw_state);
1106
1155
    priv->prevFingers = 0;
1107
1156
}
1108
1157
 
1109
 
 
1110
1158
static Bool
1111
1159
DeviceOff(DeviceIntPtr dev)
1112
1160
{
1117
1165
    DBG(3, "Synaptics DeviceOff called\n");
1118
1166
 
1119
1167
    if (pInfo->fd != -1) {
1120
 
        TimerCancel(priv->timer);
1121
 
        xf86RemoveEnabledDevice(pInfo);
1122
 
        SynapticsReset(priv);
 
1168
        TimerCancel(priv->timer);
 
1169
        xf86RemoveEnabledDevice(pInfo);
 
1170
        SynapticsReset(priv);
1123
1171
 
1124
1172
        if (priv->proto_ops->DeviceOffHook &&
1125
1173
            !priv->proto_ops->DeviceOffHook(pInfo))
1126
1174
            rc = !Success;
1127
 
        if (priv->comm.buffer) {
1128
 
            XisbFree(priv->comm.buffer);
1129
 
            priv->comm.buffer = NULL;
1130
 
        }
1131
 
        xf86CloseSerial(pInfo->fd);
1132
 
        pInfo->fd = -1;
 
1175
        if (priv->comm.buffer) {
 
1176
            XisbFree(priv->comm.buffer);
 
1177
            priv->comm.buffer = NULL;
 
1178
        }
 
1179
        xf86CloseSerial(pInfo->fd);
 
1180
        pInfo->fd = -1;
1133
1181
    }
1134
1182
    dev->public.on = FALSE;
1135
1183
    return rc;
1153
1201
    return RetValue;
1154
1202
}
1155
1203
 
1156
 
static void InitAxesLabels(Atom *labels, int nlabels,
1157
 
                           const SynapticsPrivate *priv)
 
1204
static void
 
1205
InitAxesLabels(Atom *labels, int nlabels, const SynapticsPrivate * priv)
1158
1206
{
1159
1207
#ifdef HAVE_MULTITOUCH
1160
1208
    int i;
1161
1209
#endif
1162
1210
 
1163
1211
    memset(labels, 0, nlabels * sizeof(Atom));
1164
 
    switch(nlabels)
1165
 
    {
1166
 
        default:
 
1212
    switch (nlabels) {
 
1213
    default:
1167
1214
#ifdef HAVE_SMOOTH_SCROLL
1168
 
        case 4:
1169
 
            labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
1170
 
        case 3:
1171
 
            labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
 
1215
    case 4:
 
1216
        labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
 
1217
    case 3:
 
1218
        labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
1172
1219
#endif
1173
 
        case 2:
1174
 
            labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
1175
 
        case 1:
1176
 
            labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
1177
 
            break;
 
1220
    case 2:
 
1221
        labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
 
1222
    case 1:
 
1223
        labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
 
1224
        break;
1178
1225
    }
1179
1226
 
1180
1227
#ifdef HAVE_MULTITOUCH
1181
 
    for (i = 0; i < priv->num_mt_axes; i++)
1182
 
    {
 
1228
    for (i = 0; i < priv->num_mt_axes; i++) {
1183
1229
        SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
1184
1230
        int axnum = nlabels - priv->num_mt_axes + i;
 
1231
 
1185
1232
        labels[axnum] = XIGetKnownProperty(axis->label);
1186
1233
    }
1187
1234
#endif
1188
1235
}
1189
1236
 
1190
 
static void InitButtonLabels(Atom *labels, int nlabels)
 
1237
static void
 
1238
InitButtonLabels(Atom *labels, int nlabels)
1191
1239
{
1192
1240
    memset(labels, 0, nlabels * sizeof(Atom));
1193
 
    switch(nlabels)
1194
 
    {
1195
 
        default:
1196
 
        case 7:
1197
 
            labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
1198
 
        case 6:
1199
 
            labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
1200
 
        case 5:
1201
 
            labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
1202
 
        case 4:
1203
 
            labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
1204
 
        case 3:
1205
 
            labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
1206
 
        case 2:
1207
 
            labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
1208
 
        case 1:
1209
 
            labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
1210
 
            break;
 
1241
    switch (nlabels) {
 
1242
    default:
 
1243
    case 7:
 
1244
        labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
 
1245
    case 6:
 
1246
        labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
 
1247
    case 5:
 
1248
        labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
 
1249
    case 4:
 
1250
        labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
 
1251
    case 3:
 
1252
        labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
 
1253
    case 2:
 
1254
        labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
 
1255
    case 1:
 
1256
        labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
 
1257
        break;
1211
1258
    }
1212
1259
}
1213
1260
 
1219
1266
    SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
1220
1267
    int i;
1221
1268
 
1222
 
    if (priv->has_touch)
1223
 
    {
1224
 
        priv->num_slots = priv->max_touches ? priv->max_touches : SYNAPTICS_MAX_TOUCHES;
 
1269
    if (priv->has_touch) {
 
1270
        priv->num_slots =
 
1271
            priv->max_touches ? priv->max_touches : SYNAPTICS_MAX_TOUCHES;
1225
1272
 
1226
1273
        priv->open_slots = malloc(priv->num_slots * sizeof(int));
1227
 
        if (!priv->open_slots)
1228
 
        {
 
1274
        if (!priv->open_slots) {
1229
1275
            xf86IDrvMsg(pInfo, X_ERROR,
1230
1276
                        "failed to allocate open touch slots array\n");
1231
1277
            priv->has_touch = 0;
1235
1281
 
1236
1282
        /* x/y + whatever other MT axes we found */
1237
1283
        if (!InitTouchClassDeviceStruct(dev, priv->max_touches,
1238
 
                                        XIDependentTouch, 2 + priv->num_mt_axes))
1239
 
        {
 
1284
                                        XIDependentTouch,
 
1285
                                        2 + priv->num_mt_axes)) {
1240
1286
            xf86IDrvMsg(pInfo, X_ERROR,
1241
1287
                        "failed to initialize touch class device\n");
1242
1288
            priv->has_touch = 0;
1246
1292
            return;
1247
1293
        }
1248
1294
 
1249
 
        for (i = 0; i < priv->num_mt_axes; i++)
1250
 
        {
 
1295
        for (i = 0; i < priv->num_mt_axes; i++) {
1251
1296
            SynapticsTouchAxisRec *axis = &priv->touch_axes[i];
1252
 
            int axnum = 4 + i; /* Skip x, y, and scroll axes */
 
1297
            int axnum = 4 + i;  /* Skip x, y, and scroll axes */
1253
1298
 
1254
1299
            if (!xf86InitValuatorAxisStruct(dev, axnum, axes_labels[axnum],
1255
1300
                                            axis->min, axis->max, axis->res, 0,
1256
 
                                            axis->res, Absolute))
1257
 
            {
 
1301
                                            axis->res, Absolute)) {
1258
1302
                xf86IDrvMsg(pInfo, X_WARNING,
1259
1303
                            "failed to initialize axis %s, skipping\n",
1260
1304
                            axis->label);
1291
1335
#endif
1292
1336
 
1293
1337
    axes_labels = calloc(num_axes, sizeof(Atom));
1294
 
    if (!axes_labels)
1295
 
    {
 
1338
    if (!axes_labels) {
1296
1339
        xf86IDrvMsg(pInfo, X_ERROR, "failed to allocate axis labels\n");
1297
1340
        return !Success;
1298
1341
    }
1303
1346
    DBG(3, "Synaptics DeviceInit called\n");
1304
1347
 
1305
1348
    for (i = 0; i <= SYN_MAX_BUTTONS; i++)
1306
 
        map[i] = i;
 
1349
        map[i] = i;
1307
1350
 
1308
1351
    dev->public.on = FALSE;
1309
1352
 
1310
 
    InitPointerDeviceStruct((DevicePtr)dev, map,
1311
 
                            SYN_MAX_BUTTONS,
 
1353
    InitPointerDeviceStruct((DevicePtr) dev, map,
 
1354
                            SYN_MAX_BUTTONS,
1312
1355
                            btn_labels,
1313
 
                            SynapticsCtrl,
1314
 
                            GetMotionHistorySize(),
1315
 
                            num_axes,
1316
 
                            axes_labels);
 
1356
                            SynapticsCtrl,
 
1357
                            GetMotionHistorySize(), num_axes, axes_labels);
1317
1358
 
1318
1359
    /*
1319
1360
     * setup dix acceleration to match legacy synaptics settings, and
1321
1362
     * acceleration.
1322
1363
     */
1323
1364
    if (NULL != (pVel = GetDevicePredictableAccelData(dev))) {
1324
 
        SetDeviceSpecificAccelerationProfile(pVel,
1325
 
                                             SynapticsAccelerationProfile);
1326
 
 
1327
 
        /* float property type */
1328
 
        float_type = XIGetKnownProperty(XATOM_FLOAT);
1329
 
 
1330
 
        /* translate MinAcc to constant deceleration.
1331
 
         * May be overridden in xf86InitValuatorDefaults */
1332
 
        tmpf = 1.0 / priv->synpara.min_speed;
1333
 
 
1334
 
        xf86IDrvMsg(pInfo, X_CONFIG, "(accel) MinSpeed is now constant deceleration "
1335
 
                    "%.1f\n", tmpf);
1336
 
        prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
1337
 
        XIChangeDeviceProperty(dev, prop, float_type, 32,
1338
 
                               PropModeReplace, 1, &tmpf, FALSE);
1339
 
 
1340
 
        /* adjust accordingly */
1341
 
        priv->synpara.max_speed /= priv->synpara.min_speed;
1342
 
        priv->synpara.min_speed = 1.0;
1343
 
 
1344
 
        /* synaptics seems to report 80 packet/s, but dix scales for
1345
 
         * 100 packet/s by default. */
1346
 
        pVel->corr_mul = 12.5f; /*1000[ms]/80[/s] = 12.5 */
1347
 
 
1348
 
        xf86IDrvMsg(pInfo, X_CONFIG, "MaxSpeed is now %.2f\n",
1349
 
                    priv->synpara.max_speed);
1350
 
        xf86IDrvMsg(pInfo, X_CONFIG, "AccelFactor is now %.3f\n",
1351
 
                    priv->synpara.accl);
1352
 
 
1353
 
        prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
1354
 
        i = AccelProfileDeviceSpecific;
1355
 
        XIChangeDeviceProperty(dev, prop, XA_INTEGER, 32,
1356
 
                               PropModeReplace, 1, &i, FALSE);
 
1365
        SetDeviceSpecificAccelerationProfile(pVel,
 
1366
                                             SynapticsAccelerationProfile);
 
1367
 
 
1368
        /* float property type */
 
1369
        float_type = XIGetKnownProperty(XATOM_FLOAT);
 
1370
 
 
1371
        /* translate MinAcc to constant deceleration.
 
1372
         * May be overridden in xf86InitValuatorDefaults */
 
1373
        tmpf = 1.0 / priv->synpara.min_speed;
 
1374
 
 
1375
        xf86IDrvMsg(pInfo, X_CONFIG,
 
1376
                    "(accel) MinSpeed is now constant deceleration " "%.1f\n",
 
1377
                    tmpf);
 
1378
        prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION);
 
1379
        XIChangeDeviceProperty(dev, prop, float_type, 32,
 
1380
                               PropModeReplace, 1, &tmpf, FALSE);
 
1381
 
 
1382
        /* adjust accordingly */
 
1383
        priv->synpara.max_speed /= priv->synpara.min_speed;
 
1384
        priv->synpara.min_speed = 1.0;
 
1385
 
 
1386
        /* synaptics seems to report 80 packet/s, but dix scales for
 
1387
         * 100 packet/s by default. */
 
1388
        pVel->corr_mul = 12.5f; /*1000[ms]/80[/s] = 12.5 */
 
1389
 
 
1390
        xf86IDrvMsg(pInfo, X_CONFIG, "MaxSpeed is now %.2f\n",
 
1391
                    priv->synpara.max_speed);
 
1392
        xf86IDrvMsg(pInfo, X_CONFIG, "AccelFactor is now %.3f\n",
 
1393
                    priv->synpara.accl);
 
1394
 
 
1395
        prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER);
 
1396
        i = AccelProfileDeviceSpecific;
 
1397
        XIChangeDeviceProperty(dev, prop, XA_INTEGER, 32,
 
1398
                               PropModeReplace, 1, &i, FALSE);
1357
1399
    }
1358
1400
 
1359
1401
    /* X valuator */
1360
 
    if (priv->minx < priv->maxx)
1361
 
    {
 
1402
    if (priv->minx < priv->maxx) {
1362
1403
        min = priv->minx;
1363
1404
        max = priv->maxx;
1364
 
    } else
1365
 
    {
 
1405
    }
 
1406
    else {
1366
1407
        min = 0;
1367
1408
        max = -1;
1368
1409
    }
1369
1410
 
1370
1411
    xf86InitValuatorAxisStruct(dev, 0, axes_labels[0],
1371
 
            min, max, priv->resx * 1000, 0, priv->resx * 1000
 
1412
                               min, max, priv->resx * 1000, 0, priv->resx * 1000
1372
1413
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
1373
 
            , Relative
 
1414
                               , Relative
1374
1415
#endif
1375
 
            );
 
1416
        );
1376
1417
    xf86InitValuatorDefaults(dev, 0);
1377
1418
 
1378
1419
    /* Y valuator */
1379
 
    if (priv->miny < priv->maxy)
1380
 
    {
 
1420
    if (priv->miny < priv->maxy) {
1381
1421
        min = priv->miny;
1382
1422
        max = priv->maxy;
1383
 
    } else
1384
 
    {
 
1423
    }
 
1424
    else {
1385
1425
        min = 0;
1386
1426
        max = -1;
1387
1427
    }
1388
1428
 
1389
1429
    xf86InitValuatorAxisStruct(dev, 1, axes_labels[1],
1390
 
            min, max, priv->resy * 1000, 0, priv->resy * 1000
 
1430
                               min, max, priv->resy * 1000, 0, priv->resy * 1000
1391
1431
#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
1392
 
            , Relative
 
1432
                               , Relative
1393
1433
#endif
1394
 
            );
 
1434
        );
1395
1435
    xf86InitValuatorDefaults(dev, 1);
1396
1436
 
1397
1437
#ifdef HAVE_SMOOTH_SCROLL
1402
1442
                               Relative);
1403
1443
    priv->scroll_axis_vert = 3;
1404
1444
    priv->scroll_events_mask = valuator_mask_new(MAX_VALUATORS);
1405
 
    if (!priv->scroll_events_mask)
1406
 
    {
 
1445
    if (!priv->scroll_events_mask) {
1407
1446
        free(axes_labels);
1408
1447
        return !Success;
1409
1448
    }
1428
1467
 
1429
1468
    priv->local_hw_state = SynapticsHwStateAlloc(priv);
1430
1469
    if (!priv->local_hw_state)
1431
 
        goto fail;
 
1470
        goto fail;
1432
1471
 
1433
1472
    priv->comm.hwState = SynapticsHwStateAlloc(priv);
1434
1473
 
1440
1479
 
1441
1480
    return Success;
1442
1481
 
1443
 
fail:
 
1482
 fail:
1444
1483
    free_shm_data(priv);
1445
1484
    free(priv->local_hw_state);
1446
1485
    free(priv->hwState);
1450
1489
    return !Success;
1451
1490
}
1452
1491
 
1453
 
 
1454
1492
/*
1455
1493
 * Convert from absolute X/Y coordinates to a coordinate system where
1456
1494
 * -1 corresponds to the left/upper edge and +1 corresponds to the
1457
1495
 * right/lower edge.
1458
1496
 */
1459
1497
static void
1460
 
relative_coords(SynapticsPrivate *priv, int x, int y,
1461
 
                double *relX, double *relY)
 
1498
relative_coords(SynapticsPrivate * priv, int x, int y,
 
1499
                double *relX, double *relY)
1462
1500
{
1463
1501
    int minX = priv->synpara.left_edge;
1464
1502
    int maxX = priv->synpara.right_edge;
1468
1506
    double yCenter = (minY + maxY) / 2.0;
1469
1507
 
1470
1508
    if ((maxX - xCenter > 0) && (maxY - yCenter > 0)) {
1471
 
        *relX = (x - xCenter) / (maxX - xCenter);
1472
 
        *relY = (y - yCenter) / (maxY - yCenter);
1473
 
    } else {
1474
 
        *relX = 0;
1475
 
        *relY = 0;
 
1509
        *relX = (x - xCenter) / (maxX - xCenter);
 
1510
        *relY = (y - yCenter) / (maxY - yCenter);
 
1511
    }
 
1512
    else {
 
1513
        *relX = 0;
 
1514
        *relY = 0;
1476
1515
    }
1477
1516
}
1478
1517
 
1479
1518
/* return angle of point relative to center */
1480
1519
static double
1481
 
angle(SynapticsPrivate *priv, int x, int y)
 
1520
angle(SynapticsPrivate * priv, int x, int y)
1482
1521
{
1483
1522
    double xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2.0;
1484
1523
    double yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2.0;
1491
1530
diffa(double a1, double a2)
1492
1531
{
1493
1532
    double da = fmod(a2 - a1, 2 * M_PI);
 
1533
 
1494
1534
    if (da < 0)
1495
 
        da += 2 * M_PI;
 
1535
        da += 2 * M_PI;
1496
1536
    if (da > M_PI)
1497
 
        da -= 2 * M_PI;
 
1537
        da -= 2 * M_PI;
1498
1538
    return da;
1499
1539
}
1500
1540
 
1501
1541
static edge_type
1502
 
circular_edge_detection(SynapticsPrivate *priv, int x, int y)
 
1542
circular_edge_detection(SynapticsPrivate * priv, int x, int y)
1503
1543
{
1504
1544
    edge_type edge = 0;
1505
1545
    double relX, relY, relR;
1508
1548
    relR = SQR(relX) + SQR(relY);
1509
1549
 
1510
1550
    if (relR > 1) {
1511
 
        /* we are outside the ellipse enclosed by the edge parameters */
1512
 
        if (relX > M_SQRT1_2)
1513
 
            edge |= RIGHT_EDGE;
1514
 
        else if (relX < -M_SQRT1_2)
1515
 
            edge |= LEFT_EDGE;
 
1551
        /* we are outside the ellipse enclosed by the edge parameters */
 
1552
        if (relX > M_SQRT1_2)
 
1553
            edge |= RIGHT_EDGE;
 
1554
        else if (relX < -M_SQRT1_2)
 
1555
            edge |= LEFT_EDGE;
1516
1556
 
1517
 
        if (relY < -M_SQRT1_2)
1518
 
            edge |= TOP_EDGE;
1519
 
        else if (relY > M_SQRT1_2)
1520
 
            edge |= BOTTOM_EDGE;
 
1557
        if (relY < -M_SQRT1_2)
 
1558
            edge |= TOP_EDGE;
 
1559
        else if (relY > M_SQRT1_2)
 
1560
            edge |= BOTTOM_EDGE;
1521
1561
    }
1522
1562
 
1523
1563
    return edge;
1524
1564
}
1525
1565
 
1526
1566
static edge_type
1527
 
edge_detection(SynapticsPrivate *priv, int x, int y)
 
1567
edge_detection(SynapticsPrivate * priv, int x, int y)
1528
1568
{
1529
1569
    edge_type edge = NO_EDGE;
1530
1570
 
1531
1571
    if (priv->synpara.circular_pad)
1532
 
        return circular_edge_detection(priv, x, y);
 
1572
        return circular_edge_detection(priv, x, y);
1533
1573
 
1534
1574
    if (x > priv->synpara.right_edge)
1535
 
        edge |= RIGHT_EDGE;
 
1575
        edge |= RIGHT_EDGE;
1536
1576
    else if (x < priv->synpara.left_edge)
1537
 
        edge |= LEFT_EDGE;
 
1577
        edge |= LEFT_EDGE;
1538
1578
 
1539
1579
    if (y < priv->synpara.top_edge)
1540
 
        edge |= TOP_EDGE;
 
1580
        edge |= TOP_EDGE;
1541
1581
    else if (y > priv->synpara.bottom_edge)
1542
 
        edge |= BOTTOM_EDGE;
 
1582
        edge |= BOTTOM_EDGE;
1543
1583
 
1544
1584
    return edge;
1545
1585
}
1550
1590
 * all set to zero), the function returns TRUE.
1551
1591
 */
1552
1592
static Bool
1553
 
is_inside_active_area(SynapticsPrivate *priv, int x, int y)
 
1593
is_inside_active_area(SynapticsPrivate * priv, int x, int y)
1554
1594
{
1555
1595
    Bool inside_area = TRUE;
1556
1596
 
1557
 
    if ((priv->synpara.area_left_edge != 0) && (x < priv->synpara.area_left_edge))
1558
 
        inside_area = FALSE;
1559
 
    else if ((priv->synpara.area_right_edge != 0) && (x > priv->synpara.area_right_edge))
1560
 
        inside_area = FALSE;
 
1597
    if ((priv->synpara.area_left_edge != 0) &&
 
1598
        (x < priv->synpara.area_left_edge))
 
1599
        inside_area = FALSE;
 
1600
    else if ((priv->synpara.area_right_edge != 0) &&
 
1601
             (x > priv->synpara.area_right_edge))
 
1602
        inside_area = FALSE;
1561
1603
 
1562
1604
    if ((priv->synpara.area_top_edge != 0) && (y < priv->synpara.area_top_edge))
1563
 
        inside_area = FALSE;
1564
 
    else if ((priv->synpara.area_bottom_edge != 0) && (y > priv->synpara.area_bottom_edge))
1565
 
        inside_area = FALSE;
 
1605
        inside_area = FALSE;
 
1606
    else if ((priv->synpara.area_bottom_edge != 0) &&
 
1607
             (y > priv->synpara.area_bottom_edge))
 
1608
        inside_area = FALSE;
1566
1609
 
1567
1610
    return inside_area;
1568
1611
}
1569
1612
 
1570
1613
static Bool
1571
 
is_inside_button_area(SynapticsParameters *para, int which, int x, int y)
 
1614
is_inside_button_area(SynapticsParameters * para, int which, int x, int y)
1572
1615
{
1573
1616
    Bool inside_area = TRUE;
1574
1617
 
1580
1623
 
1581
1624
    if (para->softbutton_areas[which][0] &&
1582
1625
        x < para->softbutton_areas[which][0])
1583
 
        inside_area = FALSE;
 
1626
        inside_area = FALSE;
1584
1627
    else if (para->softbutton_areas[which][1] &&
1585
1628
             x > para->softbutton_areas[which][1])
1586
 
        inside_area = FALSE;
 
1629
        inside_area = FALSE;
1587
1630
    else if (para->softbutton_areas[which][2] &&
1588
1631
             y < para->softbutton_areas[which][2])
1589
 
        inside_area = FALSE;
 
1632
        inside_area = FALSE;
1590
1633
    else if (para->softbutton_areas[which][3] &&
1591
1634
             y > para->softbutton_areas[which][3])
1592
 
        inside_area = FALSE;
 
1635
        inside_area = FALSE;
1593
1636
 
1594
1637
    return inside_area;
1595
1638
}
1596
1639
 
1597
1640
static Bool
1598
 
is_inside_rightbutton_area(SynapticsParameters *para, int x, int y)
 
1641
is_inside_rightbutton_area(SynapticsParameters * para, int x, int y)
1599
1642
{
1600
1643
    return is_inside_button_area(para, 0, x, y);
1601
1644
}
1602
1645
 
1603
1646
static Bool
1604
 
is_inside_middlebutton_area(SynapticsParameters *para, int x, int y)
 
1647
is_inside_middlebutton_area(SynapticsParameters * para, int x, int y)
1605
1648
{
1606
1649
    return is_inside_button_area(para, 1, x, y);
1607
1650
}
1634
1677
clamp(int val, int min, int max)
1635
1678
{
1636
1679
    if (val < min)
1637
 
        return min;
 
1680
        return min;
1638
1681
    else if (val < max)
1639
 
        return val;
 
1682
        return val;
1640
1683
    else
1641
 
        return max;
 
1684
        return max;
1642
1685
}
1643
1686
 
1644
1687
static Bool
1645
 
SynapticsGetHwState(InputInfoPtr pInfo, SynapticsPrivate *priv,
1646
 
                    struct SynapticsHwState *hw)
 
1688
SynapticsGetHwState(InputInfoPtr pInfo, SynapticsPrivate * priv,
 
1689
                    struct SynapticsHwState *hw)
1647
1690
{
1648
1691
    return priv->proto_ops->ReadHwState(pInfo, &priv->comm, hw);
1649
1692
}
1662
1705
    SynapticsResetTouchHwState(hw, FALSE);
1663
1706
 
1664
1707
    while (SynapticsGetHwState(pInfo, priv, hw)) {
1665
 
        /* Semi-mt device touch slots do not track touches. When there is a
1666
 
         * change in the number of touches, we must disregard the temporary
1667
 
         * motion changes. */
1668
 
        if (priv->has_semi_mt && hw->numFingers != priv->hwState->numFingers) {
1669
 
            hw->cumulative_dx = priv->hwState->cumulative_dx;
1670
 
            hw->cumulative_dy = priv->hwState->cumulative_dy;
1671
 
        }
1672
 
 
1673
 
        /* timer may cause actual events to lag behind (#48777) */
1674
 
        if (priv->hwState->millis > hw->millis)
1675
 
            hw->millis = priv->hwState->millis;
1676
 
 
1677
 
        SynapticsCopyHwState(priv->hwState, hw);
1678
 
        delay = HandleState(pInfo, hw, hw->millis, FALSE);
1679
 
        newDelay = TRUE;
 
1708
        /* Semi-mt device touch slots do not track touches. When there is a
 
1709
         * change in the number of touches, we must disregard the temporary
 
1710
         * motion changes. */
 
1711
        if (priv->has_semi_mt && hw->numFingers != priv->hwState->numFingers) {
 
1712
            hw->cumulative_dx = priv->hwState->cumulative_dx;
 
1713
            hw->cumulative_dy = priv->hwState->cumulative_dy;
 
1714
        }
 
1715
 
 
1716
        /* timer may cause actual events to lag behind (#48777) */
 
1717
        if (priv->hwState->millis > hw->millis)
 
1718
            hw->millis = priv->hwState->millis;
 
1719
 
 
1720
        SynapticsCopyHwState(priv->hwState, hw);
 
1721
        delay = HandleState(pInfo, hw, hw->millis, FALSE);
 
1722
        newDelay = TRUE;
1680
1723
    }
1681
1724
 
1682
1725
    if (newDelay) {
1683
 
        priv->timer_time = GetTimeInMillis();
1684
 
        priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
 
1726
        priv->timer_time = GetTimeInMillis();
 
1727
        priv->timer = TimerSet(priv->timer, 0, delay, timerFunc, pInfo);
1685
1728
    }
1686
1729
}
1687
1730
 
1688
1731
static int
1689
 
HandleMidButtonEmulation(SynapticsPrivate *priv, struct SynapticsHwState *hw, CARD32 now, int *delay)
 
1732
HandleMidButtonEmulation(SynapticsPrivate * priv, struct SynapticsHwState *hw,
 
1733
                         CARD32 now, int *delay)
1690
1734
{
1691
1735
    SynapticsParameters *para = &priv->synpara;
1692
1736
    Bool done = FALSE;
1697
1741
        return mid;
1698
1742
 
1699
1743
    while (!done) {
1700
 
        switch (priv->mid_emu_state) {
1701
 
        case MBE_LEFT_CLICK:
1702
 
        case MBE_RIGHT_CLICK:
1703
 
        case MBE_OFF:
1704
 
            priv->button_delay_millis = now;
1705
 
            if (hw->left) {
1706
 
                priv->mid_emu_state = MBE_LEFT;
1707
 
            } else if (hw->right) {
1708
 
                priv->mid_emu_state = MBE_RIGHT;
1709
 
            } else {
1710
 
                done = TRUE;
1711
 
            }
1712
 
            break;
1713
 
        case MBE_LEFT:
1714
 
            timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
1715
 
                                 now);
1716
 
            if (timeleft > 0)
1717
 
                *delay = MIN(*delay, timeleft);
 
1744
        switch (priv->mid_emu_state) {
 
1745
        case MBE_LEFT_CLICK:
 
1746
        case MBE_RIGHT_CLICK:
 
1747
        case MBE_OFF:
 
1748
            priv->button_delay_millis = now;
 
1749
            if (hw->left) {
 
1750
                priv->mid_emu_state = MBE_LEFT;
 
1751
            }
 
1752
            else if (hw->right) {
 
1753
                priv->mid_emu_state = MBE_RIGHT;
 
1754
            }
 
1755
            else {
 
1756
                done = TRUE;
 
1757
            }
 
1758
            break;
 
1759
        case MBE_LEFT:
 
1760
            timeleft =
 
1761
                TIME_DIFF(priv->button_delay_millis +
 
1762
                          para->emulate_mid_button_time, now);
 
1763
            if (timeleft > 0)
 
1764
                *delay = MIN(*delay, timeleft);
1718
1765
 
1719
1766
            /* timeout, but within the same ReadInput cycle! */
1720
1767
            if ((timeleft <= 0) && !hw->left) {
1721
 
                priv->mid_emu_state = MBE_LEFT_CLICK;
1722
 
                done = TRUE;
1723
 
            } else if ((!hw->left) || (timeleft <= 0)) {
1724
 
                hw->left = TRUE;
1725
 
                priv->mid_emu_state = MBE_TIMEOUT;
1726
 
                done = TRUE;
1727
 
            } else if (hw->right) {
1728
 
                priv->mid_emu_state = MBE_MID;
1729
 
            } else {
1730
 
                hw->left = FALSE;
1731
 
                done = TRUE;
1732
 
            }
1733
 
            break;
1734
 
        case MBE_RIGHT:
1735
 
            timeleft = TIME_DIFF(priv->button_delay_millis + para->emulate_mid_button_time,
1736
 
                                 now);
1737
 
            if (timeleft > 0)
1738
 
                *delay = MIN(*delay, timeleft);
 
1768
                priv->mid_emu_state = MBE_LEFT_CLICK;
 
1769
                done = TRUE;
 
1770
            }
 
1771
            else if ((!hw->left) || (timeleft <= 0)) {
 
1772
                hw->left = TRUE;
 
1773
                priv->mid_emu_state = MBE_TIMEOUT;
 
1774
                done = TRUE;
 
1775
            }
 
1776
            else if (hw->right) {
 
1777
                priv->mid_emu_state = MBE_MID;
 
1778
            }
 
1779
            else {
 
1780
                hw->left = FALSE;
 
1781
                done = TRUE;
 
1782
            }
 
1783
            break;
 
1784
        case MBE_RIGHT:
 
1785
            timeleft =
 
1786
                TIME_DIFF(priv->button_delay_millis +
 
1787
                          para->emulate_mid_button_time, now);
 
1788
            if (timeleft > 0)
 
1789
                *delay = MIN(*delay, timeleft);
1739
1790
 
1740
 
             /* timeout, but within the same ReadInput cycle! */
 
1791
            /* timeout, but within the same ReadInput cycle! */
1741
1792
            if ((timeleft <= 0) && !hw->right) {
1742
 
                priv->mid_emu_state = MBE_RIGHT_CLICK;
1743
 
                done = TRUE;
1744
 
            } else if (!hw->right || (timeleft <= 0)) {
1745
 
                hw->right = TRUE;
1746
 
                priv->mid_emu_state = MBE_TIMEOUT;
1747
 
                done = TRUE;
1748
 
            } else if (hw->left) {
1749
 
                priv->mid_emu_state = MBE_MID;
1750
 
            } else {
1751
 
                hw->right = FALSE;
1752
 
                done = TRUE;
1753
 
            }
1754
 
            break;
1755
 
        case MBE_MID:
1756
 
            if (!hw->left && !hw->right) {
1757
 
                priv->mid_emu_state = MBE_OFF;
1758
 
            } else {
1759
 
                mid = TRUE;
1760
 
                hw->left = hw->right = FALSE;
1761
 
                done = TRUE;
1762
 
            }
1763
 
            break;
1764
 
        case MBE_TIMEOUT:
1765
 
            if (!hw->left && !hw->right) {
1766
 
                priv->mid_emu_state = MBE_OFF;
1767
 
            } else {
1768
 
                done = TRUE;
1769
 
            }
1770
 
        }
 
1793
                priv->mid_emu_state = MBE_RIGHT_CLICK;
 
1794
                done = TRUE;
 
1795
            }
 
1796
            else if (!hw->right || (timeleft <= 0)) {
 
1797
                hw->right = TRUE;
 
1798
                priv->mid_emu_state = MBE_TIMEOUT;
 
1799
                done = TRUE;
 
1800
            }
 
1801
            else if (hw->left) {
 
1802
                priv->mid_emu_state = MBE_MID;
 
1803
            }
 
1804
            else {
 
1805
                hw->right = FALSE;
 
1806
                done = TRUE;
 
1807
            }
 
1808
            break;
 
1809
        case MBE_MID:
 
1810
            if (!hw->left && !hw->right) {
 
1811
                priv->mid_emu_state = MBE_OFF;
 
1812
            }
 
1813
            else {
 
1814
                mid = TRUE;
 
1815
                hw->left = hw->right = FALSE;
 
1816
                done = TRUE;
 
1817
            }
 
1818
            break;
 
1819
        case MBE_TIMEOUT:
 
1820
            if (!hw->left && !hw->right) {
 
1821
                priv->mid_emu_state = MBE_OFF;
 
1822
            }
 
1823
            else {
 
1824
                done = TRUE;
 
1825
            }
 
1826
        }
1771
1827
    }
1772
1828
    return mid;
1773
1829
}
1774
1830
 
1775
1831
static enum FingerState
1776
 
SynapticsDetectFinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
 
1832
SynapticsDetectFinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
1777
1833
{
1778
1834
    SynapticsParameters *para = &priv->synpara;
1779
1835
    enum FingerState finger;
1790
1846
    else if (hw->z > para->finger_high && priv->finger_state == FS_UNTOUCHED)
1791
1847
        finger = FS_TOUCHED;
1792
1848
    else
1793
 
        finger = priv->finger_state;
 
1849
        finger = priv->finger_state;
1794
1850
 
1795
1851
    if (!para->palm_detect)
1796
 
        return finger;
 
1852
        return finger;
1797
1853
 
1798
1854
    /* palm detection */
1799
1855
 
1801
1857
        return FS_BLOCKED;
1802
1858
 
1803
1859
    if (hw->x == 0 || priv->finger_state == FS_UNTOUCHED)
1804
 
        priv->avg_width = 0;
 
1860
        priv->avg_width = 0;
1805
1861
    else
1806
 
        priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
 
1862
        priv->avg_width += (hw->fingerWidth - priv->avg_width + 1) / 2;
1807
1863
 
1808
1864
    if (finger != FS_UNTOUCHED && priv->finger_state == FS_UNTOUCHED) {
1809
 
        int safe_width = MAX(hw->fingerWidth, priv->avg_width);
 
1865
        int safe_width = MAX(hw->fingerWidth, priv->avg_width);
1810
1866
 
1811
 
        if (hw->numFingers > 1 ||       /* more than one finger -> not a palm */
1812
 
            ((safe_width < 6) && (priv->prev_z < para->finger_high)) ||  /* thin finger, distinct touch -> not a palm */
1813
 
            ((safe_width < 7) && (priv->prev_z < para->finger_high / 2)))/* thin finger, distinct touch -> not a palm */
1814
 
        {
1815
 
            /* leave finger value as is */
1816
 
        } else if (hw->z > priv->prev_z + 1)    /* z not stable, may be a palm */
1817
 
            finger = FS_UNTOUCHED;
1818
 
        else if (hw->z < priv->prev_z - 5)      /* z not stable, may be a palm */
1819
 
            finger = FS_UNTOUCHED;
1820
 
        else if (hw->fingerWidth > para->palm_min_width) /* finger width too large -> probably palm */
1821
 
            finger = FS_UNTOUCHED;
 
1867
        if (hw->numFingers > 1 ||       /* more than one finger -> not a palm */
 
1868
            ((safe_width < 6) && (priv->prev_z < para->finger_high)) || /* thin finger, distinct touch -> not a palm */
 
1869
            ((safe_width < 7) && (priv->prev_z < para->finger_high / 2))) {     /* thin finger, distinct touch -> not a palm */
 
1870
            /* leave finger value as is */
 
1871
        }
 
1872
        else if (hw->z > priv->prev_z + 1)      /* z not stable, may be a palm */
 
1873
            finger = FS_UNTOUCHED;
 
1874
        else if (hw->z < priv->prev_z - 5)      /* z not stable, may be a palm */
 
1875
            finger = FS_UNTOUCHED;
 
1876
        else if (hw->fingerWidth > para->palm_min_width)        /* finger width too large -> probably palm */
 
1877
            finger = FS_UNTOUCHED;
1822
1878
    }
1823
1879
    priv->prev_z = hw->z;
1824
1880
 
1826
1882
}
1827
1883
 
1828
1884
static void
1829
 
SelectTapButton(SynapticsPrivate *priv, edge_type edge)
 
1885
SelectTapButton(SynapticsPrivate * priv, edge_type edge)
1830
1886
{
1831
1887
    TapEvent tap;
1832
1888
 
1833
1889
    if (priv->synpara.touchpad_off == 2) {
1834
 
        priv->tap_button = 0;
1835
 
        return;
 
1890
        priv->tap_button = 0;
 
1891
        return;
1836
1892
    }
1837
1893
 
1838
1894
    switch (priv->tap_max_fingers) {
1839
1895
    case 1:
1840
 
        switch (edge) {
1841
 
        case RIGHT_TOP_EDGE:
1842
 
            DBG(7, "right top edge\n");
1843
 
            tap = RT_TAP;
1844
 
            break;
1845
 
        case RIGHT_BOTTOM_EDGE:
1846
 
            DBG(7, "right bottom edge\n");
1847
 
            tap = RB_TAP;
1848
 
            break;
1849
 
        case LEFT_TOP_EDGE:
1850
 
            DBG(7, "left top edge\n");
1851
 
            tap = LT_TAP;
1852
 
            break;
1853
 
        case LEFT_BOTTOM_EDGE:
1854
 
            DBG(7, "left bottom edge\n");
1855
 
            tap = LB_TAP;
1856
 
            break;
1857
 
        default:
1858
 
            DBG(7, "no edge\n");
1859
 
            tap = F1_TAP;
1860
 
            break;
1861
 
        }
1862
 
        break;
 
1896
        switch (edge) {
 
1897
        case RIGHT_TOP_EDGE:
 
1898
            DBG(7, "right top edge\n");
 
1899
            tap = RT_TAP;
 
1900
            break;
 
1901
        case RIGHT_BOTTOM_EDGE:
 
1902
            DBG(7, "right bottom edge\n");
 
1903
            tap = RB_TAP;
 
1904
            break;
 
1905
        case LEFT_TOP_EDGE:
 
1906
            DBG(7, "left top edge\n");
 
1907
            tap = LT_TAP;
 
1908
            break;
 
1909
        case LEFT_BOTTOM_EDGE:
 
1910
            DBG(7, "left bottom edge\n");
 
1911
            tap = LB_TAP;
 
1912
            break;
 
1913
        default:
 
1914
            DBG(7, "no edge\n");
 
1915
            tap = F1_TAP;
 
1916
            break;
 
1917
        }
 
1918
        break;
1863
1919
    case 2:
1864
 
        DBG(7, "two finger tap\n");
1865
 
        tap = F2_TAP;
1866
 
        break;
 
1920
        DBG(7, "two finger tap\n");
 
1921
        tap = F2_TAP;
 
1922
        break;
1867
1923
    case 3:
1868
 
        DBG(7, "three finger tap\n");
1869
 
        tap = F3_TAP;
1870
 
        break;
 
1924
        DBG(7, "three finger tap\n");
 
1925
        tap = F3_TAP;
 
1926
        break;
1871
1927
    default:
1872
1928
        priv->tap_button = 0;
1873
1929
        return;
1878
1934
}
1879
1935
 
1880
1936
static void
1881
 
SetTapState(SynapticsPrivate *priv, enum TapState tap_state, CARD32 millis)
 
1937
SetTapState(SynapticsPrivate * priv, enum TapState tap_state, CARD32 millis)
1882
1938
{
1883
1939
    SynapticsParameters *para = &priv->synpara;
1884
 
    DBG(3, "SetTapState - %d -> %d (millis:%u)\n", priv->tap_state, tap_state, millis);
 
1940
 
 
1941
    DBG(3, "SetTapState - %d -> %d (millis:%u)\n", priv->tap_state, tap_state,
 
1942
        millis);
1885
1943
    switch (tap_state) {
1886
1944
    case TS_START:
1887
 
        priv->tap_button_state = TBS_BUTTON_UP;
1888
 
        priv->tap_max_fingers = 0;
1889
 
        break;
 
1945
        priv->tap_button_state = TBS_BUTTON_UP;
 
1946
        priv->tap_max_fingers = 0;
 
1947
        break;
1890
1948
    case TS_1:
1891
 
        priv->tap_button_state = TBS_BUTTON_UP;
1892
 
        break;
 
1949
        priv->tap_button_state = TBS_BUTTON_UP;
 
1950
        break;
1893
1951
    case TS_2A:
1894
 
        if (para->fast_taps)
1895
 
            priv->tap_button_state = TBS_BUTTON_DOWN;
1896
 
        else
1897
 
            priv->tap_button_state = TBS_BUTTON_UP;
1898
 
        break;
 
1952
        if (para->fast_taps)
 
1953
            priv->tap_button_state = TBS_BUTTON_DOWN;
 
1954
        else
 
1955
            priv->tap_button_state = TBS_BUTTON_UP;
 
1956
        break;
1899
1957
    case TS_2B:
1900
 
        priv->tap_button_state = TBS_BUTTON_UP;
1901
 
        break;
 
1958
        priv->tap_button_state = TBS_BUTTON_UP;
 
1959
        break;
1902
1960
    case TS_3:
1903
 
        priv->tap_button_state = TBS_BUTTON_DOWN;
1904
 
        break;
 
1961
        priv->tap_button_state = TBS_BUTTON_DOWN;
 
1962
        break;
1905
1963
    case TS_SINGLETAP:
1906
 
        if (para->fast_taps)
1907
 
            priv->tap_button_state = TBS_BUTTON_UP;
1908
 
        else
1909
 
            priv->tap_button_state = TBS_BUTTON_DOWN;
1910
 
        priv->touch_on.millis = millis;
1911
 
        break;
 
1964
        if (para->fast_taps)
 
1965
            priv->tap_button_state = TBS_BUTTON_UP;
 
1966
        else
 
1967
            priv->tap_button_state = TBS_BUTTON_DOWN;
 
1968
        priv->touch_on.millis = millis;
 
1969
        break;
1912
1970
    default:
1913
 
        break;
 
1971
        break;
1914
1972
    }
1915
1973
    priv->tap_state = tap_state;
1916
1974
}
1917
1975
 
1918
1976
static void
1919
 
SetMovingState(SynapticsPrivate *priv, enum MovingState moving_state, CARD32 millis)
 
1977
SetMovingState(SynapticsPrivate * priv, enum MovingState moving_state,
 
1978
               CARD32 millis)
1920
1979
{
1921
 
    DBG(7, "SetMovingState - %d -> %d center at %d/%d (millis:%u)\n", priv->moving_state,
1922
 
                  moving_state,priv->hwState->x, priv->hwState->y, millis);
 
1980
    DBG(7, "SetMovingState - %d -> %d center at %d/%d (millis:%u)\n",
 
1981
        priv->moving_state, moving_state, priv->hwState->x, priv->hwState->y,
 
1982
        millis);
1923
1983
 
1924
1984
    if (moving_state == MS_TRACKSTICK) {
1925
 
        priv->trackstick_neutral_x = priv->hwState->x;
1926
 
        priv->trackstick_neutral_y = priv->hwState->y;
 
1985
        priv->trackstick_neutral_x = priv->hwState->x;
 
1986
        priv->trackstick_neutral_y = priv->hwState->y;
1927
1987
    }
1928
1988
    priv->moving_state = moving_state;
1929
1989
}
1930
1990
 
1931
1991
static int
1932
 
GetTimeOut(SynapticsPrivate *priv)
 
1992
GetTimeOut(SynapticsPrivate * priv)
1933
1993
{
1934
1994
    SynapticsParameters *para = &priv->synpara;
1935
1995
 
1937
1997
    case TS_1:
1938
1998
    case TS_3:
1939
1999
    case TS_5:
1940
 
        return para->tap_time;
 
2000
        return para->tap_time;
1941
2001
    case TS_SINGLETAP:
1942
 
        return para->click_time;
 
2002
        return para->click_time;
1943
2003
    case TS_2A:
1944
 
        return para->single_tap_timeout;
 
2004
        return para->single_tap_timeout;
1945
2005
    case TS_2B:
1946
 
        return para->tap_time_2;
 
2006
        return para->tap_time_2;
1947
2007
    case TS_4:
1948
 
        return para->locked_drag_time;
 
2008
        return para->locked_drag_time;
1949
2009
    default:
1950
 
        return -1;                          /* No timeout */
 
2010
        return -1;              /* No timeout */
1951
2011
    }
1952
2012
}
1953
2013
 
1954
2014
static int
1955
 
HandleTapProcessing(SynapticsPrivate *priv, struct SynapticsHwState *hw,
1956
 
                    CARD32 now, enum FingerState finger,
1957
 
                    Bool inside_active_area)
 
2015
HandleTapProcessing(SynapticsPrivate * priv, struct SynapticsHwState *hw,
 
2016
                    CARD32 now, enum FingerState finger,
 
2017
                    Bool inside_active_area)
1958
2018
{
1959
2019
    SynapticsParameters *para = &priv->synpara;
1960
2020
    Bool touch, release, is_timeout, move, press;
1963
2023
    int delay = 1000000000;
1964
2024
 
1965
2025
    if (priv->finger_state == FS_BLOCKED)
1966
 
        return delay;
 
2026
        return delay;
1967
2027
 
1968
2028
    touch = finger >= FS_TOUCHED && priv->finger_state == FS_UNTOUCHED;
1969
2029
    release = finger == FS_UNTOUCHED && priv->finger_state >= FS_TOUCHED;
1970
2030
    move = (finger >= FS_TOUCHED &&
1971
 
             (priv->tap_max_fingers <= ((priv->horiz_scroll_twofinger_on || priv->vert_scroll_twofinger_on)? 2 : 1)) &&
1972
 
             ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
1973
 
             (abs(hw->y - priv->touch_on.y) >= para->tap_move)));
 
2031
            (priv->tap_max_fingers <=
 
2032
             ((priv->horiz_scroll_twofinger_on ||
 
2033
               priv->vert_scroll_twofinger_on) ? 2 : 1)) &&
 
2034
            ((abs(hw->x - priv->touch_on.x) >= para->tap_move) ||
 
2035
             (abs(hw->y - priv->touch_on.y) >= para->tap_move)));
1974
2036
    press = (hw->left || hw->right || hw->middle);
1975
2037
 
1976
2038
    if (touch) {
1977
 
        priv->touch_on.x = hw->x;
1978
 
        priv->touch_on.y = hw->y;
1979
 
        priv->touch_on.millis = now;
1980
 
    } else if (release) {
1981
 
        priv->touch_on.millis = now;
 
2039
        priv->touch_on.x = hw->x;
 
2040
        priv->touch_on.y = hw->y;
 
2041
        priv->touch_on.millis = now;
 
2042
    }
 
2043
    else if (release) {
 
2044
        priv->touch_on.millis = now;
1982
2045
    }
1983
2046
    if (hw->z > para->finger_high)
1984
 
        if (priv->tap_max_fingers < hw->numFingers)
1985
 
            priv->tap_max_fingers = hw->numFingers;
 
2047
        if (priv->tap_max_fingers < hw->numFingers)
 
2048
            priv->tap_max_fingers = hw->numFingers;
1986
2049
    timeout = GetTimeOut(priv);
1987
2050
    timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
1988
2051
    is_timeout = timeleft <= 0;
1990
2053
 restart:
1991
2054
    switch (priv->tap_state) {
1992
2055
    case TS_START:
1993
 
        if (touch)
1994
 
            SetTapState(priv, TS_1, now);
1995
 
        break;
 
2056
        if (touch)
 
2057
            SetTapState(priv, TS_1, now);
 
2058
        break;
1996
2059
    case TS_1:
1997
 
        if (para->clickpad && press) {
1998
 
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
1999
 
            goto restart;
2000
 
        }
2001
 
        if (move) {
2002
 
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2003
 
            SetTapState(priv, TS_MOVE, now);
2004
 
            goto restart;
2005
 
        } else if (is_timeout) {
2006
 
            if (finger == FS_TOUCHED) {
2007
 
                SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2008
 
            } else if (finger == FS_PRESSED) {
2009
 
                SetMovingState(priv, MS_TRACKSTICK, now);
2010
 
            }
2011
 
            SetTapState(priv, TS_MOVE, now);
2012
 
            goto restart;
2013
 
        } else if (release) {
2014
 
            edge = edge_detection(priv, priv->touch_on.x, priv->touch_on.y);
2015
 
            SelectTapButton(priv, edge);
2016
 
            /* Disable taps outside of the active area */
2017
 
            if (!inside_active_area) {
2018
 
                priv->tap_button = 0;
2019
 
            }
2020
 
            SetTapState(priv, TS_2A, now);
2021
 
        }
2022
 
        break;
 
2060
        if (para->clickpad && press) {
 
2061
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
 
2062
            goto restart;
 
2063
        }
 
2064
        if (move) {
 
2065
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2066
            SetTapState(priv, TS_MOVE, now);
 
2067
            goto restart;
 
2068
        }
 
2069
        else if (is_timeout) {
 
2070
            if (finger == FS_TOUCHED) {
 
2071
                SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2072
            }
 
2073
            else if (finger == FS_PRESSED) {
 
2074
                SetMovingState(priv, MS_TRACKSTICK, now);
 
2075
            }
 
2076
            SetTapState(priv, TS_MOVE, now);
 
2077
            goto restart;
 
2078
        }
 
2079
        else if (release) {
 
2080
            edge = edge_detection(priv, priv->touch_on.x, priv->touch_on.y);
 
2081
            SelectTapButton(priv, edge);
 
2082
            /* Disable taps outside of the active area */
 
2083
            if (!inside_active_area) {
 
2084
                priv->tap_button = 0;
 
2085
            }
 
2086
            SetTapState(priv, TS_2A, now);
 
2087
        }
 
2088
        break;
2023
2089
    case TS_MOVE:
2024
 
        if (para->clickpad && press) {
2025
 
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
2026
 
            goto restart;
2027
 
        }
2028
 
        if (move && priv->moving_state == MS_TRACKSTICK) {
2029
 
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2030
 
        }
2031
 
        if (release) {
2032
 
            SetMovingState(priv, MS_FALSE, now);
2033
 
            SetTapState(priv, TS_START, now);
2034
 
        }
2035
 
        break;
 
2090
        if (para->clickpad && press) {
 
2091
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
 
2092
            goto restart;
 
2093
        }
 
2094
        if (move && priv->moving_state == MS_TRACKSTICK) {
 
2095
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2096
        }
 
2097
        if (release) {
 
2098
            SetMovingState(priv, MS_FALSE, now);
 
2099
            SetTapState(priv, TS_START, now);
 
2100
        }
 
2101
        break;
2036
2102
    case TS_2A:
2037
 
        if (touch)
2038
 
            SetTapState(priv, TS_3, now);
2039
 
        else if (is_timeout)
2040
 
            SetTapState(priv, TS_SINGLETAP, now);
2041
 
        break;
 
2103
        if (touch)
 
2104
            SetTapState(priv, TS_3, now);
 
2105
        else if (is_timeout)
 
2106
            SetTapState(priv, TS_SINGLETAP, now);
 
2107
        break;
2042
2108
    case TS_2B:
2043
 
        if (touch) {
2044
 
            SetTapState(priv, TS_3, now);
2045
 
        } else if (is_timeout) {
2046
 
            SetTapState(priv, TS_START, now);
2047
 
            priv->tap_button_state = TBS_BUTTON_DOWN_UP;
2048
 
        }
2049
 
        break;
 
2109
        if (touch) {
 
2110
            SetTapState(priv, TS_3, now);
 
2111
        }
 
2112
        else if (is_timeout) {
 
2113
            SetTapState(priv, TS_START, now);
 
2114
            priv->tap_button_state = TBS_BUTTON_DOWN_UP;
 
2115
        }
 
2116
        break;
2050
2117
    case TS_SINGLETAP:
2051
 
        if (touch)
2052
 
            SetTapState(priv, TS_1, now);
2053
 
        else if (is_timeout)
2054
 
            SetTapState(priv, TS_START, now);
2055
 
        break;
 
2118
        if (touch)
 
2119
            SetTapState(priv, TS_1, now);
 
2120
        else if (is_timeout)
 
2121
            SetTapState(priv, TS_START, now);
 
2122
        break;
2056
2123
    case TS_3:
2057
 
        if (move) {
2058
 
            if (para->tap_and_drag_gesture) {
2059
 
                SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2060
 
                SetTapState(priv, TS_DRAG, now);
2061
 
            } else {
2062
 
                SetTapState(priv, TS_1, now);
2063
 
            }
2064
 
            goto restart;
2065
 
        } else if (is_timeout) {
2066
 
            if (para->tap_and_drag_gesture) {
2067
 
                if (finger == FS_TOUCHED) {
2068
 
                    SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2069
 
                } else if (finger == FS_PRESSED) {
2070
 
                    SetMovingState(priv, MS_TRACKSTICK, now);
2071
 
                }
2072
 
                SetTapState(priv, TS_DRAG, now);
2073
 
            } else {
2074
 
                SetTapState(priv, TS_1, now);
2075
 
            }
2076
 
            goto restart;
2077
 
        } else if (release) {
2078
 
            SetTapState(priv, TS_2B, now);
2079
 
        }
2080
 
        break;
 
2124
        if (move) {
 
2125
            if (para->tap_and_drag_gesture) {
 
2126
                SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2127
                SetTapState(priv, TS_DRAG, now);
 
2128
            }
 
2129
            else {
 
2130
                SetTapState(priv, TS_1, now);
 
2131
            }
 
2132
            goto restart;
 
2133
        }
 
2134
        else if (is_timeout) {
 
2135
            if (para->tap_and_drag_gesture) {
 
2136
                if (finger == FS_TOUCHED) {
 
2137
                    SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2138
                }
 
2139
                else if (finger == FS_PRESSED) {
 
2140
                    SetMovingState(priv, MS_TRACKSTICK, now);
 
2141
                }
 
2142
                SetTapState(priv, TS_DRAG, now);
 
2143
            }
 
2144
            else {
 
2145
                SetTapState(priv, TS_1, now);
 
2146
            }
 
2147
            goto restart;
 
2148
        }
 
2149
        else if (release) {
 
2150
            SetTapState(priv, TS_2B, now);
 
2151
        }
 
2152
        break;
2081
2153
    case TS_DRAG:
2082
 
        if (para->clickpad && press) {
2083
 
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
2084
 
            goto restart;
2085
 
        }
2086
 
        if (move)
2087
 
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2088
 
        if (release) {
2089
 
            SetMovingState(priv, MS_FALSE, now);
2090
 
            if (para->locked_drags) {
2091
 
                SetTapState(priv, TS_4, now);
2092
 
            } else {
2093
 
                SetTapState(priv, TS_START, now);
2094
 
            }
2095
 
        }
2096
 
        break;
 
2154
        if (para->clickpad && press) {
 
2155
            SetTapState(priv, TS_CLICKPAD_MOVE, now);
 
2156
            goto restart;
 
2157
        }
 
2158
        if (move)
 
2159
            SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2160
        if (release) {
 
2161
            SetMovingState(priv, MS_FALSE, now);
 
2162
            if (para->locked_drags) {
 
2163
                SetTapState(priv, TS_4, now);
 
2164
            }
 
2165
            else {
 
2166
                SetTapState(priv, TS_START, now);
 
2167
            }
 
2168
        }
 
2169
        break;
2097
2170
    case TS_4:
2098
 
        if (is_timeout) {
2099
 
            SetTapState(priv, TS_START, now);
2100
 
            goto restart;
2101
 
        }
2102
 
        if (touch)
2103
 
            SetTapState(priv, TS_5, now);
2104
 
        break;
 
2171
        if (is_timeout) {
 
2172
            SetTapState(priv, TS_START, now);
 
2173
            goto restart;
 
2174
        }
 
2175
        if (touch)
 
2176
            SetTapState(priv, TS_5, now);
 
2177
        break;
2105
2178
    case TS_5:
2106
 
        if (is_timeout || move) {
2107
 
            SetTapState(priv, TS_DRAG, now);
2108
 
            goto restart;
2109
 
        } else if (release) {
2110
 
            SetMovingState(priv, MS_FALSE, now);
2111
 
            SetTapState(priv, TS_START, now);
2112
 
        }
2113
 
        break;
 
2179
        if (is_timeout || move) {
 
2180
            SetTapState(priv, TS_DRAG, now);
 
2181
            goto restart;
 
2182
        }
 
2183
        else if (release) {
 
2184
            SetMovingState(priv, MS_FALSE, now);
 
2185
            SetTapState(priv, TS_START, now);
 
2186
        }
 
2187
        break;
2114
2188
    case TS_CLICKPAD_MOVE:
2115
 
        /* Disable scrolling once a button is pressed on a clickpad */
2116
 
        priv->vert_scroll_edge_on = FALSE;
2117
 
        priv->horiz_scroll_edge_on = FALSE;
2118
 
        priv->vert_scroll_twofinger_on = FALSE;
2119
 
        priv->horiz_scroll_twofinger_on = FALSE;
 
2189
        /* Disable scrolling once a button is pressed on a clickpad */
 
2190
        priv->vert_scroll_edge_on = FALSE;
 
2191
        priv->horiz_scroll_edge_on = FALSE;
 
2192
        priv->vert_scroll_twofinger_on = FALSE;
 
2193
        priv->horiz_scroll_twofinger_on = FALSE;
2120
2194
 
2121
2195
        /* Assume one touch is only for holding the clickpad button down */
2122
 
        if (hw->numFingers > 1)
2123
 
            hw->numFingers--;
2124
 
        SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
2125
 
        if (!press) {
2126
 
            SetMovingState(priv, MS_FALSE, now);
2127
 
            SetTapState(priv, TS_MOVE, now);
2128
 
            priv->count_packet_finger = 0;
2129
 
        }
2130
 
        break;
 
2196
        if (hw->numFingers > 1)
 
2197
            hw->numFingers--;
 
2198
        SetMovingState(priv, MS_TOUCHPAD_RELATIVE, now);
 
2199
        if (!press) {
 
2200
            SetMovingState(priv, MS_FALSE, now);
 
2201
            SetTapState(priv, TS_MOVE, now);
 
2202
            priv->count_packet_finger = 0;
 
2203
        }
 
2204
        break;
2131
2205
    }
2132
2206
 
2133
2207
    timeout = GetTimeOut(priv);
2134
2208
    if (timeout >= 0) {
2135
 
        timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
2136
 
        delay = clamp(timeleft, 1, delay);
 
2209
        timeleft = TIME_DIFF(priv->touch_on.millis + timeout, now);
 
2210
        delay = clamp(timeleft, 1, delay);
2137
2211
    }
2138
2212
    return delay;
2139
2213
}
2142
2216
#define HIST_DELTA(a, b, e) ((HIST((a)).e) - (HIST((b)).e))
2143
2217
 
2144
2218
static void
2145
 
store_history(SynapticsPrivate *priv, int x, int y, CARD32 millis)
 
2219
store_history(SynapticsPrivate * priv, int x, int y, CARD32 millis)
2146
2220
{
2147
2221
    int idx = (priv->hist_index + 1) % SYNAPTICS_MOVE_HISTORY;
 
2222
 
2148
2223
    priv->move_hist[idx].x = x;
2149
2224
    priv->move_hist[idx].y = y;
2150
2225
    priv->move_hist[idx].millis = millis;
2172
2247
 * @param margin the margin to center in which no change is applied
2173
2248
 * @return the new center (which might coincide with the previous)
2174
2249
 */
2175
 
static int hysteresis(int in, int center, int margin) {
 
2250
static int
 
2251
hysteresis(int in, int center, int margin)
 
2252
{
2176
2253
    int diff = in - center;
 
2254
 
2177
2255
    if (abs(diff) <= margin) {
2178
 
        diff = 0;
2179
 
    } else if (diff > margin) {
2180
 
        diff -= margin;
2181
 
    } else if (diff < -margin) {
2182
 
        diff += margin;
 
2256
        diff = 0;
 
2257
    }
 
2258
    else if (diff > margin) {
 
2259
        diff -= margin;
 
2260
    }
 
2261
    else if (diff < -margin) {
 
2262
        diff += margin;
2183
2263
    }
2184
2264
    return center + diff;
2185
2265
}
2186
2266
 
2187
2267
static void
2188
 
get_delta_for_trackstick(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
2189
 
                         double *dx, double *dy)
 
2268
get_delta_for_trackstick(SynapticsPrivate * priv,
 
2269
                         const struct SynapticsHwState *hw, double *dx,
 
2270
                         double *dy)
2190
2271
{
2191
2272
    SynapticsParameters *para = &priv->synpara;
2192
2273
    double dtime = (hw->millis - HIST(0).millis) / 1000.0;
2199
2280
}
2200
2281
 
2201
2282
static void
2202
 
get_edge_speed(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
 
2283
get_edge_speed(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
2203
2284
               edge_type edge, int *x_edge_speed, int *y_edge_speed)
2204
2285
{
2205
2286
    SynapticsParameters *para = &priv->synpara;
2212
2293
 
2213
2294
    if (hw->z <= minZ) {
2214
2295
        edge_speed = minSpd;
2215
 
    } else if (hw->z >= maxZ) {
 
2296
    }
 
2297
    else if (hw->z >= maxZ) {
2216
2298
        edge_speed = maxSpd;
2217
 
    } else {
2218
 
        edge_speed = minSpd + (hw->z - minZ) * (maxSpd - minSpd) / (maxZ - minZ);
 
2299
    }
 
2300
    else {
 
2301
        edge_speed =
 
2302
            minSpd + (hw->z - minZ) * (maxSpd - minSpd) / (maxZ - minZ);
2219
2303
    }
2220
2304
    if (!priv->synpara.circular_pad) {
2221
2305
        /* on rectangular pad */
2222
2306
        if (edge & RIGHT_EDGE) {
2223
2307
            *x_edge_speed = edge_speed;
2224
 
        } else if (edge & LEFT_EDGE) {
 
2308
        }
 
2309
        else if (edge & LEFT_EDGE) {
2225
2310
            *x_edge_speed = -edge_speed;
2226
2311
        }
2227
2312
        if (edge & TOP_EDGE) {
2228
2313
            *y_edge_speed = -edge_speed;
2229
 
        } else if (edge & BOTTOM_EDGE) {
 
2314
        }
 
2315
        else if (edge & BOTTOM_EDGE) {
2230
2316
            *y_edge_speed = edge_speed;
2231
2317
        }
2232
 
    } else if (edge) {
 
2318
    }
 
2319
    else if (edge) {
2233
2320
        /* at edge of circular pad */
2234
2321
        double relX, relY;
2235
2322
 
2236
2323
        relative_coords(priv, hw->x, hw->y, &relX, &relY);
2237
 
        *x_edge_speed = (int)(edge_speed * relX);
2238
 
        *y_edge_speed = (int)(edge_speed * relY);
 
2324
        *x_edge_speed = (int) (edge_speed * relX);
 
2325
        *y_edge_speed = (int) (edge_speed * relY);
2239
2326
    }
2240
2327
}
2241
2328
 
2242
2329
static void
2243
 
get_delta(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
 
2330
get_delta(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
2244
2331
          edge_type edge, double *dx, double *dy)
2245
2332
{
2246
2333
    SynapticsParameters *para = &priv->synpara;
2278
2365
 * Compute relative motion ('deltas') including edge motion xor trackstick.
2279
2366
 */
2280
2367
static int
2281
 
ComputeDeltas(SynapticsPrivate *priv, const struct SynapticsHwState *hw,
2282
 
              edge_type edge, int *dxP, int *dyP, Bool inside_area)
 
2368
ComputeDeltas(SynapticsPrivate * priv, const struct SynapticsHwState *hw,
 
2369
              edge_type edge, int *dxP, int *dyP, Bool inside_area)
2283
2370
{
2284
2371
    enum MovingState moving_state;
2285
2372
    double dx, dy;
2289
2376
 
2290
2377
    moving_state = priv->moving_state;
2291
2378
    if (moving_state == MS_FALSE) {
2292
 
        switch (priv->tap_state) {
2293
 
        case TS_MOVE:
2294
 
        case TS_DRAG:
2295
 
            moving_state = MS_TOUCHPAD_RELATIVE;
2296
 
            break;
2297
 
        case TS_1:
2298
 
        case TS_3:
2299
 
        case TS_5:
2300
 
            moving_state = MS_TOUCHPAD_RELATIVE;
2301
 
            break;
2302
 
        default:
2303
 
            break;
2304
 
        }
 
2379
        switch (priv->tap_state) {
 
2380
        case TS_MOVE:
 
2381
        case TS_DRAG:
 
2382
            moving_state = MS_TOUCHPAD_RELATIVE;
 
2383
            break;
 
2384
        case TS_1:
 
2385
        case TS_3:
 
2386
        case TS_5:
 
2387
            moving_state = MS_TOUCHPAD_RELATIVE;
 
2388
            break;
 
2389
        default:
 
2390
            break;
 
2391
        }
2305
2392
    }
2306
2393
 
2307
2394
    if (!inside_area || !moving_state || priv->finger_state == FS_BLOCKED ||
2308
 
        priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
2309
 
        priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
2310
 
        priv->circ_scroll_on || priv->prevFingers != hw->numFingers ||
2311
 
        (moving_state == MS_TOUCHPAD_RELATIVE && hw->numFingers != 1))
2312
 
    {
 
2395
        priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
 
2396
        priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
 
2397
        priv->circ_scroll_on || priv->prevFingers != hw->numFingers ||
 
2398
        (moving_state == MS_TOUCHPAD_RELATIVE && hw->numFingers != 1)) {
2313
2399
        /* reset packet counter. */
2314
2400
        priv->count_packet_finger = 0;
2315
2401
        goto out;
2321
2407
    delay = MIN(delay, POLL_MS);
2322
2408
 
2323
2409
    if (priv->count_packet_finger <= 1)
2324
 
        goto out; /* skip the lot */
 
2410
        goto out;               /* skip the lot */
2325
2411
 
2326
2412
    if (priv->moving_state == MS_TRACKSTICK)
2327
2413
        get_delta_for_trackstick(priv, hw, &dx, &dy);
2328
2414
    else if (moving_state == MS_TOUCHPAD_RELATIVE)
2329
2415
        get_delta(priv, hw, edge, &dx, &dy);
2330
2416
 
2331
 
out:
 
2417
 out:
2332
2418
    priv->prevFingers = hw->numFingers;
2333
2419
 
2334
2420
    *dxP = dx;
2338
2424
}
2339
2425
 
2340
2426
static double
2341
 
estimate_delta_circ(SynapticsPrivate *priv)
 
2427
estimate_delta_circ(SynapticsPrivate * priv)
2342
2428
{
2343
 
        double a1 = angle(priv, HIST(3).x, HIST(3).y);
2344
 
        double a2 = angle(priv, HIST(2).x, HIST(2).y);
2345
 
        double a3 = angle(priv, HIST(1).x, HIST(1).y);
2346
 
        double a4 = angle(priv, HIST(0).x, HIST(0).y);
2347
 
        double d1 = diffa(a2, a1);
2348
 
        double d2 = d1 + diffa(a3, a2);
2349
 
        double d3 = d2 + diffa(a4, a3);
2350
 
        return estimate_delta(d3, d2, d1, 0);
 
2429
    double a1 = angle(priv, HIST(3).x, HIST(3).y);
 
2430
    double a2 = angle(priv, HIST(2).x, HIST(2).y);
 
2431
    double a3 = angle(priv, HIST(1).x, HIST(1).y);
 
2432
    double a4 = angle(priv, HIST(0).x, HIST(0).y);
 
2433
    double d1 = diffa(a2, a1);
 
2434
    double d2 = d1 + diffa(a3, a2);
 
2435
    double d3 = d2 + diffa(a4, a3);
 
2436
 
 
2437
    return estimate_delta(d3, d2, d1, 0);
2351
2438
}
2352
2439
 
2353
2440
/* vert and horiz are to know which direction to start coasting
2354
2441
 * circ is true if the user had been circular scrolling.
2355
2442
 */
2356
2443
static void
2357
 
start_coasting(SynapticsPrivate *priv, struct SynapticsHwState *hw,
2358
 
               Bool vert, Bool horiz, Bool circ)
 
2444
start_coasting(SynapticsPrivate * priv, struct SynapticsHwState *hw,
 
2445
               Bool vert, Bool horiz, Bool circ)
2359
2446
{
2360
2447
    SynapticsParameters *para = &priv->synpara;
2361
2448
 
2363
2450
    priv->scroll.coast_delta_x = 0.0;
2364
2451
 
2365
2452
    if ((priv->scroll.packets_this_scroll > 3) && (para->coasting_speed > 0.0)) {
2366
 
        double pkt_time = HIST_DELTA(0, 3, millis) / 1000.0;
2367
 
        if (vert && !circ) {
2368
 
            double dy = estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
2369
 
            if (pkt_time > 0) {
2370
 
                double scrolls_per_sec = dy / pkt_time;
2371
 
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2372
 
                    priv->scroll.coast_speed_y = scrolls_per_sec;
2373
 
                    priv->scroll.coast_delta_y = (hw->y - priv->scroll.last_y);
2374
 
                }
2375
 
            }
2376
 
        }
2377
 
        if (horiz && !circ){
2378
 
            double dx = estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
2379
 
            if (pkt_time > 0) {
2380
 
                double scrolls_per_sec = dx / pkt_time;
2381
 
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2382
 
                    priv->scroll.coast_speed_x = scrolls_per_sec;
2383
 
                    priv->scroll.coast_delta_x = (hw->x - priv->scroll.last_x);
2384
 
                }
2385
 
            }
2386
 
        }
2387
 
        if (circ) {
2388
 
            double da = estimate_delta_circ(priv);
2389
 
            if (pkt_time > 0) {
2390
 
                double scrolls_per_sec = da / pkt_time;
2391
 
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
2392
 
                    if (vert) {
2393
 
                        priv->scroll.coast_speed_y = scrolls_per_sec;
2394
 
                        priv->scroll.coast_delta_y = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
2395
 
                    }
2396
 
                    else if (horiz) {
2397
 
                        priv->scroll.coast_speed_x = scrolls_per_sec;
2398
 
                        priv->scroll.coast_delta_x = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
2399
 
                    }
2400
 
                }
2401
 
            }
2402
 
        }
 
2453
        double pkt_time = HIST_DELTA(0, 3, millis) / 1000.0;
 
2454
 
 
2455
        if (vert && !circ) {
 
2456
            double dy =
 
2457
                estimate_delta(HIST(0).y, HIST(1).y, HIST(2).y, HIST(3).y);
 
2458
            if (pkt_time > 0) {
 
2459
                double scrolls_per_sec = (dy / abs(para->scroll_dist_vert)) / pkt_time;
 
2460
 
 
2461
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
 
2462
                    priv->scroll.coast_speed_y = scrolls_per_sec;
 
2463
                    priv->scroll.coast_delta_y = (hw->y - priv->scroll.last_y);
 
2464
                }
 
2465
            }
 
2466
        }
 
2467
        if (horiz && !circ) {
 
2468
            double dx =
 
2469
                estimate_delta(HIST(0).x, HIST(1).x, HIST(2).x, HIST(3).x);
 
2470
            if (pkt_time > 0) {
 
2471
                double scrolls_per_sec = (dx / abs(para->scroll_dist_vert)) / pkt_time;
 
2472
 
 
2473
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
 
2474
                    priv->scroll.coast_speed_x = scrolls_per_sec;
 
2475
                    priv->scroll.coast_delta_x = (hw->x - priv->scroll.last_x);
 
2476
                }
 
2477
            }
 
2478
        }
 
2479
        if (circ) {
 
2480
            double da = estimate_delta_circ(priv);
 
2481
 
 
2482
            if (pkt_time > 0) {
 
2483
                double scrolls_per_sec = (da / para->scroll_dist_circ) / pkt_time;
 
2484
 
 
2485
                if (fabs(scrolls_per_sec) >= para->coasting_speed) {
 
2486
                    if (vert) {
 
2487
                        priv->scroll.coast_speed_y = scrolls_per_sec;
 
2488
                        priv->scroll.coast_delta_y =
 
2489
                            diffa(priv->scroll.last_a,
 
2490
                                  angle(priv, hw->x, hw->y));
 
2491
                    }
 
2492
                    else if (horiz) {
 
2493
                        priv->scroll.coast_speed_x = scrolls_per_sec;
 
2494
                        priv->scroll.coast_delta_x =
 
2495
                            diffa(priv->scroll.last_a,
 
2496
                                  angle(priv, hw->x, hw->y));
 
2497
                    }
 
2498
                }
 
2499
            }
 
2500
        }
2403
2501
    }
2404
2502
    priv->scroll.packets_this_scroll = 0;
2405
2503
}
2406
2504
 
2407
2505
static void
2408
 
stop_coasting(SynapticsPrivate *priv)
 
2506
stop_coasting(SynapticsPrivate * priv)
2409
2507
{
2410
2508
    priv->scroll.coast_speed_x = 0;
2411
2509
    priv->scroll.coast_speed_y = 0;
2413
2511
}
2414
2512
 
2415
2513
static int
2416
 
HandleScrolling(SynapticsPrivate *priv, struct SynapticsHwState *hw,
2417
 
                edge_type edge, Bool finger)
 
2514
HandleScrolling(SynapticsPrivate * priv, struct SynapticsHwState *hw,
 
2515
                edge_type edge, Bool finger)
2418
2516
{
2419
2517
    SynapticsParameters *para = &priv->synpara;
2420
2518
    int delay = 1000000000;
2421
2519
 
2422
2520
    if ((priv->synpara.touchpad_off == 2) || (priv->finger_state == FS_BLOCKED)) {
2423
 
        stop_coasting(priv);
2424
 
        priv->circ_scroll_on = FALSE;
2425
 
        priv->vert_scroll_edge_on = FALSE;
2426
 
        priv->horiz_scroll_edge_on = FALSE;
2427
 
        priv->vert_scroll_twofinger_on = FALSE;
2428
 
        priv->horiz_scroll_twofinger_on = FALSE;
2429
 
        return delay;
 
2521
        stop_coasting(priv);
 
2522
        priv->circ_scroll_on = FALSE;
 
2523
        priv->vert_scroll_edge_on = FALSE;
 
2524
        priv->horiz_scroll_edge_on = FALSE;
 
2525
        priv->vert_scroll_twofinger_on = FALSE;
 
2526
        priv->horiz_scroll_twofinger_on = FALSE;
 
2527
        return delay;
2430
2528
    }
2431
2529
 
2432
2530
    /* scroll detection */
2433
2531
    if (finger && priv->finger_state == FS_UNTOUCHED) {
2434
 
        stop_coasting(priv);
 
2532
        stop_coasting(priv);
2435
2533
        priv->scroll.delta_y = 0;
2436
2534
        priv->scroll.delta_x = 0;
2437
 
        if (para->circular_scrolling) {
2438
 
            if ((para->circular_trigger == 0 && edge) ||
2439
 
                (para->circular_trigger == 1 && edge & TOP_EDGE) ||
2440
 
                (para->circular_trigger == 2 && edge & TOP_EDGE && edge & RIGHT_EDGE) ||
2441
 
                (para->circular_trigger == 3 && edge & RIGHT_EDGE) ||
2442
 
                (para->circular_trigger == 4 && edge & RIGHT_EDGE && edge & BOTTOM_EDGE) ||
2443
 
                (para->circular_trigger == 5 && edge & BOTTOM_EDGE) ||
2444
 
                (para->circular_trigger == 6 && edge & BOTTOM_EDGE && edge & LEFT_EDGE) ||
2445
 
                (para->circular_trigger == 7 && edge & LEFT_EDGE) ||
2446
 
                (para->circular_trigger == 8 && edge & LEFT_EDGE && edge & TOP_EDGE)) {
2447
 
                priv->circ_scroll_on = TRUE;
2448
 
                priv->circ_scroll_vert = TRUE;
2449
 
                priv->scroll.last_a = angle(priv, hw->x, hw->y);
2450
 
                DBG(7, "circular scroll detected on edge\n");
2451
 
            }
2452
 
        }
 
2535
        if (para->circular_scrolling) {
 
2536
            if ((para->circular_trigger == 0 && edge) ||
 
2537
                (para->circular_trigger == 1 && edge & TOP_EDGE) ||
 
2538
                (para->circular_trigger == 2 && edge & TOP_EDGE &&
 
2539
                 edge & RIGHT_EDGE) || (para->circular_trigger == 3 &&
 
2540
                                        edge & RIGHT_EDGE) ||
 
2541
                (para->circular_trigger == 4 && edge & RIGHT_EDGE &&
 
2542
                 edge & BOTTOM_EDGE) || (para->circular_trigger == 5 &&
 
2543
                                         edge & BOTTOM_EDGE) ||
 
2544
                (para->circular_trigger == 6 && edge & BOTTOM_EDGE &&
 
2545
                 edge & LEFT_EDGE) || (para->circular_trigger == 7 &&
 
2546
                                       edge & LEFT_EDGE) ||
 
2547
                (para->circular_trigger == 8 && edge & LEFT_EDGE &&
 
2548
                 edge & TOP_EDGE)) {
 
2549
                priv->circ_scroll_on = TRUE;
 
2550
                priv->circ_scroll_vert = TRUE;
 
2551
                priv->scroll.last_a = angle(priv, hw->x, hw->y);
 
2552
                DBG(7, "circular scroll detected on edge\n");
 
2553
            }
 
2554
        }
2453
2555
    }
2454
2556
    if (!priv->circ_scroll_on) {
2455
 
        if (finger) {
2456
 
            if (hw->numFingers == 2) {
2457
 
                if (!priv->vert_scroll_twofinger_on &&
2458
 
                    (para->scroll_twofinger_vert) && (para->scroll_dist_vert != 0)) {
2459
 
                    stop_coasting(priv);
2460
 
                    priv->vert_scroll_twofinger_on = TRUE;
2461
 
                    priv->vert_scroll_edge_on = FALSE;
2462
 
                    priv->scroll.last_y = hw->y;
2463
 
                    DBG(7, "vert two-finger scroll detected\n");
2464
 
                }
2465
 
                if (!priv->horiz_scroll_twofinger_on &&
2466
 
                    (para->scroll_twofinger_horiz) && (para->scroll_dist_horiz != 0)) {
2467
 
                    stop_coasting(priv);
2468
 
                    priv->horiz_scroll_twofinger_on = TRUE;
2469
 
                    priv->horiz_scroll_edge_on = FALSE;
2470
 
                    priv->scroll.last_x = hw->x;
2471
 
                    DBG(7, "horiz two-finger scroll detected\n");
2472
 
                }
2473
 
            }
2474
 
        }
2475
 
        if (finger && priv->finger_state == FS_UNTOUCHED) {
2476
 
            if (!priv->vert_scroll_twofinger_on && !priv->horiz_scroll_twofinger_on) {
2477
 
                if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
2478
 
                    (edge & RIGHT_EDGE)) {
2479
 
                    priv->vert_scroll_edge_on = TRUE;
2480
 
                    priv->scroll.last_y = hw->y;
2481
 
                    DBG(7, "vert edge scroll detected on right edge\n");
2482
 
                }
2483
 
                if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0) &&
2484
 
                    (edge & BOTTOM_EDGE)) {
2485
 
                    priv->horiz_scroll_edge_on = TRUE;
2486
 
                    priv->scroll.last_x = hw->x;
2487
 
                    DBG(7, "horiz edge scroll detected on bottom edge\n");
2488
 
                }
2489
 
            }
2490
 
        }
 
2557
        if (finger) {
 
2558
            if (hw->numFingers == 2) {
 
2559
                if (!priv->vert_scroll_twofinger_on &&
 
2560
                    (para->scroll_twofinger_vert) &&
 
2561
                    (para->scroll_dist_vert != 0)) {
 
2562
                    stop_coasting(priv);
 
2563
                    priv->vert_scroll_twofinger_on = TRUE;
 
2564
                    priv->vert_scroll_edge_on = FALSE;
 
2565
                    priv->scroll.last_y = hw->y;
 
2566
                    DBG(7, "vert two-finger scroll detected\n");
 
2567
                }
 
2568
                if (!priv->horiz_scroll_twofinger_on &&
 
2569
                    (para->scroll_twofinger_horiz) &&
 
2570
                    (para->scroll_dist_horiz != 0)) {
 
2571
                    stop_coasting(priv);
 
2572
                    priv->horiz_scroll_twofinger_on = TRUE;
 
2573
                    priv->horiz_scroll_edge_on = FALSE;
 
2574
                    priv->scroll.last_x = hw->x;
 
2575
                    DBG(7, "horiz two-finger scroll detected\n");
 
2576
                }
 
2577
            }
 
2578
        }
 
2579
        if (finger && priv->finger_state == FS_UNTOUCHED) {
 
2580
            if (!priv->vert_scroll_twofinger_on &&
 
2581
                !priv->horiz_scroll_twofinger_on) {
 
2582
                if ((para->scroll_edge_vert) && (para->scroll_dist_vert != 0) &&
 
2583
                    (edge & RIGHT_EDGE)) {
 
2584
                    priv->vert_scroll_edge_on = TRUE;
 
2585
                    priv->scroll.last_y = hw->y;
 
2586
                    DBG(7, "vert edge scroll detected on right edge\n");
 
2587
                }
 
2588
                if ((para->scroll_edge_horiz) && (para->scroll_dist_horiz != 0)
 
2589
                    && (edge & BOTTOM_EDGE)) {
 
2590
                    priv->horiz_scroll_edge_on = TRUE;
 
2591
                    priv->scroll.last_x = hw->x;
 
2592
                    DBG(7, "horiz edge scroll detected on bottom edge\n");
 
2593
                }
 
2594
            }
 
2595
        }
2491
2596
    }
2492
2597
    {
2493
 
        Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on ||
2494
 
                      (priv->circ_scroll_on && priv->circ_scroll_vert);
2495
 
 
2496
 
        Bool oldh = priv->horiz_scroll_twofinger_on || priv->horiz_scroll_edge_on ||
2497
 
                      (priv->circ_scroll_on && !priv->circ_scroll_vert);
2498
 
 
2499
 
        Bool oldc = priv->circ_scroll_on;
2500
 
 
2501
 
        if (priv->circ_scroll_on && !finger) {
2502
 
            /* circular scroll locks in until finger is raised */
2503
 
            DBG(7, "cicular scroll off\n");
2504
 
            priv->circ_scroll_on = FALSE;
2505
 
        }
2506
 
 
2507
 
        if (!finger || hw->numFingers != 2) {
2508
 
            if (priv->vert_scroll_twofinger_on) {
2509
 
                DBG(7, "vert two-finger scroll off\n");
2510
 
                priv->vert_scroll_twofinger_on = FALSE;
2511
 
            }
2512
 
            if (priv->horiz_scroll_twofinger_on) {
2513
 
                DBG(7, "horiz two-finger scroll off\n");
2514
 
                priv->horiz_scroll_twofinger_on = FALSE;
2515
 
            }
2516
 
        }
2517
 
 
2518
 
        if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
2519
 
            DBG(7, "vert edge scroll off\n");
2520
 
            priv->vert_scroll_edge_on = FALSE;
2521
 
        }
2522
 
        if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
2523
 
            DBG(7, "horiz edge scroll off\n");
2524
 
            priv->horiz_scroll_edge_on = FALSE;
2525
 
        }
2526
 
        /* If we were corner edge scrolling (coasting),
2527
 
         * but no longer in corner or raised a finger, then stop coasting. */
2528
 
        if (para->scroll_edge_corner && (priv->scroll.coast_speed_x || priv->scroll.coast_speed_y)) {
2529
 
            Bool is_in_corner =
2530
 
                ((edge & RIGHT_EDGE)  && (edge & (TOP_EDGE | BOTTOM_EDGE))) ||
2531
 
                ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) ;
2532
 
            if (!is_in_corner || !finger) {
2533
 
                DBG(7, "corner edge scroll off\n");
2534
 
                stop_coasting(priv);
2535
 
            }
2536
 
        }
2537
 
        /* if we were scrolling, but couldn't corner edge scroll,
2538
 
         * and are no longer scrolling, then start coasting */
2539
 
        oldv = oldv && !(priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on ||
2540
 
                      (priv->circ_scroll_on && priv->circ_scroll_vert));
2541
 
 
2542
 
        oldh = oldh && !(priv->horiz_scroll_twofinger_on || priv->horiz_scroll_edge_on ||
2543
 
                      (priv->circ_scroll_on && !priv->circ_scroll_vert));
2544
 
 
2545
 
        oldc = oldc && !priv->circ_scroll_on;
2546
 
 
2547
 
        if ((oldv || oldh) && !para->scroll_edge_corner) {
2548
 
            start_coasting(priv, hw, oldv, oldh, oldc);
2549
 
        }
 
2598
        Bool oldv = priv->vert_scroll_twofinger_on || priv->vert_scroll_edge_on
 
2599
            || (priv->circ_scroll_on && priv->circ_scroll_vert);
 
2600
 
 
2601
        Bool oldh = priv->horiz_scroll_twofinger_on ||
 
2602
            priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
 
2603
                                           !priv->circ_scroll_vert);
 
2604
 
 
2605
        Bool oldc = priv->circ_scroll_on;
 
2606
 
 
2607
        if (priv->circ_scroll_on && !finger) {
 
2608
            /* circular scroll locks in until finger is raised */
 
2609
            DBG(7, "cicular scroll off\n");
 
2610
            priv->circ_scroll_on = FALSE;
 
2611
        }
 
2612
 
 
2613
        if (!finger || hw->numFingers != 2) {
 
2614
            if (priv->vert_scroll_twofinger_on) {
 
2615
                DBG(7, "vert two-finger scroll off\n");
 
2616
                priv->vert_scroll_twofinger_on = FALSE;
 
2617
            }
 
2618
            if (priv->horiz_scroll_twofinger_on) {
 
2619
                DBG(7, "horiz two-finger scroll off\n");
 
2620
                priv->horiz_scroll_twofinger_on = FALSE;
 
2621
            }
 
2622
        }
 
2623
 
 
2624
        if (priv->vert_scroll_edge_on && (!(edge & RIGHT_EDGE) || !finger)) {
 
2625
            DBG(7, "vert edge scroll off\n");
 
2626
            priv->vert_scroll_edge_on = FALSE;
 
2627
        }
 
2628
        if (priv->horiz_scroll_edge_on && (!(edge & BOTTOM_EDGE) || !finger)) {
 
2629
            DBG(7, "horiz edge scroll off\n");
 
2630
            priv->horiz_scroll_edge_on = FALSE;
 
2631
        }
 
2632
        /* If we were corner edge scrolling (coasting),
 
2633
         * but no longer in corner or raised a finger, then stop coasting. */
 
2634
        if (para->scroll_edge_corner &&
 
2635
            (priv->scroll.coast_speed_x || priv->scroll.coast_speed_y)) {
 
2636
            Bool is_in_corner = ((edge & RIGHT_EDGE) &&
 
2637
                                 (edge & (TOP_EDGE | BOTTOM_EDGE))) ||
 
2638
                ((edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE)));
 
2639
            if (!is_in_corner || !finger) {
 
2640
                DBG(7, "corner edge scroll off\n");
 
2641
                stop_coasting(priv);
 
2642
            }
 
2643
        }
 
2644
        /* if we were scrolling, but couldn't corner edge scroll,
 
2645
         * and are no longer scrolling, then start coasting */
 
2646
        oldv = oldv && !(priv->vert_scroll_twofinger_on ||
 
2647
                         priv->vert_scroll_edge_on || (priv->circ_scroll_on &&
 
2648
                                                       priv->circ_scroll_vert));
 
2649
 
 
2650
        oldh = oldh && !(priv->horiz_scroll_twofinger_on ||
 
2651
                         priv->horiz_scroll_edge_on || (priv->circ_scroll_on &&
 
2652
                                                        !priv->
 
2653
                                                        circ_scroll_vert));
 
2654
 
 
2655
        oldc = oldc && !priv->circ_scroll_on;
 
2656
 
 
2657
        if ((oldv || oldh) && !para->scroll_edge_corner) {
 
2658
            start_coasting(priv, hw, oldv, oldh, oldc);
 
2659
        }
2550
2660
    }
2551
2661
 
2552
2662
    /* if hitting a corner (top right or bottom right) while vertical
2553
2663
     * scrolling is active, consider starting corner edge scrolling or
2554
2664
     * switching over to circular scrolling smoothly */
2555
2665
    if (priv->vert_scroll_edge_on && !priv->horiz_scroll_edge_on &&
2556
 
        (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
2557
 
        if (para->scroll_edge_corner) {
2558
 
            if (priv->scroll.coast_speed_y == 0) {
2559
 
                /* FYI: We can generate multiple start_coasting requests if
2560
 
                 * we're in the corner, but we were moving so slowly when we
2561
 
                 * got here that we didn't actually start coasting. */
2562
 
                DBG(7, "corner edge scroll on\n");
2563
 
                start_coasting(priv, hw, TRUE, FALSE, FALSE);
2564
 
            }
2565
 
        } else if (para->circular_scrolling) {
2566
 
            priv->vert_scroll_edge_on = FALSE;
2567
 
            priv->circ_scroll_on = TRUE;
2568
 
            priv->circ_scroll_vert = TRUE;
2569
 
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
2570
 
            DBG(7, "switching to circular scrolling\n");
2571
 
        }
 
2666
        (edge & RIGHT_EDGE) && (edge & (TOP_EDGE | BOTTOM_EDGE))) {
 
2667
        if (para->scroll_edge_corner) {
 
2668
            if (priv->scroll.coast_speed_y == 0) {
 
2669
                /* FYI: We can generate multiple start_coasting requests if
 
2670
                 * we're in the corner, but we were moving so slowly when we
 
2671
                 * got here that we didn't actually start coasting. */
 
2672
                DBG(7, "corner edge scroll on\n");
 
2673
                start_coasting(priv, hw, TRUE, FALSE, FALSE);
 
2674
            }
 
2675
        }
 
2676
        else if (para->circular_scrolling) {
 
2677
            priv->vert_scroll_edge_on = FALSE;
 
2678
            priv->circ_scroll_on = TRUE;
 
2679
            priv->circ_scroll_vert = TRUE;
 
2680
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
 
2681
            DBG(7, "switching to circular scrolling\n");
 
2682
        }
2572
2683
    }
2573
2684
    /* Same treatment for horizontal scrolling */
2574
2685
    if (priv->horiz_scroll_edge_on && !priv->vert_scroll_edge_on &&
2575
 
        (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
2576
 
        if (para->scroll_edge_corner) {
2577
 
            if (priv->scroll.coast_speed_x == 0) {
2578
 
                /* FYI: We can generate multiple start_coasting requests if
2579
 
                 * we're in the corner, but we were moving so slowly when we
2580
 
                 * got here that we didn't actually start coasting. */
2581
 
                DBG(7, "corner edge scroll on\n");
2582
 
                start_coasting(priv, hw, FALSE, TRUE, FALSE);
2583
 
            }
2584
 
        } else if (para->circular_scrolling) {
2585
 
            priv->horiz_scroll_edge_on = FALSE;
2586
 
            priv->circ_scroll_on = TRUE;
2587
 
            priv->circ_scroll_vert = FALSE;
2588
 
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
2589
 
            DBG(7, "switching to circular scrolling\n");
2590
 
        }
 
2686
        (edge & BOTTOM_EDGE) && (edge & (LEFT_EDGE | RIGHT_EDGE))) {
 
2687
        if (para->scroll_edge_corner) {
 
2688
            if (priv->scroll.coast_speed_x == 0) {
 
2689
                /* FYI: We can generate multiple start_coasting requests if
 
2690
                 * we're in the corner, but we were moving so slowly when we
 
2691
                 * got here that we didn't actually start coasting. */
 
2692
                DBG(7, "corner edge scroll on\n");
 
2693
                start_coasting(priv, hw, FALSE, TRUE, FALSE);
 
2694
            }
 
2695
        }
 
2696
        else if (para->circular_scrolling) {
 
2697
            priv->horiz_scroll_edge_on = FALSE;
 
2698
            priv->circ_scroll_on = TRUE;
 
2699
            priv->circ_scroll_vert = FALSE;
 
2700
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
 
2701
            DBG(7, "switching to circular scrolling\n");
 
2702
        }
2591
2703
    }
2592
2704
 
2593
2705
    if (priv->vert_scroll_edge_on || priv->horiz_scroll_edge_on ||
2594
 
        priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
2595
 
        priv->circ_scroll_on) {
2596
 
        priv->scroll.packets_this_scroll++;
 
2706
        priv->vert_scroll_twofinger_on || priv->horiz_scroll_twofinger_on ||
 
2707
        priv->circ_scroll_on) {
 
2708
        priv->scroll.packets_this_scroll++;
2597
2709
    }
2598
2710
 
2599
2711
    if (priv->vert_scroll_edge_on || priv->vert_scroll_twofinger_on) {
2600
 
        /* + = down, - = up */
2601
 
        if (para->scroll_dist_vert != 0 && hw->y != priv->scroll.last_y) {
2602
 
            priv->scroll.delta_y += (hw->y - priv->scroll.last_y);
2603
 
            priv->scroll.last_y = hw->y;
2604
 
        }
 
2712
        /* + = down, - = up */
 
2713
        if (para->scroll_dist_vert != 0 && hw->y != priv->scroll.last_y) {
 
2714
            priv->scroll.delta_y += (hw->y - priv->scroll.last_y);
 
2715
            priv->scroll.last_y = hw->y;
 
2716
        }
2605
2717
    }
2606
2718
    if (priv->horiz_scroll_edge_on || priv->horiz_scroll_twofinger_on) {
2607
 
        /* + = right, - = left */
2608
 
        if (para->scroll_dist_horiz != 0 && hw->x != priv->scroll.last_x) {
2609
 
            priv->scroll.delta_x += (hw->x - priv->scroll.last_x);
2610
 
            priv->scroll.last_x = hw->x;
2611
 
        }
 
2719
        /* + = right, - = left */
 
2720
        if (para->scroll_dist_horiz != 0 && hw->x != priv->scroll.last_x) {
 
2721
            priv->scroll.delta_x += (hw->x - priv->scroll.last_x);
 
2722
            priv->scroll.last_x = hw->x;
 
2723
        }
2612
2724
    }
2613
2725
    if (priv->circ_scroll_on) {
2614
 
        /* + = counter clockwise, - = clockwise */
2615
 
        double delta = para->scroll_dist_circ;
2616
 
        double diff = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
2617
 
        if (delta >= 0.005 && diff != 0.0) {
2618
 
            if (priv->circ_scroll_vert)
2619
 
                priv->scroll.delta_y -= diff / delta * para->scroll_dist_vert;
2620
 
            else
2621
 
                priv->scroll.delta_x -= diff / delta * para->scroll_dist_horiz;
2622
 
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
 
2726
        /* + = counter clockwise, - = clockwise */
 
2727
        double delta = para->scroll_dist_circ;
 
2728
        double diff = diffa(priv->scroll.last_a, angle(priv, hw->x, hw->y));
 
2729
 
 
2730
        if (delta >= 0.005 && diff != 0.0) {
 
2731
            if (priv->circ_scroll_vert)
 
2732
                priv->scroll.delta_y -= diff / delta * para->scroll_dist_vert;
 
2733
            else
 
2734
                priv->scroll.delta_x -= diff / delta * para->scroll_dist_horiz;
 
2735
            priv->scroll.last_a = angle(priv, hw->x, hw->y);
2623
2736
        }
2624
2737
    }
2625
2738
 
2626
2739
    if (priv->scroll.coast_speed_y) {
2627
 
        double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
2628
 
        double ddy = para->coasting_friction * dtime * abs(para->scroll_dist_vert);
 
2740
        double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
 
2741
        double ddy = para->coasting_friction * dtime;
2629
2742
 
2630
 
        priv->scroll.delta_y += priv->scroll.coast_speed_y * dtime;
2631
 
        delay = MIN(delay, POLL_MS);
2632
 
        if (abs(priv->scroll.coast_speed_y) < ddy) {
2633
 
            priv->scroll.coast_speed_y = 0;
2634
 
            priv->scroll.packets_this_scroll = 0;
2635
 
        } else {
2636
 
            priv->scroll.coast_speed_y += (priv->scroll.coast_speed_y < 0 ? ddy : -ddy);
2637
 
        }
 
2743
        priv->scroll.delta_y += priv->scroll.coast_speed_y * dtime * para->scroll_dist_vert;
 
2744
        delay = MIN(delay, POLL_MS);
 
2745
        if (abs(priv->scroll.coast_speed_y) < ddy) {
 
2746
            priv->scroll.coast_speed_y = 0;
 
2747
            priv->scroll.packets_this_scroll = 0;
 
2748
        }
 
2749
        else {
 
2750
            priv->scroll.coast_speed_y +=
 
2751
                (priv->scroll.coast_speed_y < 0 ? ddy : -ddy);
 
2752
        }
2638
2753
    }
2639
2754
 
2640
2755
    if (priv->scroll.coast_speed_x) {
2641
 
        double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
2642
 
        double ddx = para->coasting_friction * dtime * abs(para->scroll_dist_horiz);
2643
 
        priv->scroll.delta_x += priv->scroll.coast_speed_x * dtime;
2644
 
        delay = MIN(delay, POLL_MS);
2645
 
        if (abs(priv->scroll.coast_speed_x) < ddx) {
2646
 
            priv->scroll.coast_speed_x = 0;
2647
 
            priv->scroll.packets_this_scroll = 0;
2648
 
        } else {
2649
 
            priv->scroll.coast_speed_x += (priv->scroll.coast_speed_x < 0 ? ddx : -ddx);
2650
 
        }
 
2756
        double dtime = (hw->millis - priv->scroll.last_millis) / 1000.0;
 
2757
        double ddx = para->coasting_friction * dtime;
 
2758
        priv->scroll.delta_x += priv->scroll.coast_speed_x * dtime * para->scroll_dist_vert;
 
2759
        delay = MIN(delay, POLL_MS);
 
2760
        if (abs(priv->scroll.coast_speed_x) < ddx) {
 
2761
            priv->scroll.coast_speed_x = 0;
 
2762
            priv->scroll.packets_this_scroll = 0;
 
2763
        }
 
2764
        else {
 
2765
            priv->scroll.coast_speed_x +=
 
2766
                (priv->scroll.coast_speed_x < 0 ? ddx : -ddx);
 
2767
        }
2651
2768
    }
2652
2769
 
2653
2770
    return delay;
2658
2775
 * ClickFinger action.
2659
2776
 */
2660
2777
static int
2661
 
clickpad_guess_clickfingers(SynapticsPrivate *priv, struct SynapticsHwState *hw)
 
2778
clickpad_guess_clickfingers(SynapticsPrivate * priv,
 
2779
                            struct SynapticsHwState *hw)
2662
2780
{
2663
2781
    int nfingers = 0;
 
2782
 
2664
2783
#if HAVE_MULTITOUCH
2665
 
    char close_point[SYNAPTICS_MAX_TOUCHES] = {0}; /* 1 for each point close
2666
 
                                                      to another one */
 
2784
    char close_point[SYNAPTICS_MAX_TOUCHES] = { 0 };    /* 1 for each point close
 
2785
                                                           to another one */
2667
2786
    int i, j;
2668
2787
 
2669
2788
    for (i = 0; i < hw->num_mt_mask - 1; i++) {
2710
2829
    return nfingers;
2711
2830
}
2712
2831
 
2713
 
 
2714
2832
static void
2715
 
handle_clickfinger(SynapticsPrivate *priv, struct SynapticsHwState *hw)
 
2833
handle_clickfinger(SynapticsPrivate * priv, struct SynapticsHwState *hw)
2716
2834
{
2717
2835
    SynapticsParameters *para = &priv->synpara;
2718
2836
    int action = 0;
2727
2845
    if (para->clickpad)
2728
2846
        nfingers = clickpad_guess_clickfingers(priv, hw);
2729
2847
 
2730
 
    switch(nfingers) {
2731
 
        case 1:
2732
 
            action = para->click_action[F1_CLICK1];
2733
 
            break;
2734
 
        case 2:
2735
 
            action = para->click_action[F2_CLICK1];
2736
 
            break;
2737
 
        case 3:
2738
 
            action = para->click_action[F3_CLICK1];
2739
 
            break;
 
2848
    switch (nfingers) {
 
2849
    case 1:
 
2850
        action = para->click_action[F1_CLICK1];
 
2851
        break;
 
2852
    case 2:
 
2853
        action = para->click_action[F2_CLICK1];
 
2854
        break;
 
2855
    case 3:
 
2856
        action = para->click_action[F3_CLICK1];
 
2857
        break;
2740
2858
    }
2741
 
    switch(action){
2742
 
        case 1:
2743
 
            hw->left = 1 | BTN_EMULATED_FLAG;
2744
 
            break;
2745
 
        case 2:
2746
 
            hw->left = 0;
2747
 
            hw->middle = 1 | BTN_EMULATED_FLAG;
2748
 
            break;
2749
 
        case 3:
2750
 
            hw->left = 0;
2751
 
            hw->right = 1 | BTN_EMULATED_FLAG;
2752
 
            break;
 
2859
    switch (action) {
 
2860
    case 1:
 
2861
        hw->left = 1 | BTN_EMULATED_FLAG;
 
2862
        break;
 
2863
    case 2:
 
2864
        hw->left = 0;
 
2865
        hw->middle = 1 | BTN_EMULATED_FLAG;
 
2866
        break;
 
2867
    case 3:
 
2868
        hw->left = 0;
 
2869
        hw->right = 1 | BTN_EMULATED_FLAG;
 
2870
        break;
2753
2871
    }
2754
2872
}
2755
2873
 
2756
 
 
2757
2874
/* Update the hardware state in shared memory. This is read-only these days,
2758
2875
 * nothing in the driver reads back from SHM. SHM configuration is a thing of the past.
2759
2876
 */
2765
2882
    SynapticsSHM *shm = priv->synshm;
2766
2883
 
2767
2884
    if (!shm)
2768
 
            return;
 
2885
        return;
2769
2886
 
2770
2887
    shm->x = hw->x;
2771
2888
    shm->y = hw->y;
2777
2894
    shm->up = hw->up;
2778
2895
    shm->down = hw->down;
2779
2896
    for (i = 0; i < 8; i++)
2780
 
            shm->multi[i] = hw->multi[i];
 
2897
        shm->multi[i] = hw->multi[i];
2781
2898
    shm->middle = hw->middle;
2782
2899
}
2783
2900
 
2787
2904
 * function (or scrolling into).
2788
2905
 */
2789
2906
static Bool
2790
 
adjust_state_from_scrollbuttons(const InputInfoPtr pInfo, struct SynapticsHwState *hw)
 
2907
adjust_state_from_scrollbuttons(const InputInfoPtr pInfo,
 
2908
                                struct SynapticsHwState *hw)
2791
2909
{
2792
2910
    SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2793
2911
    SynapticsParameters *para = &priv->synpara;
2794
2912
    Bool double_click = FALSE;
2795
2913
 
2796
2914
    if (!para->updown_button_scrolling) {
2797
 
        if (hw->down) {         /* map down button to middle button */
2798
 
            hw->middle = TRUE;
2799
 
        }
2800
 
 
2801
 
        if (hw->up) {           /* up button generates double click */
2802
 
            if (!priv->prev_up)
2803
 
                double_click = TRUE;
2804
 
        }
2805
 
        priv->prev_up = hw->up;
2806
 
 
2807
 
        /* reset up/down button events */
2808
 
        hw->up = hw->down = FALSE;
 
2915
        if (hw->down) {         /* map down button to middle button */
 
2916
            hw->middle = TRUE;
 
2917
        }
 
2918
 
 
2919
        if (hw->up) {           /* up button generates double click */
 
2920
            if (!priv->prev_up)
 
2921
                double_click = TRUE;
 
2922
        }
 
2923
        priv->prev_up = hw->up;
 
2924
 
 
2925
        /* reset up/down button events */
 
2926
        hw->up = hw->down = FALSE;
2809
2927
    }
2810
2928
 
2811
2929
    /* Left/right button scrolling, or middle clicks */
2812
2930
    if (!para->leftright_button_scrolling) {
2813
 
        if (hw->multi[2] || hw->multi[3])
2814
 
            hw->middle = TRUE;
 
2931
        if (hw->multi[2] || hw->multi[3])
 
2932
            hw->middle = TRUE;
2815
2933
 
2816
 
        /* reset left/right button events */
2817
 
        hw->multi[2] = hw->multi[3] = FALSE;
 
2934
        /* reset left/right button events */
 
2935
        hw->multi[2] = hw->multi[3] = FALSE;
2818
2936
    }
2819
2937
 
2820
2938
    return double_click;
2836
2954
 
2837
2955
    /* If this is a clickpad and the user clicks in a soft button area, press
2838
2956
     * the soft button instead. */
2839
 
    if (para->clickpad && hw->left && !hw->right && !hw->middle)
2840
 
    {
2841
 
        if (is_inside_rightbutton_area(para, hw->x, hw->y))
2842
 
        {
2843
 
            hw->left = 0;
2844
 
            hw->right = 1;
 
2957
    if (para->clickpad) {
 
2958
        /* hw->left is down, but no other buttons were already down */
 
2959
        if (!old->left && !old->right && !old->middle &&
 
2960
            hw->left && !hw->right && !hw->middle) {
 
2961
                if (is_inside_rightbutton_area(para, hw->x, hw->y)) {
 
2962
                    hw->left = 0;
 
2963
                    hw->right = 1;
 
2964
                }
 
2965
                else if (is_inside_middlebutton_area(para, hw->x, hw->y)) {
 
2966
                    hw->left = 0;
 
2967
                    hw->middle = 1;
 
2968
                }
2845
2969
        }
2846
 
        else if (is_inside_middlebutton_area(para, hw->x, hw->y))
2847
 
        {
2848
 
            hw->left = 0;
2849
 
            hw->middle = 1;
 
2970
        else if (hw->left) {
 
2971
            hw->left = old->left;
 
2972
            hw->right = old->right;
 
2973
            hw->middle = old->middle;
2850
2974
        }
2851
2975
    }
2852
2976
 
2853
2977
    /* Fingers emulate other buttons. ClickFinger can only be
2854
2978
       triggered on transition, when left is pressed
2855
2979
     */
2856
 
    if(hw->left && !old->left && !old->middle && !old->right &&
2857
 
       hw->numFingers >= 1) {
 
2980
    if (hw->left && !old->left && !old->middle && !old->right &&
 
2981
        hw->numFingers >= 1) {
2858
2982
        handle_clickfinger(priv, hw);
2859
2983
    }
2860
2984
 
2861
2985
    /* Two finger emulation */
2862
2986
    if (hw->numFingers == 1 && hw->z >= para->emulate_twofinger_z &&
2863
2987
        hw->fingerWidth >= para->emulate_twofinger_w) {
2864
 
        hw->numFingers = 2;
 
2988
        hw->numFingers = 2;
2865
2989
    }
2866
2990
}
2867
2991
 
2872
2996
    xf86PostButtonEvent(pInfo->dev, FALSE, button, FALSE, 0, 0);
2873
2997
}
2874
2998
 
2875
 
 
2876
2999
static void
2877
3000
post_scroll_events(const InputInfoPtr pInfo)
2878
3001
{
2881
3004
#ifdef HAVE_SMOOTH_SCROLL
2882
3005
    valuator_mask_zero(priv->scroll_events_mask);
2883
3006
 
2884
 
    if (priv->scroll.delta_y != 0.0)
2885
 
    {
 
3007
    if (priv->scroll.delta_y != 0.0) {
2886
3008
        valuator_mask_set_double(priv->scroll_events_mask,
2887
 
                                 priv->scroll_axis_vert,
2888
 
                                 priv->scroll.delta_y);
 
3009
                                 priv->scroll_axis_vert, priv->scroll.delta_y);
2889
3010
        priv->scroll.delta_y = 0;
2890
3011
    }
2891
 
    if (priv->scroll.delta_x != 0.0)
2892
 
    {
 
3012
    if (priv->scroll.delta_x != 0.0) {
2893
3013
        valuator_mask_set_double(priv->scroll_events_mask,
2894
 
                                 priv->scroll_axis_horiz,
2895
 
                                 priv->scroll.delta_x);
 
3014
                                 priv->scroll_axis_horiz, priv->scroll.delta_x);
2896
3015
        priv->scroll.delta_x = 0;
2897
3016
    }
2898
3017
    if (valuator_mask_num_valuators(priv->scroll_events_mask))
2902
3021
 
2903
3022
    /* smooth scrolling uses the dist as increment */
2904
3023
 
2905
 
    while (priv->scroll.delta_y <= -para->scroll_dist_vert)
2906
 
    {
 
3024
    while (priv->scroll.delta_y <= -para->scroll_dist_vert) {
2907
3025
        post_button_click(pInfo, 4);
2908
3026
        priv->scroll.delta_y += para->scroll_dist_vert;
2909
3027
    }
2910
3028
 
2911
 
    while (priv->scroll.delta_y >= para->scroll_dist_vert)
2912
 
    {
 
3029
    while (priv->scroll.delta_y >= para->scroll_dist_vert) {
2913
3030
        post_button_click(pInfo, 5);
2914
3031
        priv->scroll.delta_y -= para->scroll_dist_vert;
2915
3032
    }
2916
3033
 
2917
 
    while (priv->scroll.delta_x <= -para->scroll_dist_horiz)
2918
 
    {
 
3034
    while (priv->scroll.delta_x <= -para->scroll_dist_horiz) {
2919
3035
        post_button_click(pInfo, 6);
2920
3036
        priv->scroll.delta_x += para->scroll_dist_horiz;
2921
3037
    }
2922
3038
 
2923
 
    while (priv->scroll.delta_x >= para->scroll_dist_horiz)
2924
 
    {
 
3039
    while (priv->scroll.delta_x >= para->scroll_dist_horiz) {
2925
3040
        post_button_click(pInfo, 7);
2926
3041
        priv->scroll.delta_x -= para->scroll_dist_horiz;
2927
3042
    }
2931
3046
static inline int
2932
3047
repeat_scrollbuttons(const InputInfoPtr pInfo,
2933
3048
                     const struct SynapticsHwState *hw,
2934
 
                     int buttons, CARD32 now, int delay)
 
3049
                     int buttons, CARD32 now, int delay)
2935
3050
{
2936
3051
    SynapticsPrivate *priv = (SynapticsPrivate *) (pInfo->private);
2937
3052
    SynapticsParameters *para = &priv->synpara;
2946
3061
    /* Handle auto repeat buttons */
2947
3062
    repeat_delay = clamp(para->scroll_button_repeat, SBR_MIN, SBR_MAX);
2948
3063
    if (((hw->up || hw->down) && para->updown_button_repeat &&
2949
 
         para->updown_button_scrolling) ||
2950
 
        ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
2951
 
         para->leftright_button_scrolling)) {
2952
 
        priv->repeatButtons = buttons & rep_buttons;
2953
 
        if (!priv->nextRepeat) {
2954
 
            priv->nextRepeat = now + repeat_delay * 2;
2955
 
        }
2956
 
    } else {
2957
 
        priv->repeatButtons = 0;
2958
 
        priv->nextRepeat = 0;
 
3064
         para->updown_button_scrolling) ||
 
3065
        ((hw->multi[2] || hw->multi[3]) && para->leftright_button_repeat &&
 
3066
         para->leftright_button_scrolling)) {
 
3067
        priv->repeatButtons = buttons & rep_buttons;
 
3068
        if (!priv->nextRepeat) {
 
3069
            priv->nextRepeat = now + repeat_delay * 2;
 
3070
        }
 
3071
    }
 
3072
    else {
 
3073
        priv->repeatButtons = 0;
 
3074
        priv->nextRepeat = 0;
2959
3075
    }
2960
3076
 
2961
3077
    if (priv->repeatButtons) {
2962
 
        timeleft = TIME_DIFF(priv->nextRepeat, now);
2963
 
        if (timeleft > 0)
2964
 
            delay = MIN(delay, timeleft);
2965
 
        if (timeleft <= 0) {
2966
 
            int change, id;
2967
 
            change = priv->repeatButtons;
2968
 
            while (change) {
2969
 
                id = ffs(change);
2970
 
                change &= ~(1 << (id - 1));
2971
 
                if (id == 4)
2972
 
                    priv->scroll.delta_y -= para->scroll_dist_vert;
2973
 
                else if (id == 5)
2974
 
                    priv->scroll.delta_y += para->scroll_dist_vert;
2975
 
                else if (id == 6)
2976
 
                    priv->scroll.delta_x -= para->scroll_dist_horiz;
2977
 
                else if (id == 7)
2978
 
                    priv->scroll.delta_x += para->scroll_dist_horiz;
2979
 
            }
2980
 
 
2981
 
            priv->nextRepeat = now + repeat_delay;
2982
 
            delay = MIN(delay, repeat_delay);
2983
 
        }
 
3078
        timeleft = TIME_DIFF(priv->nextRepeat, now);
 
3079
        if (timeleft > 0)
 
3080
            delay = MIN(delay, timeleft);
 
3081
        if (timeleft <= 0) {
 
3082
            int change, id;
 
3083
 
 
3084
            change = priv->repeatButtons;
 
3085
            while (change) {
 
3086
                id = ffs(change);
 
3087
                change &= ~(1 << (id - 1));
 
3088
                if (id == 4)
 
3089
                    priv->scroll.delta_y -= para->scroll_dist_vert;
 
3090
                else if (id == 5)
 
3091
                    priv->scroll.delta_y += para->scroll_dist_vert;
 
3092
                else if (id == 6)
 
3093
                    priv->scroll.delta_x -= para->scroll_dist_horiz;
 
3094
                else if (id == 7)
 
3095
                    priv->scroll.delta_x += para->scroll_dist_horiz;
 
3096
            }
 
3097
 
 
3098
            priv->nextRepeat = now + repeat_delay;
 
3099
            delay = MIN(delay, repeat_delay);
 
3100
        }
2984
3101
    }
2985
3102
 
2986
3103
    return delay;
2991
3108
UpdateTouchState(InputInfoPtr pInfo, struct SynapticsHwState *hw)
2992
3109
{
2993
3110
#ifdef HAVE_MULTITOUCH
2994
 
    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
 
3111
    SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
2995
3112
    int i;
2996
3113
 
2997
 
    for (i = 0; i < hw->num_mt_mask; i++)
2998
 
    {
2999
 
        if (hw->slot_state[i] == SLOTSTATE_OPEN)
3000
 
        {
 
3114
    for (i = 0; i < hw->num_mt_mask; i++) {
 
3115
        if (hw->slot_state[i] == SLOTSTATE_OPEN) {
3001
3116
            priv->open_slots[priv->num_active_touches] = i;
3002
3117
            priv->num_active_touches++;
3003
 
        } else if (hw->slot_state[i] == SLOTSTATE_CLOSE)
3004
 
        {
 
3118
        }
 
3119
        else if (hw->slot_state[i] == SLOTSTATE_CLOSE) {
3005
3120
            Bool found = FALSE;
3006
3121
            int j;
3007
3122
 
3008
 
            for (j = 0; j < priv->num_active_touches - 1; j++)
3009
 
            {
 
3123
            for (j = 0; j < priv->num_active_touches - 1; j++) {
3010
3124
                if (priv->open_slots[j] == i)
3011
3125
                    found = TRUE;
3012
3126
 
3026
3140
HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw)
3027
3141
{
3028
3142
#ifdef HAVE_MULTITOUCH
3029
 
    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
 
3143
    SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
3030
3144
    SynapticsParameters *para = &priv->synpara;
3031
3145
    int new_active_touches = priv->num_active_touches;
3032
3146
    int min_touches = 2;
3040
3154
        min_touches = 3;
3041
3155
 
3042
3156
    /* Count new number of active touches */
3043
 
    for (i = 0; i < hw->num_mt_mask; i++)
3044
 
    {
 
3157
    for (i = 0; i < hw->num_mt_mask; i++) {
3045
3158
        if (hw->slot_state[i] == SLOTSTATE_OPEN)
3046
3159
            new_active_touches++;
3047
3160
        else if (hw->slot_state[i] == SLOTSTATE_CLOSE)
3052
3165
        goto out;
3053
3166
 
3054
3167
    if (priv->num_active_touches < min_touches &&
3055
 
        new_active_touches < min_touches)
3056
 
    {
 
3168
        new_active_touches < min_touches) {
3057
3169
        /* We stayed below number of touches needed to send events */
3058
3170
        goto out;
3059
 
    } else if (priv->num_active_touches >= min_touches &&
3060
 
               new_active_touches < min_touches)
3061
 
    {
 
3171
    }
 
3172
    else if (priv->num_active_touches >= min_touches &&
 
3173
             new_active_touches < min_touches) {
3062
3174
        /* We are transitioning to less than the number of touches needed to
3063
3175
         * send events. End all currently open touches. */
3064
 
        for (i = 0; i < priv->num_active_touches; i++)
3065
 
        {
 
3176
        for (i = 0; i < priv->num_active_touches; i++) {
3066
3177
            int slot = priv->open_slots[i];
 
3178
 
3067
3179
            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0,
3068
3180
                               hw->mt_mask[slot]);
3069
3181
        }
3070
3182
 
3071
3183
        /* Don't send any more events */
3072
3184
        goto out;
3073
 
    } else if (priv->num_active_touches < min_touches &&
3074
 
               new_active_touches >= min_touches)
3075
 
    {
 
3185
    }
 
3186
    else if (priv->num_active_touches < min_touches &&
 
3187
             new_active_touches >= min_touches) {
3076
3188
        /* We are transitioning to more than the number of touches needed to
3077
3189
         * send events. Begin all already open touches. */
3078
3190
        restart_touches = TRUE;
3079
 
        for (i = 0; i < priv->num_active_touches; i++)
3080
 
        {
 
3191
        for (i = 0; i < priv->num_active_touches; i++) {
3081
3192
            int slot = priv->open_slots[i];
3082
3193
 
3083
3194
            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchBegin, 0,
3088
3199
    /* Send touch begin events for all new touches */
3089
3200
    for (i = 0; i < hw->num_mt_mask; i++)
3090
3201
        if (hw->slot_state[i] == SLOTSTATE_OPEN)
3091
 
            xf86PostTouchEvent(pInfo->dev, i, XI_TouchBegin, 0,
3092
 
                               hw->mt_mask[i]);
 
3202
            xf86PostTouchEvent(pInfo->dev, i, XI_TouchBegin, 0, hw->mt_mask[i]);
3093
3203
 
3094
3204
    /* Send touch update/end events for all the rest */
3095
 
    for (i = 0; i < priv->num_active_touches; i++)
3096
 
    {
 
3205
    for (i = 0; i < priv->num_active_touches; i++) {
3097
3206
        int slot = priv->open_slots[i];
3098
3207
 
3099
3208
        /* Don't send update event if we just reopened the touch above */
3105
3214
                               hw->mt_mask[slot]);
3106
3215
    }
3107
3216
 
3108
 
out:
 
3217
 out:
3109
3218
    UpdateTouchState(pInfo, hw);
3110
3219
#endif
3111
3220
}
3112
3221
 
3113
3222
static void
3114
 
filter_jitter(SynapticsPrivate *priv, int *x, int *y)
 
3223
filter_jitter(SynapticsPrivate * priv, int *x, int *y)
3115
3224
{
3116
3225
    SynapticsParameters *para = &priv->synpara;
3117
3226
 
3159
3268
    update_shm(pInfo, hw);
3160
3269
 
3161
3270
    /* If touchpad is switched off, we skip the whole thing and return delay */
3162
 
    if (para->touchpad_off == 1)
3163
 
    {
3164
 
        UpdateTouchState(pInfo, hw);
3165
 
        return delay;
 
3271
    if (para->touchpad_off == 1) {
 
3272
        UpdateTouchState(pInfo, hw);
 
3273
        return delay;
3166
3274
    }
3167
3275
 
3168
3276
    /* If a physical button is pressed on a clickpad, use cumulative relative
3169
3277
     * touch movements for motion */
3170
 
    if (para->clickpad && (hw->left || hw->right || hw->middle))
3171
 
    {
 
3278
    if (para->clickpad && (hw->left || hw->right || hw->middle)) {
3172
3279
        hw->x = hw->cumulative_dx;
3173
3280
        hw->y = hw->cumulative_dy;
3174
3281
    }
3183
3290
    /* now we know that these _coordinates_ aren't in the area.
3184
3291
       invalid are: x, y, z, numFingers, fingerWidth
3185
3292
       valid are: millis, left/right/middle/up/down/etc.
3186
 
    */
3187
 
    if (!inside_active_area)
3188
 
    {
3189
 
        reset_hw_state(hw);
 
3293
     */
 
3294
    if (!inside_active_area) {
 
3295
        reset_hw_state(hw);
3190
3296
 
3191
 
        /* FIXME: if finger accidentally moves into the area and doesn't
3192
 
         * really release, the finger should remain down. */
 
3297
        /* FIXME: if finger accidentally moves into the area and doesn't
 
3298
         * really release, the finger should remain down. */
3193
3299
    }
3194
3300
 
3195
3301
    /* these two just update hw->left, right, etc. */
3196
3302
    update_hw_button_state(pInfo, hw, priv->old_hw_state, now, &delay);
3197
3303
    if (priv->has_scrollbuttons)
3198
 
        double_click = adjust_state_from_scrollbuttons(pInfo, hw);
 
3304
        double_click = adjust_state_from_scrollbuttons(pInfo, hw);
3199
3305
 
3200
3306
    /* no edge or finger detection outside of area */
3201
3307
    if (inside_active_area) {
3202
 
        edge = edge_detection(priv, hw->x, hw->y);
3203
 
        if (!from_timer)
3204
 
            finger = SynapticsDetectFinger(priv, hw);
3205
 
        else
3206
 
            finger = priv->finger_state;
 
3308
        edge = edge_detection(priv, hw->x, hw->y);
 
3309
        if (!from_timer)
 
3310
            finger = SynapticsDetectFinger(priv, hw);
 
3311
        else
 
3312
            finger = priv->finger_state;
3207
3313
    }
3208
3314
 
3209
3315
    /* tap and drag detection. Needs to be performed even if the finger is in
3210
3316
     * the dead area to reset the state. */
3211
3317
    timeleft = HandleTapProcessing(priv, hw, now, finger, inside_active_area);
3212
3318
    if (timeleft > 0)
3213
 
        delay = MIN(delay, timeleft);
3214
 
 
3215
 
    if (inside_active_area)
3216
 
    {
3217
 
        /* Don't bother about scrolling in the dead area of the touchpad. */
3218
 
        timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED));
3219
 
        if (timeleft > 0)
3220
 
            delay = MIN(delay, timeleft);
3221
 
 
3222
 
        /*
3223
 
         * Compensate for unequal x/y resolution. This needs to be done after
3224
 
         * calculations that require unadjusted coordinates, for example edge
3225
 
         * detection.
3226
 
         */
3227
 
        ScaleCoordinates(priv, hw);
 
3319
        delay = MIN(delay, timeleft);
 
3320
 
 
3321
    if (inside_active_area) {
 
3322
        /* Don't bother about scrolling in the dead area of the touchpad. */
 
3323
        timeleft = HandleScrolling(priv, hw, edge, (finger >= FS_TOUCHED));
 
3324
        if (timeleft > 0)
 
3325
            delay = MIN(delay, timeleft);
 
3326
 
 
3327
        /*
 
3328
         * Compensate for unequal x/y resolution. This needs to be done after
 
3329
         * calculations that require unadjusted coordinates, for example edge
 
3330
         * detection.
 
3331
         */
 
3332
        ScaleCoordinates(priv, hw);
3228
3333
    }
3229
3334
 
3230
3335
    dx = dy = 0;
3231
3336
 
3232
3337
    if (!priv->absolute_events) {
3233
 
      timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area);
3234
 
      delay = MIN(delay, timeleft);
 
3338
        timeleft = ComputeDeltas(priv, hw, edge, &dx, &dy, inside_active_area);
 
3339
        delay = MIN(delay, timeleft);
3235
3340
    }
3236
3341
 
3237
 
 
3238
 
    buttons = ((hw->left     ? 0x01 : 0) |
3239
 
               (hw->middle   ? 0x02 : 0) |
3240
 
               (hw->right    ? 0x04 : 0) |
3241
 
               (hw->up       ? 0x08 : 0) |
3242
 
               (hw->down     ? 0x10 : 0) |
3243
 
               (hw->multi[2] ? 0x20 : 0) |
3244
 
               (hw->multi[3] ? 0x40 : 0));
 
3342
    buttons = ((hw->left ? 0x01 : 0) |
 
3343
               (hw->middle ? 0x02 : 0) |
 
3344
               (hw->right ? 0x04 : 0) |
 
3345
               (hw->up ? 0x08 : 0) |
 
3346
               (hw->down ? 0x10 : 0) |
 
3347
               (hw->multi[2] ? 0x20 : 0) | (hw->multi[3] ? 0x40 : 0));
3245
3348
 
3246
3349
    if (priv->tap_button > 0) {
3247
 
        int tap_mask = 1 << (priv->tap_button - 1);
3248
 
        if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) {
3249
 
            if (tap_mask != (priv->lastButtons & tap_mask)) {
3250
 
                xf86PostButtonEvent(pInfo->dev, FALSE, priv->tap_button, TRUE, 0, 0);
3251
 
                priv->lastButtons |= tap_mask;
3252
 
            }
3253
 
            priv->tap_button_state = TBS_BUTTON_UP;
3254
 
        }
3255
 
        if (priv->tap_button_state == TBS_BUTTON_DOWN)
3256
 
            buttons |= tap_mask;
 
3350
        int tap_mask = 1 << (priv->tap_button - 1);
 
3351
 
 
3352
        if (priv->tap_button_state == TBS_BUTTON_DOWN_UP) {
 
3353
            if (tap_mask != (priv->lastButtons & tap_mask)) {
 
3354
                xf86PostButtonEvent(pInfo->dev, FALSE, priv->tap_button, TRUE,
 
3355
                                    0, 0);
 
3356
                priv->lastButtons |= tap_mask;
 
3357
            }
 
3358
            priv->tap_button_state = TBS_BUTTON_UP;
 
3359
        }
 
3360
        if (priv->tap_button_state == TBS_BUTTON_DOWN)
 
3361
            buttons |= tap_mask;
3257
3362
    }
3258
3363
 
3259
3364
    /* Post events */
3260
3365
    if (finger >= FS_TOUCHED) {
3261
3366
        if (priv->absolute_events && inside_active_area) {
3262
3367
            xf86PostMotionEvent(pInfo->dev, 1, 0, 2, hw->x, hw->y);
3263
 
        } else if (dx || dy) {
 
3368
        }
 
3369
        else if (dx || dy) {
3264
3370
            xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
3265
3371
        }
3266
3372
    }
3267
3373
 
3268
 
    if (priv->mid_emu_state == MBE_LEFT_CLICK)
3269
 
    {
3270
 
        post_button_click(pInfo, 1);
3271
 
        priv->mid_emu_state = MBE_OFF;
3272
 
    } else if (priv->mid_emu_state == MBE_RIGHT_CLICK)
3273
 
    {
3274
 
        post_button_click(pInfo, 3);
3275
 
        priv->mid_emu_state = MBE_OFF;
 
3374
    if (priv->mid_emu_state == MBE_LEFT_CLICK) {
 
3375
        post_button_click(pInfo, 1);
 
3376
        priv->mid_emu_state = MBE_OFF;
 
3377
    }
 
3378
    else if (priv->mid_emu_state == MBE_RIGHT_CLICK) {
 
3379
        post_button_click(pInfo, 3);
 
3380
        priv->mid_emu_state = MBE_OFF;
3276
3381
    }
3277
3382
 
3278
3383
    change = buttons ^ priv->lastButtons;
3279
3384
    while (change) {
3280
 
        id = ffs(change); /* number of first set bit 1..32 is returned */
3281
 
        change &= ~(1 << (id - 1));
3282
 
        xf86PostButtonEvent(pInfo->dev, FALSE, id, (buttons & (1 << (id - 1))), 0, 0);
 
3385
        id = ffs(change);       /* number of first set bit 1..32 is returned */
 
3386
        change &= ~(1 << (id - 1));
 
3387
        xf86PostButtonEvent(pInfo->dev, FALSE, id, (buttons & (1 << (id - 1))),
 
3388
                            0, 0);
3283
3389
    }
3284
3390
 
3285
3391
    if (priv->has_scrollbuttons)
3286
 
        delay = repeat_scrollbuttons(pInfo, hw, buttons, now, delay);
 
3392
        delay = repeat_scrollbuttons(pInfo, hw, buttons, now, delay);
3287
3393
 
3288
3394
    /* Process scroll events only if coordinates are
3289
3395
     * in the Synaptics Area
3290
3396
     */
3291
3397
    if (inside_active_area &&
3292
3398
        (priv->scroll.delta_x != 0.0 || priv->scroll.delta_y != 0.0)) {
3293
 
        post_scroll_events(pInfo);
3294
 
        priv->scroll.last_millis = hw->millis;
 
3399
        post_scroll_events(pInfo);
 
3400
        priv->scroll.last_millis = hw->millis;
3295
3401
    }
3296
3402
 
3297
3403
    if (double_click) {
3298
 
        post_button_click(pInfo, 1);
3299
 
        post_button_click(pInfo, 1);
 
3404
        post_button_click(pInfo, 1);
 
3405
        post_button_click(pInfo, 1);
3300
3406
    }
3301
3407
 
3302
3408
    HandleTouches(pInfo, hw);
3307
3413
 
3308
3414
    /* generate a history of the absolute positions */
3309
3415
    if (inside_active_area)
3310
 
        store_history(priv, hw->x, hw->y, hw->millis);
 
3416
        store_history(priv, hw->x, hw->y, hw->millis);
3311
3417
 
3312
3418
    /* Save logical state for transition comparisons */
3313
3419
    SynapticsCopyHwState(priv->old_hw_state, hw);
3322
3428
    return Success;
3323
3429
}
3324
3430
 
3325
 
 
3326
3431
static int
3327
3432
SwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
3328
3433
{
3353
3458
    SynapticsPrivate *priv = (SynapticsPrivate *) pInfo->private;
3354
3459
 
3355
3460
    if (priv->proto_ops->ReadDevDimensions)
3356
 
        priv->proto_ops->ReadDevDimensions(pInfo);
 
3461
        priv->proto_ops->ReadDevDimensions(pInfo);
3357
3462
 
3358
3463
    SanitizeDimensions(pInfo);
3359
3464
}
3366
3471
    priv->comm.protoBufTail = 0;
3367
3472
 
3368
3473
    if (!priv->proto_ops->QueryHardware(pInfo)) {
3369
 
        xf86IDrvMsg(pInfo, X_PROBED, "no supported touchpad found\n");
3370
 
        if (priv->proto_ops->DeviceOffHook)
 
3474
        xf86IDrvMsg(pInfo, X_PROBED, "no supported touchpad found\n");
 
3475
        if (priv->proto_ops->DeviceOffHook)
3371
3476
            priv->proto_ops->DeviceOffHook(pInfo);
3372
3477
        return FALSE;
3373
3478
    }
3376
3481
}
3377
3482
 
3378
3483
static void
3379
 
ScaleCoordinates(SynapticsPrivate *priv, struct SynapticsHwState *hw)
 
3484
ScaleCoordinates(SynapticsPrivate * priv, struct SynapticsHwState *hw)
3380
3485
{
3381
3486
    int xCenter = (priv->synpara.left_edge + priv->synpara.right_edge) / 2;
3382
3487
    int yCenter = (priv->synpara.top_edge + priv->synpara.bottom_edge) / 2;
3386
3491
}
3387
3492
 
3388
3493
void
3389
 
CalculateScalingCoeffs(SynapticsPrivate *priv)
 
3494
CalculateScalingCoeffs(SynapticsPrivate * priv)
3390
3495
{
3391
3496
    int vertRes = priv->synpara.resolution_vert;
3392
3497
    int horizRes = priv->synpara.resolution_horiz;
3393
3498
 
3394
3499
    if ((horizRes > vertRes) && (horizRes > 0)) {
3395
 
        priv->horiz_coeff = vertRes / (double)horizRes;
 
3500
        priv->horiz_coeff = vertRes / (double) horizRes;
3396
3501
        priv->vert_coeff = 1;
3397
 
    } else if ((horizRes < vertRes) && (vertRes > 0)) {
 
3502
    }
 
3503
    else if ((horizRes < vertRes) && (vertRes > 0)) {
3398
3504
        priv->horiz_coeff = 1;
3399
 
        priv->vert_coeff = horizRes / (double)vertRes;
3400
 
    } else {
 
3505
        priv->vert_coeff = horizRes / (double) vertRes;
 
3506
    }
 
3507
    else {
3401
3508
        priv->horiz_coeff = 1;
3402
3509
        priv->vert_coeff = 1;
3403
3510
    }