📄 qwsmouse_qws.cpp
字号:
/****************************************************************************
** $Id: qt/qwsmouse_qws.cpp 3.0.4 edited Apr 2 09:25 $
**
** Implementation of Qt/Embedded mouse drivers
**
** Created : 991025
**
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
**
** This file is part of the kernel module of the Qt GUI Toolkit.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
** licenses for Qt/Embedded may use this file in accordance with the
** Qt Embedded Commercial License Agreement provided with the Software.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
** information about Qt Commercial License Agreements.
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "qwindowsystem_qws.h"
#include "qsocketnotifier.h"
#include "qwsevent_qws.h"
#include "qwscommand_qws.h"
#include "qwsutils_qws.h"
#include "qwsmouse_qws.h"
#include "qapplication.h"
#include "qpointarray.h"
#include "qtimer.h"
#include "qfile.h"
#include "qtextstream.h"
#include "tslib.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <qgfx_qws.h>
#define QT_QWS_LUBBOCK
#ifdef QT_QWS_LUBBOCK
#include <linux/input.h>
#include <dlfcn.h>
#include "tslib.h"
#endif
#ifdef QT_QWS_CASSIOPEIA
#include <linux/tpanel.h>
#endif
#if defined(QT_QWS_IPAQ)
#define QT_QWS_IPAQ_RAW
typedef struct {
unsigned short pressure;
unsigned short x;
unsigned short y;
unsigned short pad;
} TS_EVENT;
#elif defined(QT_QWS_EBX)
#define QT_QWS_EBX_RAW
#ifndef QT_QWS_CUSTOM
typedef struct {
unsigned short pressure;
unsigned short x;
unsigned short y;
unsigned short pad;
} TS_EVENT;
#else
typedef struct {
long y;
long x;
long pressure;
long long millisecs;
} TS_EVENT;
#endif
#define QT_QWS_TP_SAMPLE_SIZE 5
#define QT_QWS_TP_PRESSURE_THRESHOLD 500
#define QT_QWS_TP_MOVE_LIMIT 50
#endif
#ifndef QT_QWS_TP_SAMPLE_SIZE
#define QT_QWS_TP_SAMPLE_SIZE 5
#endif
#ifndef QT_QWS_TP_PRESSURE_THRESHOLD
#define QT_QWS_TP_PRESSURE_THRESHOLD 1
#endif
#ifndef QT_QWS_TP_MOVE_LIMIT
#define QT_QWS_TP_MOVE_LIMIT 100
#endif
#ifndef QT_QWS_TP_SAMPLE_SIZE
#define QT_QWS_TP_SAMPLE_SIZE 5
#endif
#ifndef QT_QWS_TP_PRESSURE_THRESHOLD
#define QT_QWS_TP_PRESSURE_THRESHOLD 1
#endif
#ifndef QT_QWS_TP_MOVE_LIMIT
#define QT_QWS_TP_MOVE_LIMIT 100
#endif
/*!
\class QWSMouseHandler qwsmouse_qws.h
\ingroup qws
\brief The QWSMouseHandler class is a mouse driver/handler for Qt/Embedded.
The mouse driver/handler handles events from system devices and
generates mouse events.
A QWSMouseHandler will usually open some system device in its
constructor, create a QSocketNotifier on that opened device and when
it receives data, it will call mouseChanged() to send the event
to Qt/Embedded for relaying to clients.
*/
/*!
Constructs a mouse handler. This becomes the primary mouse handler.
Note that once created, mouse handlers are controlled by the system
and should not be deleted.
*/
QWSMouseHandler::QWSMouseHandler()
{
QWSServer::setMouseHandler(this);
}
/*!
Destroys the mouse handler. You should not call this directly.
*/
QWSMouseHandler::~QWSMouseHandler()
{
}
/*!
To be called by the mouse handler to signal that the
mouse is at position \a pos and the mouse buttons are
in state \a bstate.
*/
static void limitToScreen( QPoint &pt )
{
static int w = -1;
static int h;
if ( w < 0 ) {
w = qt_screen->deviceWidth();
h = qt_screen->deviceHeight();
}
pt.setX( QMIN( w-1, QMAX( 0, pt.x() )));
pt.setY( QMIN( h-1, QMAX( 0, pt.y() )));
}
static QPoint &mousePos = QWSServer::mousePosition;
#ifdef Q_OS_QNX6
#include "qwsmouse_qnx6.cpp"
#endif
/*!
When a mouse event occurs this function is called with the mouse's
position in \a pos, and the state of its buttons in \a bstate.
*/
void QWSMouseHandler::mouseChanged( const QPoint& pos, int bstate )
{
QWSServer::sendMouseEvent(pos,bstate);
}
typedef struct {
char *name;
MouseProtocol id;
} MouseConfig;
static const MouseConfig mouseConfig[] = {
{ "Auto", Auto },
{ "MouseMan", MouseMan },
{ "IntelliMouse", IntelliMouse },
{ "Microsoft", Microsoft },
{ "QVFbMouse", QVFBMouse },
{ "TPanel", TPanel },
{ "BusMouse", BusMouse },
{ 0, Unknown }
};
#ifndef QT_NO_QWS_MOUSE_AUTO
/*
* Automatic-detection mouse driver
*/
class QAutoMouseSubHandler {
protected:
enum { max_buf=32 };
int fd;
uchar buffer[max_buf];
int nbuf;
QPoint motion;
int bstate;
int goodness;
int badness;
virtual int tryData()=0;
public:
QAutoMouseSubHandler(int f) : fd(f)
{
nbuf = bstate = goodness = badness = 0;
}
int file() const { return fd; }
void closeIfNot(int& f)
{
if ( fd != f ) {
f = fd;
close(fd);
}
}
void worse(int by=1) { badness+=by; }
bool reliable() const { return goodness >= 5 && badness < 50; }
int buttonState() const { return bstate; }
bool motionPending() const { return motion!=QPoint(0,0); }
QPoint takeMotion() { QPoint r=motion; motion=QPoint(0,0); return r; }
void appendData(uchar* data, int length)
{
memcpy(buffer+nbuf, data, length);
nbuf += length;
}
enum UsageResult { Insufficient, Motion, Button };
UsageResult useData()
{
int pbstate = bstate;
int n = tryData();
if ( n > 0 ) {
if ( n<nbuf )
memcpy( buffer, buffer+n, nbuf-n );
nbuf -= n;
return pbstate == bstate ? Motion : Button;
}
return Insufficient;
}
};
class QAutoMouseSubHandler_intellimouse : public QAutoMouseSubHandler {
int packetsize;
public:
QAutoMouseSubHandler_intellimouse(int f) : QAutoMouseSubHandler(f)
{
init();
}
void init()
{
int n;
uchar reply[20];
tcflush(fd,TCIOFLUSH);
static const uchar initseq[] = { 243, 200, 243, 100, 243, 80 };
static const uchar query[] = { 0xf2 };
if (write(fd, initseq, sizeof(initseq))!=sizeof(initseq)) {
badness = 100;
return;
}
usleep(10000);
tcflush(fd,TCIOFLUSH);
if (write(fd, query, sizeof(query))!=sizeof(query)) {
badness = 100;
return;
}
usleep(10000);
n = read(fd, reply, 20);
if ( n > 0 ) {
goodness = 10;
switch ( reply[n-1] ) {
case 3:
case 4:
packetsize = 4;
break;
default:
packetsize = 3;
}
} else {
badness = 100;
}
}
int tryData()
{
if ( nbuf >= packetsize ) {
//int overflow = (buffer[0]>>6 )& 0x03;
if ( /*overflow ||*/ !(buffer[0] & 8) ) {
badness++;
return 1;
} else {
motion +=
QPoint((buffer[0] & 0x10) ? buffer[1]-256 : buffer[1],
(buffer[0] & 0x20) ? 256-buffer[2] : -buffer[2]);
int nbstate = buffer[0] & 0x7;
if ( motion.x() || motion.y() || bstate != nbstate ) {
bstate = nbstate;
goodness++;
} else {
badness++;
return 1;
}
}
return packetsize;
}
return 0;
}
};
class QAutoMouseSubHandler_serial : public QAutoMouseSubHandler {
public:
QAutoMouseSubHandler_serial(int f) : QAutoMouseSubHandler(f)
{
initSerial();
}
protected:
void setflags(int f)
{
termios tty;
tcgetattr(fd, &tty);
tty.c_iflag = IGNBRK | IGNPAR;
tty.c_oflag = 0;
tty.c_lflag = 0;
tty.c_cflag = f | CREAD | CLOCAL | HUPCL;
#if !defined(Q_OS_FREEBSD) && !defined(Q_OS_SOLARIS)
tty.c_line = 0;
#endif
tty.c_cc[VTIME] = 0;
tty.c_cc[VMIN] = 1;
tcsetattr(fd, TCSANOW, &tty);
}
private:
void initSerial()
{
int speed[4] = { B9600, B4800, B2400, B1200 };
for (int n = 0; n < 4; n++) {
setflags(CSTOPB | speed[n]);
write(fd, "*q", 2);
usleep(10000);
}
}
};
class QAutoMouseSubHandler_mousesystems : public QAutoMouseSubHandler_serial {
public:
// ##### This driver has not been tested
QAutoMouseSubHandler_mousesystems(int f) : QAutoMouseSubHandler_serial(f)
{
init();
}
void init()
{
setflags(B1200|CS8|CSTOPB);
// 60Hz
if (write(fd, "R", 1)!=1) {
badness = 100;
return;
}
tcflush(fd,TCIOFLUSH);
}
int tryData()
{
if ( nbuf >= 5 ) {
if ( (buffer[0] & 0xf8) != 0x80 ) {
badness++;
return 1;
}
motion +=
QPoint((signed char)buffer[1] + (signed char)buffer[3],
-(signed char)buffer[2] + (signed char)buffer[4]);
int t = ~buffer[0];
int nbstate = ((t&3) << 1) | ((t&4) >> 2);
if ( motion.x() || motion.y() || bstate != nbstate ) {
bstate = nbstate;
goodness++;
} else {
badness++;
return 1;
}
return 5;
}
return 0;
}
};
class QAutoMouseSubHandler_ms : public QAutoMouseSubHandler_serial {
int mman;
public:
QAutoMouseSubHandler_ms(int f) : QAutoMouseSubHandler_serial(f)
{
mman=0;
init();
}
void init()
{
setflags(B1200|CS7);
// 60Hz
if (write(fd, "R", 1)!=1) {
badness = 100;
return;
}
tcflush(fd,TCIOFLUSH);
}
int tryData()
{
if ( !(buffer[0] & 0x40) ) {
if ( buffer[0] == 0x20 && (bstate & Qt::MidButton) ) {
mman=1; // mouseman extension
}
return 1;
}
int extra = mman&&(bstate & Qt::MidButton);
if ( nbuf >= 3+extra ) {
int nbstate = 0;
if ( buffer[0] == 0x40 && !bstate && !buffer[1] && !buffer[2] ) {
nbstate = Qt::MidButton;
} else {
nbstate = ((buffer[0] & 0x20) >> 5)
| ((buffer[0] & 0x10) >> 3);
if ( extra && buffer[3] == 0x20 )
nbstate = Qt::MidButton;
}
if ( buffer[1] & 0x40 ) {
badness++;
return 1;
} else {
motion +=
QPoint((signed char)((buffer[0]&0x3)<<6)
|(signed char)(buffer[1]&0x3f),
(signed char)((buffer[0]&0xc)<<4)
|(signed char)(buffer[2]&0x3f));
if ( motion.x() || motion.y() || bstate != nbstate ) {
bstate = nbstate;
goodness++;
} else {
badness++;
return 1;
}
return 3+extra;
}
}
return 0;
}
};
/*
QAutoMouseHandler::UsageResult QAutoMouseHandler::useDev(Dev& d)
{
if ( d.nbuf >= mouseData[d.protocol].bytesPerPacket ) {
uchar *mb = d.buf;
int bstate = 0;
int dx = 0;
int dy = 0;
switch (mouseProtocol) {
case MouseMan:
case IntelliMouse:
{
bstate = mb[0] & 0x7; // assuming Qt::*Button order
int overflow = (mb[0]>>6 )& 0x03;
if (mouseProtocol == MouseMan && overflow) {
//### wheel events signalled with overflow bit, ignore for now
}
else {
bool xs = mb[0] & 0x10;
bool ys = mb[0] & 0x20;
dx = xs ? mb[1]-256 : mb[1];
dy = ys ? mb[2]-256 : mb[2];
}
break;
}
case Microsoft:
if ( ((mb[0] & 0x20) >> 3) ) {
bstate |= Qt::LeftButton;
}
if ( ((mb[0] & 0x10) >> 4) ) {
bstate |= Qt::RightButton;
}
dx=(signed char)(((mb[0] & 0x03) << 6) | (mb[1] & 0x3f));
dy=-(signed char)(((mb[0] & 0x0c) << 4) | (mb[2] & 0x3f));
break;
}
}
}
*/
bool QAutoMouseHandlerPrivate::sendEvent(QAutoMouseSubHandler& h)
{
if ( h.reliable() ) {
mousePos += h.takeMotion();
limitToScreen( mousePos );
/*
qDebug("%d,%d %c%c%c",
mousePos.x(),mousePos.y(),
(h.buttonState()&Qt::LeftButton)?'L':'.',
(h.buttonState()&Qt::MidButton)?'M':'.',
(h.buttonState()&Qt::RightButton)?'R':'.');
*/
mouseChanged(mousePos,h.buttonState());
return TRUE;
} else {
h.takeMotion();
if ( h.buttonState() & (Qt::RightButton|Qt::MidButton) ) {
// Strange for the user to press right or middle without
// a moving mouse!
h.worse();
}
return FALSE;
}
}
QAutoMouseHandlerPrivate::QAutoMouseHandlerPrivate()
{
notifiers.setAutoDelete( TRUE );
retries = 0;
openDevices();
}
QAutoMouseHandlerPrivate::~QAutoMouseHandlerPrivate()
{
closeDevices();
}
void QAutoMouseHandlerPrivate::openDevices()
{
nsub=0;
int fd;
fd = open( "/dev/psaux", O_RDWR | O_NDELAY );
if ( fd >= 0 ) {
sub[nsub++] = new QAutoMouseSubHandler_intellimouse(fd);
notify(fd);
}
#if 0
char fn[] = "/dev/ttyS?";
for (int ch='0'; ch<='3'; ch++) {
fn[9] = ch;
fd = open( fn, O_RDWR | O_NDELAY );
if ( fd >= 0 ) {
//sub[nsub++] = new QAutoMouseSubHandler_intellimouse(fd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -