1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qmousepc_qws.h"
43
44 #ifndef QT_NO_QWS_MOUSE_PC
45
46 #include "qwindowsystem_qws.h"
47 #include "qsocketnotifier.h"
48 #include "qwsevent_qws.h"
49 #include "qwscommand_qws_p.h"
50 #include "qwsutils_qws.h"
51
52 #include "qapplication.h"
53 #include "qpolygon.h"
54 #include "qtimer.h"
55 #include "qfile.h"
56 #include "qtextstream.h"
57 #include "qstringlist.h"
58 #include <private/qcore_unix_p.h> // overrides QT_OPEN
59
60 #include <unistd.h>
61 #include <stdlib.h>
62 #include <stdio.h>
63 #include <sys/ioctl.h>
64 #include <sys/types.h>
65 #include <sys/stat.h>
66 #include <fcntl.h>
67 #include <errno.h>
68 #include <termios.h>
69
70 #include <qscreen_qws.h>
71
72 QT_BEGIN_NAMESPACE
73
74 //#define QWS_MOUSE_DEBUG
75
76 /*
77 * Automatic-detection mouse driver
78 */
79
80 class QWSPcMouseSubHandler {
81 protected:
82 enum { max_buf=32 };
83
84 int fd;
85
86 uchar buffer[max_buf];
87 int nbuf;
88
89 QPoint motion;
90 int bstate;
91 int wheel;
92
93 int goodness;
94 int badness;
95
96 virtual int tryData()=0;
97
98 public:
QWSPcMouseSubHandler(int f)99 QWSPcMouseSubHandler(int f) : fd(f)
100 {
101 initState();
102 }
~QWSPcMouseSubHandler()103 virtual ~QWSPcMouseSubHandler() {}
104
file() const105 int file() const { return fd; }
106
closeIfNot(int & f)107 void closeIfNot(int& f)
108 {
109 if (fd != f) {
110 f = fd;
111 QT_CLOSE(fd);
112 }
113 }
114
initState()115 void initState() { nbuf = bstate = goodness = badness = 0; }
116
worse(int by=1)117 void worse(int by=1) { badness+=by; }
reliable() const118 bool reliable() const { return goodness >= 5 && badness < 50; }
buttonState() const119 int buttonState() const { return bstate; }
motionPending() const120 bool motionPending() const { return motion!=QPoint(0,0); }
takeMotion()121 QPoint takeMotion() { QPoint r=motion; motion=QPoint(0,0); return r; }
takeWheel()122 int takeWheel() { int result = wheel; wheel = 0; return result; }
123
appendData(uchar * data,int length)124 void appendData(uchar* data, int length)
125 {
126 memcpy(buffer+nbuf, data, length);
127 nbuf += length;
128 }
129
130 enum UsageResult { Insufficient, Motion, Button };
131
useData()132 UsageResult useData()
133 {
134 int pbstate = bstate;
135 int n = tryData();
136 #ifdef QWS_MOUSE_DEBUG
137 if (n) {
138 fprintf(stderr, "QWSPcMouseSubHandler tryData read %d bytes:", n);
139 for (int i=0; i<n; ++i)
140 fprintf(stderr, " %02x", buffer[i]);
141 fprintf(stderr, "\n");
142 }
143 #endif
144 if (n > 0) {
145 if (n<nbuf)
146 memmove(buffer, buffer+n, nbuf-n);
147 nbuf -= n;
148 return (wheel || pbstate != bstate) ? Button : Motion;
149 }
150 return Insufficient;
151 }
152 };
153
154 class QWSPcMouseSubHandler_intellimouse : public QWSPcMouseSubHandler {
155 int packetsize;
156 public:
QWSPcMouseSubHandler_intellimouse(int f)157 QWSPcMouseSubHandler_intellimouse(int f) : QWSPcMouseSubHandler(f)
158 {
159 init();
160 }
161
init()162 void init()
163 {
164 int n;
165 uchar reply[20];
166
167 if (tcflush(fd,TCIOFLUSH) == -1) {
168 #ifdef QWS_MOUSE_DEBUG
169 perror("QWSPcMouseSubHandler_intellimouse: pre-init tcflush");
170 #endif
171 }
172 static const uchar initseq[] = { 243, 200, 243, 100, 243, 80 };
173 static const uchar query[] = { 0xf2 };
174 if (QT_WRITE(fd, initseq, sizeof(initseq))!=sizeof(initseq)) {
175 badness = 100;
176 return;
177 }
178 usleep(10000);
179 if (tcflush(fd,TCIOFLUSH) == -1) {
180 #ifdef QWS_MOUSE_DEBUG
181 perror("QWSPcMouseSubHandler_intellimouse: post-init tcflush");
182 #endif
183 }
184 if (QT_WRITE(fd, query, sizeof(query))!=sizeof(query)) {
185 badness = 100;
186 return;
187 }
188 usleep(10000);
189 n = QT_READ(fd, reply, 20);
190 if (n > 0) {
191 goodness = 10;
192 switch (reply[n-1]) {
193 case 3:
194 case 4:
195 packetsize = 4;
196 break;
197 default:
198 packetsize = 3;
199 }
200 } else {
201 badness = 100;
202 }
203 }
204
tryData()205 int tryData()
206 {
207 if (nbuf >= packetsize) {
208 //int overflow = (buffer[0]>>6)& 0x03;
209
210 if (/*overflow ||*/ !(buffer[0] & 8)) {
211 #ifdef QWS_MOUSE_DEBUG
212 qDebug("Intellimouse: skipping (overflow)");
213 #endif
214 badness++;
215 return 1;
216 } else {
217 QPoint delta((buffer[0] & 0x10) ? buffer[1]-256 : buffer[1],
218 (buffer[0] & 0x20) ? 256-buffer[2] : -buffer[2]);
219 motion += delta;
220 int nbstate = buffer[0] & 0x7;
221 #ifdef QWS_MOUSE_DEBUG
222 int debugwheel =
223 #endif
224 wheel = packetsize > 3 ? -(signed char)buffer[3] : 0;
225 if (wheel < -2 || wheel > 2)
226 wheel = 0;
227 wheel *= 120; // WHEEL_DELTA?
228 #ifdef QWS_MOUSE_DEBUG
229 qDebug("Intellimouse: motion %d,%d, state %d, raw wheel %d, wheel %d", motion.x(), motion.y(), nbstate, debugwheel, wheel);
230 #endif
231 if (motion.x() || motion.y() || bstate != nbstate || wheel) {
232 bstate = nbstate;
233 goodness++;
234 } else {
235 badness++;
236 return 1;
237 }
238 }
239 return packetsize;
240 }
241 return 0;
242 }
243 };
244
245 class QWSPcMouseSubHandler_mouseman : public QWSPcMouseSubHandler {
246 int packetsize;
247 public:
QWSPcMouseSubHandler_mouseman(int f)248 QWSPcMouseSubHandler_mouseman(int f) : QWSPcMouseSubHandler(f)
249 {
250 init();
251 }
252
init()253 void init()
254 {
255 if (tcflush(fd,TCIOFLUSH) == -1) {
256 #ifdef QWS_MOUSE_DEBUG
257 perror("QWSPcMouseSubHandler_mouseman: initial tcflush");
258 #endif
259 }
260 QT_WRITE(fd,"",1);
261 usleep(50000);
262 QT_WRITE(fd,"@EeI!",5);
263 usleep(10000);
264 static const unsigned char ibuf[] = { 246, 244 };
265 QT_WRITE(fd,ibuf,1);
266 QT_WRITE(fd,ibuf+1,1);
267 if (tcflush(fd,TCIOFLUSH) == -1) {
268 #ifdef QWS_MOUSE_DEBUG
269 perror("QWSPcMouseSubHandler_mouseman: tcflush");
270 #endif
271 }
272 usleep(10000);
273
274 char buf[100];
275 while (QT_READ(fd, buf, 100) > 0) { } // eat unwanted replies
276 }
277
tryData()278 int tryData()
279 {
280 if (nbuf >= 3) {
281 int nbstate = 0;
282 if (buffer[0] & 0x01)
283 nbstate |= Qt::LeftButton;
284 if (buffer[0] & 0x02)
285 nbstate |= Qt::RightButton;
286 if (buffer[0] & 0x04)
287 nbstate |= Qt::MidButton;
288
289 int overflow = (buffer[0]>>6)& 0x03;
290 if (overflow) {
291 //### wheel events signalled with overflow bit, ignore for now
292 badness++;
293 return 1;
294 } else {
295 bool xs = buffer[0] & 0x10;
296 bool ys = buffer[0] & 0x20;
297 int dx = xs ? buffer[1]-256 : buffer[1];
298 int dy = ys ? buffer[2]-256 : buffer[2];
299
300 motion += QPoint(dx, -dy);
301 if (motion.x() || motion.y() || bstate != nbstate) {
302 bstate = nbstate;
303 goodness++;
304 } else {
305 badness++;
306 return 1;
307 }
308 }
309 return 3;
310 }
311 return 0;
312 }
313 };
314
315 class QWSPcMouseSubHandler_serial : public QWSPcMouseSubHandler {
316 public:
QWSPcMouseSubHandler_serial(int f)317 QWSPcMouseSubHandler_serial(int f) : QWSPcMouseSubHandler(f)
318 {
319 initSerial();
320 }
321
322 protected:
setflags(int f)323 void setflags(int f)
324 {
325 termios tty;
326 if (tcgetattr(fd, &tty) == -1) {
327 #ifdef QWS_MOUSE_DEBUG
328 perror("QWSPcMouseSubHandler_serial: tcgetattr");
329 #endif
330 }
331 tty.c_iflag = IGNBRK | IGNPAR;
332 tty.c_oflag = 0;
333 tty.c_lflag = 0;
334 tty.c_cflag = f | CREAD | CLOCAL | HUPCL;
335 #ifdef Q_OS_LINUX
336 tty.c_line = 0;
337 #endif
338 tty.c_cc[VTIME] = 0;
339 tty.c_cc[VMIN] = 1;
340 if (tcsetattr(fd, TCSANOW, &tty) == -1) {
341 #ifdef QWS_MOUSE_DEBUG
342 perror("QWSPcMouseSubHandler_serial: tcgetattr");
343 #endif
344 }
345 }
346
347 private:
initSerial()348 void initSerial()
349 {
350 int speed[4] = { B9600, B4800, B2400, B1200 };
351
352 for (int n = 0; n < 4; n++) {
353 setflags(CSTOPB | speed[n]);
354 QT_WRITE(fd, "*q", 2);
355 usleep(10000);
356 }
357 }
358 };
359
360 class QWSPcMouseSubHandler_mousesystems : public QWSPcMouseSubHandler_serial {
361 public:
362 // ##### This driver has not been tested
363
QWSPcMouseSubHandler_mousesystems(int f)364 QWSPcMouseSubHandler_mousesystems(int f) : QWSPcMouseSubHandler_serial(f)
365 {
366 init();
367 }
368
init()369 void init()
370 {
371 setflags(B1200|CS8|CSTOPB);
372 // 60Hz
373 if (QT_WRITE(fd, "R", 1)!=1) {
374 badness = 100;
375 return;
376 }
377 if (tcflush(fd,TCIOFLUSH) == -1) {
378 #ifdef QT_QWS_VNC_DEBUG
379 perror("QWSPcMouseSubHandler_mousesystems: tcflush");
380 #endif
381 }
382 }
383
tryData()384 int tryData()
385 {
386 if (nbuf >= 5) {
387 if ((buffer[0] & 0xf8) != 0x80) {
388 badness++;
389 return 1;
390 }
391 motion +=
392 QPoint((signed char)buffer[1] + (signed char)buffer[3],
393 -(signed char)buffer[2] + (signed char)buffer[4]);
394 int t = ~buffer[0];
395 int nbstate = ((t&3) << 1) | ((t&4) >> 2);
396 if (motion.x() || motion.y() || bstate != nbstate) {
397 bstate = nbstate;
398 goodness++;
399 } else {
400 badness++;
401 return 1;
402 }
403 return 5;
404 }
405 return 0;
406 }
407 };
408
409 class QWSPcMouseSubHandler_ms : public QWSPcMouseSubHandler_serial {
410 int mman;
411 public:
QWSPcMouseSubHandler_ms(int f)412 QWSPcMouseSubHandler_ms(int f) : QWSPcMouseSubHandler_serial(f)
413 {
414 mman=0;
415 init();
416 }
417
init()418 void init()
419 {
420 setflags(B1200|CS7);
421 // 60Hz
422 if (QT_WRITE(fd, "R", 1)!=1) {
423 badness = 100;
424 return;
425 }
426 if (tcflush(fd,TCIOFLUSH) == -1) {
427 #ifdef QWS_MOUSE_DEBUG
428 perror("QWSPcMouseSubHandler_ms: tcflush");
429 #endif
430 }
431 }
432
tryData()433 int tryData()
434 {
435 if (!(buffer[0] & 0x40)) {
436 if (buffer[0] == 0x20 && (bstate & Qt::MidButton)) {
437 mman=1; // mouseman extension
438 }
439 return 1;
440 }
441 int extra = mman&&(bstate & Qt::MidButton);
442 if (nbuf >= 3+extra) {
443 int nbstate = 0;
444 if (buffer[0] == 0x40 && !bstate && !buffer[1] && !buffer[2]) {
445 nbstate = Qt::MidButton;
446 } else {
447 nbstate = ((buffer[0] & 0x20) >> 5)
448 | ((buffer[0] & 0x10) >> 3);
449 if (extra && buffer[3] == 0x20)
450 nbstate = Qt::MidButton;
451 }
452
453 if (buffer[1] & 0x40) {
454 badness++;
455 return 1;
456 } else {
457 motion +=
458 QPoint((signed char)((buffer[0]&0x3)<<6)
459 |(signed char)(buffer[1]&0x3f),
460 (signed char)((buffer[0]&0xc)<<4)
461 |(signed char)(buffer[2]&0x3f));
462 if (motion.x() || motion.y() || bstate != nbstate) {
463 bstate = nbstate;
464 goodness++;
465 } else {
466 badness++;
467 return 1;
468 }
469 return 3+extra;
470 }
471 }
472 return 0;
473 }
474 };
475
476 //===========================================================================
477
478 class QWSPcMouseHandlerPrivate : public QObject
479 {
480 Q_OBJECT
481 public:
482 QWSPcMouseHandlerPrivate(QWSPcMouseHandler *h, const QString &, const QString &);
483 ~QWSPcMouseHandlerPrivate();
484
485 void suspend();
486 void resume();
487
488 private:
489 enum { max_dev=32 };
490 QWSPcMouseSubHandler *sub[max_dev];
491 QList<QSocketNotifier*> notifiers;
492 int nsub;
493 int retries;
494
495 private slots:
496 void readMouseData(int);
497
498 private:
499 void openDevices();
500 void closeDevices();
501 void notify(int fd);
502 bool sendEvent(QWSPcMouseSubHandler& h);
503
504 private:
505 QWSPcMouseHandler *handler;
506 QString driver;
507 QString device;
508 qreal accel;
509 int accel_limit;
510 };
511
QWSPcMouseHandler(const QString & driver,const QString & device)512 QWSPcMouseHandler::QWSPcMouseHandler(const QString &driver, const QString &device)
513 : QWSMouseHandler(driver, device)
514 {
515 d = new QWSPcMouseHandlerPrivate(this, driver, device);
516 }
517
~QWSPcMouseHandler()518 QWSPcMouseHandler::~QWSPcMouseHandler()
519 {
520 delete d;
521 }
522
suspend()523 void QWSPcMouseHandler::suspend()
524 {
525 d->suspend();
526 }
527
resume()528 void QWSPcMouseHandler::resume()
529 {
530 d->resume();
531 }
532
533
QWSPcMouseHandlerPrivate(QWSPcMouseHandler * h,const QString & drv,const QString & arg)534 QWSPcMouseHandlerPrivate::QWSPcMouseHandlerPrivate(QWSPcMouseHandler *h,
535 const QString &drv, const QString &arg)
536 : handler(h), driver(drv)
537 {
538 QStringList args = arg.split(QLatin1Char(':'), QString::SkipEmptyParts);
539
540 int index;
541
542 accel = qreal(2.0);
543 QRegExp accelRegex(QLatin1String("^accel=(\\d+\\.?\\d*)$"));
544 index = args.indexOf(accelRegex);
545 if (index >= 0) {
546 accel = qreal(accelRegex.cap(1).toDouble());
547 args.removeAt(index);
548 }
549
550 accel_limit = 5;
551 QRegExp accelLimitRegex(QLatin1String("^accel_limit=(\\d+)$"));
552 index = args.indexOf(accelLimitRegex);
553 if (index >= 0) {
554 accel_limit = accelLimitRegex.cap(1).toInt();
555 args.removeAt(index);
556 }
557
558 device = args.join(QString());
559
560 retries = 0;
561 openDevices();
562 }
563
~QWSPcMouseHandlerPrivate()564 QWSPcMouseHandlerPrivate::~QWSPcMouseHandlerPrivate()
565 {
566 closeDevices();
567 }
568
569 /*
570 QWSPcMouseHandler::UsageResult QWSPcMouseHandler::useDev(Dev& d)
571 {
572 if (d.nbuf >= mouseData[d.protocol].bytesPerPacket) {
573 uchar *mb = d.buf;
574 int bstate = 0;
575 int dx = 0;
576 int dy = 0;
577
578 switch (mouseProtocol) {
579 case MouseMan:
580 case IntelliMouse:
581 {
582 bstate = mb[0] & 0x7; // assuming Qt::*Button order
583
584 int overflow = (mb[0]>>6)& 0x03;
585 if (mouseProtocol == MouseMan && overflow) {
586 //### wheel events signalled with overflow bit, ignore for now
587 }
588 else {
589 bool xs = mb[0] & 0x10;
590 bool ys = mb[0] & 0x20;
591 dx = xs ? mb[1]-256 : mb[1];
592 dy = ys ? mb[2]-256 : mb[2];
593 }
594 break;
595 }
596 case Microsoft:
597 if (((mb[0] & 0x20) >> 3)) {
598 bstate |= Qt::LeftButton;
599 }
600 if (((mb[0] & 0x10) >> 4)) {
601 bstate |= Qt::RightButton;
602 }
603
604 dx=(signed char)(((mb[0] & 0x03) << 6) | (mb[1] & 0x3f));
605 dy=-(signed char)(((mb[0] & 0x0c) << 4) | (mb[2] & 0x3f));
606
607 break;
608 }
609 }
610 }
611 */
612
613
sendEvent(QWSPcMouseSubHandler & h)614 bool QWSPcMouseHandlerPrivate::sendEvent(QWSPcMouseSubHandler& h)
615 {
616 if (h.reliable()) {
617 QPoint motion = h.takeMotion();
618 if (qAbs(motion.x()) > accel_limit || qAbs(motion.y()) > accel_limit)
619 motion *= accel;
620 QPoint newPos = handler->pos() + motion;
621 if (qt_screen->isTransformed()) {
622 QSize s = QSize(qt_screen->width(), qt_screen->height());
623 newPos = qt_screen->mapToDevice(newPos, s);
624 }
625 handler->limitToScreen(newPos);
626
627 handler->mouseChanged(newPos, h.buttonState(), h.takeWheel());
628 return true;
629 } else {
630 h.takeMotion();
631 if (h.buttonState() & (Qt::RightButton|Qt::MidButton)) {
632 // Strange for the user to press right or middle without
633 // a moving mouse!
634 h.worse();
635 }
636 return false;
637 }
638 }
639
openDevices()640 void QWSPcMouseHandlerPrivate::openDevices()
641 {
642 nsub=0;
643 int fd = -1;
644
645 QString drv = driver.toLower();
646 if (!drv.isEmpty() && drv != QLatin1String("auto")) {
647 // Manually specified mouse
648 QByteArray dev = device.toLatin1();
649 if (drv == QLatin1String("intellimouse")) {
650 if (dev.isEmpty())
651 dev = "/dev/psaux";
652 fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
653 if (fd >= 0)
654 sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
655 } else if (drv == QLatin1String("microsoft")) {
656 if (dev.isEmpty())
657 dev = "/dev/ttyS0";
658 fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
659 if (fd >= 0)
660 sub[nsub++] = new QWSPcMouseSubHandler_ms(fd);
661 } else if (drv == QLatin1String("mousesystems")) {
662 if (dev.isEmpty())
663 dev = "/dev/ttyS0";
664 fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
665 if (fd >= 0)
666 sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
667 } else if (drv == QLatin1String("mouseman")) {
668 if (dev.isEmpty())
669 dev = "/dev/psaux";
670 fd = QT_OPEN(dev, O_RDWR | O_NDELAY);
671 if (fd >= 0)
672 sub[nsub++] = new QWSPcMouseSubHandler_mouseman(fd);
673 }
674 if (fd >= 0)
675 notify(fd);
676 else
677 qCritical("Error opening mouse device '%s': %s",
678 dev.constData(), strerror(errno));
679 } else {
680 // Try automatically
681 fd = QT_OPEN("/dev/psaux", O_RDWR | O_NDELAY);
682 if (fd >= 0) {
683 sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
684 notify(fd);
685 }
686 fd = QT_OPEN("/dev/input/mice", O_RDWR | O_NDELAY);
687 if (fd >= 0) {
688 sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
689 notify(fd);
690 //qDebug("/dev/input/mice fd %d #%d", fd, nsub-1);
691 }
692
693 // include the code below to auto-detect serial mice, and to mess up
694 // any sort of serial communication
695 #if 0
696 const char fn[4][11] = { "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3" };
697 for (int ch = 0; ch < 4; ++ch) {
698 fd = QT_OPEN(fn[ch], O_RDWR | O_NDELAY);
699 if (fd >= 0) {
700 //sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
701 sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
702 sub[nsub++] = new QWSPcMouseSubHandler_ms(fd);
703 notify(fd);
704 }
705 }
706 #endif
707 }
708 }
709
closeDevices()710 void QWSPcMouseHandlerPrivate::closeDevices()
711 {
712 int pfd=-1;
713 for (int i=0; i<nsub; i++) {
714 sub[i]->closeIfNot(pfd);
715 delete sub[i];
716 }
717 qDeleteAll(notifiers);
718 notifiers.clear();
719 }
720
suspend()721 void QWSPcMouseHandlerPrivate::suspend()
722 {
723 for (int i=0; i<notifiers.size(); ++i)
724 notifiers.at(i)->setEnabled(false);
725 }
726
resume()727 void QWSPcMouseHandlerPrivate::resume()
728 {
729 for (int i=0; i<nsub; i++)
730 sub[i]->initState();
731
732 for (int i=0; i<notifiers.size(); ++i)
733 notifiers.at(i)->setEnabled(true);
734 }
735
736
737
notify(int fd)738 void QWSPcMouseHandlerPrivate::notify(int fd)
739 {
740 QSocketNotifier *mouseNotifier
741 = new QSocketNotifier(fd, QSocketNotifier::Read, this);
742 connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData(int)));
743 notifiers.append(mouseNotifier);
744 }
745
readMouseData(int fd)746 void QWSPcMouseHandlerPrivate::readMouseData(int fd)
747 {
748 for (;;) {
749 uchar buf[8];
750 int n = read(fd, buf, 8);
751 if (n<=0)
752 break;
753 for (int i=0; i<nsub; i++) {
754 QWSPcMouseSubHandler& h = *sub[i];
755 if (h.file() == fd) {
756 h.appendData(buf,n);
757 for (;;) {
758 switch (h.useData()) {
759 case QWSPcMouseSubHandler::Button:
760 sendEvent(h);
761 break;
762 case QWSPcMouseSubHandler::Insufficient:
763 goto breakbreak;
764 case QWSPcMouseSubHandler::Motion:
765 break;
766 }
767 }
768 breakbreak:
769 ;
770 }
771 }
772 }
773 bool any_reliable=false;
774 for (int i=0; i<nsub; i++) {
775 QWSPcMouseSubHandler& h = *sub[i];
776 if (h.motionPending())
777 sendEvent(h);
778 any_reliable = any_reliable || h.reliable();
779 }
780 if (any_reliable) {
781 // ... get rid of all unreliable ones? All bad ones?
782 } else if (retries < 2) {
783 // Try again - maybe the mouse was being moved when we tried to init.
784 closeDevices();
785 openDevices();
786 retries++;
787 }
788 }
789
790 QT_END_NAMESPACE
791
792 #include "qmousepc_qws.moc"
793
794 #endif // QT_NO_MOUSE_PC
795