Qt 4.8
qvfbintegration.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins 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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <sys/ipc.h>
45 #include <sys/shm.h>
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #include <fcntl.h>
49 #include <errno.h>
50 #include <private/qcore_unix_p.h> // overrides QT_OPEN
51 
52 #include <qvfbhdr.h>
53 #include <qsocketnotifier.h>
54 
55 #include "qvfbintegration.h"
56 #include "qvfbwindowsurface.h"
57 #include <QtGui/private/qpixmap_raster_p.h>
58 #include <QtCore/qdebug.h>
59 #include <QMouseEvent>
60 
61 #include <qsocketnotifier.h>
62 #include <QApplication>
63 #include <QWindowSystemInterface>
64 
66 
68 
69 
71 {
72  Q_OBJECT
73 public:
74  QVFbScreenKeyboardHandler(int displayId);
76 
77 private slots:
78  void readKeyboardData();
79 
80 private:
81  int kbdFD;
82  int kbdIdx;
84  unsigned char *kbdBuffer;
86 };
87 
89 {
90  const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId);
91 
92 
93  kbdFD = -1;
94  kbdIdx = 0;
95  kbdBufferLen = sizeof(QVFbKeyData) * 5;
96  kbdBuffer = new unsigned char [kbdBufferLen];
97 
98  kbdFD = QT_OPEN(keyboardDev.toLatin1().constData(), O_RDWR | O_NDELAY);
99 
100  if (kbdFD == -1) {
101  perror("QVFbScreenKeyboardHandler");
102  qWarning("QVFbScreenKeyboardHandler: Unable to open device %s",
103  qPrintable(keyboardDev));
104  return;
105  }
106 
107  // Clear pending input
108  char buf[2];
109  while (QT_READ(kbdFD, buf, 1) > 0) { }
110 
112  connect(keyNotifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
113 
114 }
115 
117 {
118  if (kbdFD >= 0)
119  QT_CLOSE(kbdFD);
120  delete [] kbdBuffer;
121 }
122 
123 
125 {
126  int n;
127  do {
129  if (n > 0)
130  kbdIdx += n;
131  } while (n > 0);
132 
133  int idx = 0;
134  while (kbdIdx - idx >= (int)sizeof(QVFbKeyData)) {
135  QVFbKeyData *kd = (QVFbKeyData *)(kbdBuffer + idx);
136  if (kd->unicode == 0 && kd->keycode == 0 && kd->modifiers == 0 && kd->press) {
137  // magic exit key
138  qWarning("Instructed to quit by Virtual Keyboard");
139  qApp->quit();
140  }
141 
142  //QWSServer::processKeyEvent(kd->unicode ? kd->unicode : 0xffff, kd->keycode, kd->modifiers, kd->press, kd->repeat);
143 
145 
146  QString text;
147  if (kd->unicode && kd->unicode != 0xffff)
148  text += QChar(kd->unicode);
149 
150 // qDebug() << "readKeyboardData" << type << hex << kd->keycode << kd->modifiers << text;
151 
152  QWindowSystemInterface::handleKeyEvent(0, type, kd->keycode, kd->modifiers, text, kd->repeat, int(text.length()));
153  idx += sizeof(QVFbKeyData);
154  }
155 
156  int surplus = kbdIdx - idx;
157  for (int i = 0; i < surplus; i++)
158  kbdBuffer[i] = kbdBuffer[idx+i];
159  kbdIdx = surplus;
160 }
161 
162 
163 
164 
166 {
167  Q_OBJECT
168 public:
169  QVFbScreenMouseHandler(int displayId);
171 
172 private slots:
173  void readMouseData();
174 
175 private:
176  int mouseFD;
177  int mouseIdx;
178  enum {mouseBufSize = 128};
179  uchar mouseBuf[mouseBufSize];
181 
183 };
184 
186 {
187  QString mouseDev = QT_VFB_MOUSE_PIPE(displayId);
188 
189  mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY);
190 
191  if (mouseFD == -1) {
192  perror("QVFbMouseHandler::QVFbMouseHandler");
193  qWarning("QVFbMouseHander: Unable to open device %s",
194  qPrintable(mouseDev));
195  return;
196  }
197 
198  // Clear pending input
199  char buf[2];
200  while (QT_READ(mouseFD, buf, 1) > 0) { }
201 
202  mouseIdx = 0;
203  oldButtonState = 0;
204  mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
205  connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
206 }
207 
208 
210 {
211  if (mouseFD >= 0)
212  QT_CLOSE(mouseFD);
213 }
214 
216 {
217  int n;
218  do {
219  n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
220  if (n > 0)
221  mouseIdx += n;
222  } while (n > 0);
223 
224  int idx = 0;
225  static const int packetsize = sizeof(QPoint) + 2*sizeof(int);
226  while (mouseIdx-idx >= packetsize) {
227  uchar *mb = mouseBuf+idx;
228  QPoint mousePos = *reinterpret_cast<QPoint *>(mb);
229  mb += sizeof(QPoint);
230  int bstate = *reinterpret_cast<int *>(mb);
231  mb += sizeof(int);
232  //int wheel = *reinterpret_cast<int *>(mb);
233 
234  int button = bstate ^ oldButtonState;
236 
237  if (button) {
238  type = (button & bstate) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease;
239  }
240  QWindowSystemInterface::handleMouseEvent(0, mousePos, mousePos, Qt::MouseButtons(bstate));
241 
242 // qDebug() << "readMouseData" << mousePos << button << bstate << oldButtonState << type;
243 
244  oldButtonState = bstate;
245 
246  idx += packetsize;
247  }
248 
249  int surplus = mouseIdx - idx;
250  for (int i = 0; i < surplus; i++)
251  mouseBuf[i] = mouseBuf[idx+i];
252  mouseIdx = surplus;
253 
254 }
255 
256 
257 class QVFbScreenPrivate
258 {
259 public:
261  : shmrgn(0), hdr(0), data(0), mouseHandler(0), keyboardHandler(0)
262  {
263  displayId = id;
264  connect(displayId);
265  }
266 
268  void setDirty(const QRect &r);
269 
270  bool connect(int displayId);
271  void disconnect();
272 
273  QImage *screenImage() { return &img; }
274  QSize screenSize() { return img.size(); }
275 
276  int depth() const { return img.depth(); }
277  QImage::Format format() const { return img.format(); }
278 
279 private:
280  unsigned char *shmrgn;
281  QVFbHeader *hdr;
286 
288 };
289 
290 
292 {
293  hdr->dirty = true;
294  hdr->update = hdr->update.united(r);
295 }
296 
297 
298 bool QVFbScreenPrivate::connect(int displayId)
299 {
300  qDebug() << "QVFbScreenPrivate::connect" << displayId;
301  key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLatin1(), 'b');
302 
303  if (key == -1)
304  return false;
305 
306 
307  int shmId = shmget(key, 0, 0);
308  if (shmId != -1)
309  shmrgn = (unsigned char *)shmat(shmId, 0, 0);
310  else
311  return false;
312 
313  if ((long)shmrgn == -1 || shmrgn == 0) {
314  qDebug("No shmrgn %ld", (long)shmrgn);
315  return false;
316  }
317 
318  hdr = (QVFbHeader *)shmrgn;
319  data = shmrgn + hdr->dataoffset;
320 
321  int w = hdr->width;
322  int h = hdr->height;
323  int d = hdr->depth;
324  int lstep = hdr->linestep;
325 
327  if (d == 32)
329  else if (d == 16)
330  format = QImage::Format_RGB16;
331 
332 
333  if (format == QImage::Format_Invalid) {
334  img = QImage();
335  return false;
336  }
337 
338  img = QImage(data, w, h, lstep, format);
339 
340  qDebug("connected %dx%d %d bpp", w, h, d);
341 
342 
343  mouseHandler = new QVFbScreenMouseHandler(displayId);
344  keyboardHandler = new QVFbScreenKeyboardHandler(displayId);
345  return true;
346 }
347 
349 {
350  if ((long)shmrgn != -1 && shmrgn) {
351  shmdt((char*)shmrgn);
352  shmrgn = 0;
353  }
354  delete mouseHandler;
355  mouseHandler = 0;
356  delete keyboardHandler;
357  keyboardHandler = 0;
358 }
359 
360 
362 {
363  d_ptr = new QVFbScreenPrivate(id);
364 }
365 
366 
368 {
369  delete d_ptr;
370 }
371 
372 void QVFbScreen::setDirty(const QRect &rect)
373 {
374  d_ptr->setDirty(rect);
375 }
376 
377 
378 
380  return QRect(QPoint(), d_ptr->screenSize());
381 }
382 
383 
384 int QVFbScreen::depth() const
385 {
386  return d_ptr->depth();
387 }
388 
390 {
391  return d_ptr->format();
392 }
393 
395  return (d_ptr->screenSize()*254)/720;
396 }
397 
398 #if 0
399 int QVFbScreen::linestep() const {
400  return d_ptr->screenImage() ? d_ptr->screenImage()->bytesPerLine() : 0;
401 }
402 
403 uchar *QVFbScreen::base() const {
404  return d_ptr->screenImage() ? d_ptr->screenImage()->bits() : 0;
405 }
406 #endif
407 
409 {
410  return d_ptr->screenImage();
411 }
412 
414  : mFontDb(new QGenericUnixFontDatabase())
415 {
416  int displayId = 0;
417  if (paramList.length() > 0)
418  displayId = paramList.at(0).toInt();
419 
420  mPrimaryScreen = new QVFbScreen(displayId);
421 
423 }
424 
426 {
427  return new QRasterPixmapData(type);
428 }
429 
431 {
432  return new QVFbWindowSurface(mPrimaryScreen, widget);
433 }
434 
435 
437 {
438  return new QVFbWindow(mPrimaryScreen, widget);
439 }
440 
442 {
443  return mFontDb;
444 }
445 
447 
448 #include "qvfbintegration.moc"
QPixmapData * createPixmapData(QPixmapData::PixelType type) const
Factory function for QPixmapData.
double d
Definition: qnumeric_p.h:62
QPlatformFontDatabase * fontDatabase() const
Accessor for the platform integrations fontdatabase.
bool repeat
Definition: qvfbhdr.h:112
QImage::Format format() const
Reimplement in subclass to return the image format which corresponds to the screen format...
QVFbScreenKeyboardHandler * keyboardHandler
Format
The following image formats are available in Qt.
Definition: qimage.h:91
QImage * screenImage()
unsigned long WId
Definition: qwindowdefs.h:119
int type
Definition: qmetatype.cpp:239
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QPointer< QWidget > widget
QVFbScreenKeyboardHandler(int displayId)
QRect geometry() const
Reimplement in subclass to return the pixel geometry of the screen.
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
#define SLOT(a)
Definition: qobjectdefs.h:226
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
The QVFbScreen class implements a screen driver for the virtual framebuffer.
static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString &text=QString(), bool autorep=false, ushort count=1)
The QString class provides a Unicode character string.
Definition: qstring.h:83
QVFbIntegration(const QStringList &paramList)
The QPlatformWindow class provides an abstraction for top-level windows.
QVFbScreen * mPrimaryScreen
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
#define QT_READ
Definition: qcore_unix_p.h:280
QPlatformFontDatabase * mFontDb
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
QSocketNotifier * keyNotifier
bool press
Definition: qvfbhdr.h:111
Q_CORE_EXPORT void qDebug(const char *,...)
#define SIGNAL(a)
Definition: qobjectdefs.h:227
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int linestep() const
Returns the length of each scanline of the framebuffer in bytes.
Definition: qscreen_qws.h:232
QSize physicalSize() const
Reimplement this function in subclass to return the physical size of the screen.
#define QT_VFB_KEYBOARD_PIPE(DISPLAY)
Definition: qvfbhdr.h:78
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
#define qApp
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static void handleMouseEvent(QWidget *w, const QPoint &local, const QPoint &global, Qt::MouseButtons b)
tlw == 0 means that ev is in global coords only
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
QVFbScreen(int display_id)
Constructs a QVNCScreen object.
unsigned int keycode
Definition: qvfbhdr.h:108
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
QVFbScreenMouseHandler(int displayId)
bool connect(int displayId)
#define Q_OBJECT
Definition: qobjectdefs.h:157
The QWindowSurface class provides the drawing area for top-level windows.
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QPlatformWindow * createPlatformWindow(QWidget *widget, WId winId) const
Factory function for QPlatformWindow.
QWindowSurface * createWindowSurface(QWidget *widget, WId winId) const
Factory function for QWindowSurface.
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
virtual ~QVFbScreen()
Destroys this QVFbScreen object.
#define QT_VFB_MOUSE_PIPE(DISPLAY)
Definition: qvfbhdr.h:76
uchar * base() const
Returns a pointer to the beginning of the framebuffer.
Definition: qscreen_qws.h:235
QList< QPlatformScreen * > mScreens
#define QT_OPEN
Definition: qcore_unix_p.h:186
QSocketNotifier * mouseNotifier
Type
This enum type defines the valid event types in Qt.
Definition: qcoreevent.h:62
int length() const
This function is identical to count().
Definition: qlist.h:281
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
unsigned short int unicode
Definition: qvfbhdr.h:110
The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they ...
QScopedPointer< QObjectData > d_ptr
Definition: qobject.h:320
int depth() const
Reimplement in subclass to return current depth of the screen.
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
QImage::Format format() const
void setDirty(const QRect &r)
#define slots
Definition: qobjectdefs.h:68
#define qPrintable(string)
Definition: qglobal.h:1750
virtual void setDirty(const QRect &r)
Reimplemented Function
#define O_RDWR
Qt::KeyboardModifiers modifiers
Definition: qvfbhdr.h:109
QVFbScreenMouseHandler * mouseHandler
#define text
Definition: qobjectdefs.h:80
#define QT_CLOSE
Definition: qcore_unix_p.h:304