Qt LinuxFB旋转界面和触摸

  • 一.修改源代码
  • 二.修改后的源代码
    • 头文件qlinuxfbscreen.h
    • c文件qlinuxfbscreen.cpp
  • 三对应的补丁文件
    • 头文件补丁code_h.patch
    • C文件补丁code_c.patch
  • 四.Qt运行脚本配置

一.修改源代码

需要修改qtbase/src/plugins/platforms/linuxfb目录下得qlinuxfbscreen.h和qlinuxfbscreen.cpp文件

二.修改后的源代码

头文件qlinuxfbscreen.h

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#ifndef QLINUXFBSCREEN_H
#define QLINUXFBSCREEN_H//#include <QtFbSupport/private/qfbscreen_p.h>
//#include <QtPlatformSupport/private/qfbscreen_p.h>
#include <QtFbSupport/private/qfbscreen_p.h>QT_BEGIN_NAMESPACEclass QPainter;
class QFbCursor;class QLinuxFbScreen : public QFbScreen
{Q_OBJECT
public:QLinuxFbScreen(const QStringList &args);~QLinuxFbScreen();bool initialize();QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;QRegion doRedraw() Q_DECL_OVERRIDE;private:QStringList mArgs;int mFbFd;int mTtyFd;// add by immortal startint mRotation;// add by immortal endQImage mFbScreenImage;int mBytesPerLine;int mOldTtyMode;struct {uchar *data;int offset, size;} mMmap;QPainter *mBlitter;
};QT_END_NAMESPACE#endif // QLINUXFBSCREEN_H

c文件qlinuxfbscreen.cpp

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#include "qlinuxfbscreen.h"
/*
#include <QtFbSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
*/
//#include <QtPlatformSupport/private/qfbcursor_p.h>
#include <QtFbSupport/private/qfbcursor_p.h>
//#include <QtPlatformSupport/private/qfbwindow_p.h>
#include <QtFbSupport/private/qfbwindow_p.h>
#include <QtCore/QFile>
#include <QtCore/QRegularExpression>
#include <QtGui/QPainter>#include <private/qcore_unix_p.h> // overrides QT_OPEN
#include <qimage.h>
#include <qdebug.h>#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <linux/kd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <limits.h>
#include <signal.h>#include <linux/fb.h>QT_BEGIN_NAMESPACEstatic int openFramebufferDevice(const QString &dev)
{int fd = -1;if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);if (fd == -1) {if (access(dev.toLatin1().constData(), R_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);}return fd;
}static int determineDepth(const fb_var_screeninfo &vinfo)
{int depth = vinfo.bits_per_pixel;if (depth== 24) {depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;if (depth <= 0)depth = 24; // reset if color component lengths are not reported} else if (depth == 16) {depth = vinfo.red.length + vinfo.green.length + vinfo.blue.length;if (depth <= 0)depth = 16;}return depth;
}static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry)
{int xoff = vinfo.xoffset;int yoff = vinfo.yoffset;int w, h;if (userGeometry.isValid()) {w = userGeometry.width();h = userGeometry.height();if ((uint)w > vinfo.xres)w = vinfo.xres;if ((uint)h > vinfo.yres)h = vinfo.yres;int xxoff = userGeometry.x(), yyoff = userGeometry.y();if (xxoff != 0 || yyoff != 0) {if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))xxoff = vinfo.xres - w;if (yyoff < 0 || yyoff + h > (int)(vinfo.yres))yyoff = vinfo.yres - h;xoff += xxoff;yoff += yyoff;} else {xoff += (vinfo.xres - w)/2;yoff += (vinfo.yres - h)/2;}} else {w = vinfo.xres;h = vinfo.yres;}if (w == 0 || h == 0) {qWarning("Unable to find screen geometry, using 320x240");w = 320;h = 240;}return QRect(xoff, yoff, w, h);
}static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res)
{int mmWidth = mmSize.width(), mmHeight = mmSize.height();if (mmWidth <= 0 && mmHeight <= 0) {if (vinfo.width != 0 && vinfo.height != 0&& vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {mmWidth = vinfo.width;mmHeight = vinfo.height;} else {const int dpi = 100;mmWidth = qRound(res.width() * 25.4 / dpi);mmHeight = qRound(res.height() * 25.4 / dpi);}} else if (mmWidth > 0 && mmHeight <= 0) {mmHeight = res.height() * mmWidth/res.width();} else if (mmHeight > 0 && mmWidth <= 0) {mmWidth = res.width() * mmHeight/res.height();}return QSize(mmWidth, mmHeight);
}static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth)
{const fb_bitfield rgba[4] = { info.red, info.green,info.blue, info.transp };QImage::Format format = QImage::Format_Invalid;switch (depth) {case 32: {const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},{0, 8, 0}, {24, 8, 0}};const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0},{16, 8, 0}, {24, 8, 0}};if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_ARGB32;} else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB32;} else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB32;// pixeltype = BGRPixel;}break;}case 24: {const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0},{0, 8, 0}, {0, 0, 0}};const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0},{16, 8, 0}, {0, 0, 0}};if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB888;} else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB888;// pixeltype = BGRPixel;}break;}case 18: {const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0},{0, 6, 0}, {0, 0, 0}};if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0)format = QImage::Format_RGB666;break;}case 16: {const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0},{0, 5, 0}, {0, 0, 0}};const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0},{11, 5, 0}, {0, 0, 0}};if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB16;} else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB16;// pixeltype = BGRPixel;}break;}case 15: {const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0},{0, 5, 0}, {15, 1, 0}};const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0},{10, 5, 0}, {15, 1, 0}};if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB555;} else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) {format = QImage::Format_RGB555;// pixeltype = BGRPixel;}break;}case 12: {const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0},{0, 4, 0}, {0, 0, 0}};if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0)format = QImage::Format_RGB444;break;}case 8:break;case 1:format = QImage::Format_Mono; //###: LSB???break;default:break;}qDebug() << "*******************************************" << format << "************************************************";return format;
}static int openTtyDevice(const QString &device)
{const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };int fd = -1;if (device.isEmpty()) {for (const char * const *dev = devs; *dev; ++dev) {fd = QT_OPEN(*dev, O_RDWR);if (fd != -1)break;}} else {fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);}return fd;
}static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode)
{// Do not warn if the switch fails: the ioctl fails when launching from a// remote console and there is nothing we can do about it.  The matching// call in resetTty should at least fail then, too, so we do no harm.if (ioctl(ttyfd, KDGETMODE, oldMode) == 0) {if (doSwitch && *oldMode != KD_GRAPHICS)ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);}
}static void resetTty(int ttyfd, int oldMode)
{ioctl(ttyfd, KDSETMODE, oldMode);QT_CLOSE(ttyfd);
}static void blankScreen(int fd, bool on)
{ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);
}QLinuxFbScreen::QLinuxFbScreen(const QStringList &args): mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
{mMmap.data = 0;
}QLinuxFbScreen::~QLinuxFbScreen()
{if (mFbFd != -1) {if (mMmap.data)munmap(mMmap.data - mMmap.offset, mMmap.size);close(mFbFd);}if (mTtyFd != -1)resetTty(mTtyFd, mOldTtyMode);delete mBlitter;
}bool QLinuxFbScreen::initialize()
{QRegularExpression ttyRx(QLatin1String("tty=(.*)"));QRegularExpression fbRx(QLatin1String("fb=(.*)"));QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));// add by immorta startQRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));// add by immorta endQString fbDevice, ttyDevice;QSize userMmSize;QRect userGeometry;bool doSwitchToGraphicsMode = true;// Parse arguments//for (const QString &arg : qAsConst(mArgs)) {//   foreach (const QString &arg, mArgs) {for (const QString &arg : qAsConst(mArgs)) {QRegularExpressionMatch match;if (arg == QLatin1String("nographicsmodeswitch"))doSwitchToGraphicsMode = false;else if (arg.contains(mmSizeRx, &match))userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());else if (arg.contains(sizeRx, &match))userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));else if (arg.contains(offsetRx, &match))userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));else if (arg.contains(ttyRx, &match))ttyDevice = match.captured(1);else if (arg.contains(fbRx, &match))fbDevice = match.captured(1);// add by immortal startelse if (arg.contains(rotationRx, &match))mRotation = match.captured(1).toInt();// add by immortal end}if (fbDevice.isEmpty()) {fbDevice = QLatin1String("/dev/fb0");if (!QFile::exists(fbDevice))fbDevice = QLatin1String("/dev/graphics/fb0");if (!QFile::exists(fbDevice)) {qWarning("Unable to figure out framebuffer device. Specify it manually.");return false;}}// Open the devicemFbFd = openFramebufferDevice(fbDevice);if (mFbFd == -1) {qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));return false;}// Read the fixed and variable screen informationfb_fix_screeninfo finfo;fb_var_screeninfo vinfo;memset(&vinfo, 0, sizeof(vinfo));memset(&finfo, 0, sizeof(finfo));if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {qErrnoWarning(errno, "Error reading fixed information");return false;}if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {qErrnoWarning(errno, "Error reading variable information");return false;}mDepth = determineDepth(vinfo);mBytesPerLine = finfo.line_length;QRect geometry = determineGeometry(vinfo, userGeometry);// add by immortal startQRect originalGeometry = geometry;if( 90 == mRotation  || 270 == mRotation ){int tmp = geometry.width();geometry.setWidth(geometry.height());geometry.setHeight(tmp);}// add by immortal endmGeometry = QRect(QPoint(0, 0), geometry.size());mFormat = determineFormat(vinfo, mDepth);//mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());// mmap the framebuffermMmap.size = finfo.smem_len;uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);if ((long)data == -1) {qErrnoWarning(errno, "Failed to mmap framebuffer");return false;}//mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;mMmap.data = data + mMmap.offset;QFbScreen::initializeCompositor();//mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);mCursor = new QFbCursor(this);mTtyFd = openTtyDevice(ttyDevice);if (mTtyFd == -1)qErrnoWarning(errno, "Failed to open tty");switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);blankScreen(mFbFd, false);return true;
}QRegion QLinuxFbScreen::doRedraw()
{QRegion touched = QFbScreen::doRedraw();if (touched.isEmpty())return touched;if (!mBlitter)mBlitter = new QPainter(&mFbScreenImage);const QVector<QRect> rects = touched.rects();mBlitter->setCompositionMode(QPainter::CompositionMode_Source);for (int i = 0; i < rects.size(); ++i){if( 90 == mRotation || 270 == mRotation ){mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);}else if( 180 == mRotation ){mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);}if( mRotation != 0 ){mBlitter->rotate(mRotation);mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);}mBlitter->drawImage(rects[i], mScreenImage, rects[i]);mBlitter->resetTransform();}return touched;
}// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{if (!wid) {if (width < 0)width = mFbScreenImage.width() - x;if (height < 0)height = mFbScreenImage.height() - y;return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);}QFbWindow *window = windowForId(wid);if (window) {const QRect geom = window->geometry();if (width < 0)width = geom.width() - x;if (height < 0)height = geom.height() - y;QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));rect &= window->geometry();return QPixmap::fromImage(mFbScreenImage).copy(rect);}return QPixmap();
}QT_END_NAMESPACE

三对应的补丁文件

头文件补丁code_h.patch

--- /home/mywork/qtSrc/qt-everywhere-src-5.12.9/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.h    2020-06-03 03:51:20.000000000 -0700
+++ ./qlinuxfbscreen.h   2020-09-24 04:14:14.923500800 -0700
@@ -36,48 +36,52 @@** $QT_END_LICENSE$******************************************************************************/
-
+ #ifndef QLINUXFBSCREEN_H#define QLINUXFBSCREEN_H
-
+
+//#include <QtFbSupport/private/qfbscreen_p.h>
+//#include <QtPlatformSupport/private/qfbscreen_p.h>#include <QtFbSupport/private/qfbscreen_p.h>QT_BEGIN_NAMESPACE
-
+ class QPainter;class QFbCursor;
-
+ class QLinuxFbScreen : public QFbScreen{Q_OBJECTpublic:QLinuxFbScreen(const QStringList &args);~QLinuxFbScreen();
-
-    bool initialize() override;
-
-    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const override;
-
-    QRegion doRedraw() override;
-
+
+    bool initialize();
+
+    QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
+
+    QRegion doRedraw() Q_DECL_OVERRIDE;
+ private:QStringList mArgs;int mFbFd;int mTtyFd;
-
+  // add by immortal start
+  int mRotation;
+  // add by immortal endQImage mFbScreenImage;int mBytesPerLine;int mOldTtyMode;
-
+ struct {uchar *data;int offset, size;} mMmap;
-
+ QPainter *mBlitter;};
-
+ QT_END_NAMESPACE
-
+ #endif // QLINUXFBSCREEN_H
-
+ 

C文件补丁code_c.patch

--- /home/mywork/qtSrc/qt-everywhere-src-5.12.9/qtbase/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp  2020-06-03 03:51:20.000000000 -0700
+++ ./qlinuxfbscreen.cpp 2020-09-24 04:19:03.311256600 -0700
@@ -36,18 +36,24 @@** $QT_END_LICENSE$******************************************************************************/
-
+ #include "qlinuxfbscreen.h"
+/*
+#include <QtFbSupport/private/qfbcursor_p.h>
+#include <QtFbSupport/private/qfbwindow_p.h>
+*/
+//#include <QtPlatformSupport/private/qfbcursor_p.h>#include <QtFbSupport/private/qfbcursor_p.h>
+//#include <QtPlatformSupport/private/qfbwindow_p.h>#include <QtFbSupport/private/qfbwindow_p.h>#include <QtCore/QFile>#include <QtCore/QRegularExpression>#include <QtGui/QPainter>
-
+ #include <private/qcore_unix_p.h> // overrides QT_OPEN#include <qimage.h>#include <qdebug.h>
-
+ #include <unistd.h>#include <stdlib.h>#include <sys/ioctl.h>
@@ -60,26 +66,27 @@#include <stdio.h>#include <limits.h>#include <signal.h>
-
+ #include <linux/fb.h>+ QT_BEGIN_NAMESPACE
-
+ static int openFramebufferDevice(const QString &dev){int fd = -1;
-
+ if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR);
-
+ if (fd == -1) {if (access(dev.toLatin1().constData(), R_OK) == 0)fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY);}
-
+ return fd;}
-
+ static int determineDepth(const fb_var_screeninfo &vinfo){int depth = vinfo.bits_per_pixel;
@@ -94,7 +101,7 @@}return depth;}
-
+ static QRect determineGeometry(const fb_var_screeninfo &vinfo, const QRect &userGeometry){int xoff = vinfo.xoffset;
@@ -107,7 +114,7 @@w = vinfo.xres;if ((uint)h > vinfo.yres)h = vinfo.yres;
-
+ int xxoff = userGeometry.x(), yyoff = userGeometry.y();if (xxoff != 0 || yyoff != 0) {if (xxoff < 0 || xxoff + w > (int)(vinfo.xres))
@@ -124,20 +131,20 @@w = vinfo.xres;h = vinfo.yres;}
-
+ if (w == 0 || h == 0) {qWarning("Unable to find screen geometry, using 320x240");w = 320;h = 240;}
-
+ return QRect(xoff, yoff, w, h);}
-
+ static QSizeF determinePhysicalSize(const fb_var_screeninfo &vinfo, const QSize &mmSize, const QSize &res){int mmWidth = mmSize.width(), mmHeight = mmSize.height();
-
+ if (mmWidth <= 0 && mmHeight <= 0) {if (vinfo.width != 0 && vinfo.height != 0&& vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) {@@ -153,17 +160,17 @@} else if (mmHeight > 0 && mmWidth <= 0) {mmWidth = res.width() * mmHeight/res.height();}
-
+ return QSize(mmWidth, mmHeight);}
-
+ static QImage::Format determineFormat(const fb_var_screeninfo &info, int depth){const fb_bitfield rgba[4] = { info.red, info.green,info.blue, info.transp };
-
+ QImage::Format format = QImage::Format_Invalid;
-
+ switch (depth) {case 32: {const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0},
@@ -241,14 +248,14 @@default:break;}
-
+  qDebug() << "*******************************************" << format << "************************************************";return format;}
-
+ static int openTtyDevice(const QString &device){const char *const devs[] = { "/dev/tty0", "/dev/tty", "/dev/console", 0 };
-
+ int fd = -1;if (device.isEmpty()) {for (const char * const *dev = devs; *dev; ++dev) {@@ -259,10 +266,10 @@} else {fd = QT_OPEN(QFile::encodeName(device).constData(), O_RDWR);}
-
+ return fd;}
-
+ static void switchToGraphicsMode(int ttyfd, bool doSwitch, int *oldMode){// Do not warn if the switch fails: the ioctl fails when launching from a
@@ -273,25 +280,25 @@ioctl(ttyfd, KDSETMODE, KD_GRAPHICS);}}
-
+ static void resetTty(int ttyfd, int oldMode){ioctl(ttyfd, KDSETMODE, oldMode);
-
+ QT_CLOSE(ttyfd);}
-
+ static void blankScreen(int fd, bool on){ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);}
-
+ QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
-    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
+    : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0){mMmap.data = 0;}
-
+ QLinuxFbScreen::~QLinuxFbScreen(){if (mFbFd != -1) {@@ -299,13 +306,13 @@munmap(mMmap.data - mMmap.offset, mMmap.size);close(mFbFd);}
-
+ if (mTtyFd != -1)resetTty(mTtyFd, mOldTtyMode);
-
+ delete mBlitter;}
-
+ bool QLinuxFbScreen::initialize(){QRegularExpression ttyRx(QLatin1String("tty=(.*)"));
@@ -313,14 +320,19 @@QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
-
+  // add by immorta start
+  QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
+  // add by immorta endQString fbDevice, ttyDevice;QSize userMmSize;QRect userGeometry;bool doSwitchToGraphicsMode = true;
-
+ // Parse arguments
-    for (const QString &arg : qAsConst(mArgs)) {+
+    //for (const QString &arg : qAsConst(mArgs)) {+    //   foreach (const QString &arg, mArgs) {+     for (const QString &arg : qAsConst(mArgs)) {QRegularExpressionMatch match;if (arg == QLatin1String("nographicsmodeswitch"))doSwitchToGraphicsMode = false;
@@ -334,8 +346,12 @@ttyDevice = match.captured(1);else if (arg.contains(fbRx, &match))fbDevice = match.captured(1);
+      // add by immortal start
+      else if (arg.contains(rotationRx, &match))
+          mRotation = match.captured(1).toInt();
+      // add by immortal end}
-
+ if (fbDevice.isEmpty()) {fbDevice = QLatin1String("/dev/fb0");if (!QFile::exists(fbDevice))
@@ -345,37 +361,47 @@return false;}}
-
+ // Open the devicemFbFd = openFramebufferDevice(fbDevice);if (mFbFd == -1) {qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));return false;}
-
+ // Read the fixed and variable screen informationfb_fix_screeninfo finfo;fb_var_screeninfo vinfo;memset(&vinfo, 0, sizeof(vinfo));memset(&finfo, 0, sizeof(finfo));
-
+ if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {qErrnoWarning(errno, "Error reading fixed information");return false;}
-
+ if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {qErrnoWarning(errno, "Error reading variable information");return false;}
-
+ mDepth = determineDepth(vinfo);mBytesPerLine = finfo.line_length;QRect geometry = determineGeometry(vinfo, userGeometry);
+  // add by immortal start
+  QRect originalGeometry = geometry;
+  if( 90 == mRotation  || 270 == mRotation )
+    {+      int tmp = geometry.width();
+        geometry.setWidth(geometry.height());
+        geometry.setHeight(tmp);
+    }
+  // add by immortal endmGeometry = QRect(QPoint(0, 0), geometry.size());mFormat = determineFormat(vinfo, mDepth);
-    mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
-
+
+    //mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
+  mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());// mmap the framebuffermMmap.size = finfo.smem_len;uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
@@ -383,42 +409,60 @@qErrnoWarning(errno, "Failed to mmap framebuffer");return false;}
-
-    mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
+
+    //mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
+  mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;mMmap.data = data + mMmap.offset;
-
+ QFbScreen::initializeCompositor();
-    mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
-
+    //mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
+  mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
+ mCursor = new QFbCursor(this);
-
+ mTtyFd = openTtyDevice(ttyDevice);if (mTtyFd == -1)qErrnoWarning(errno, "Failed to open tty");
-
+ switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);blankScreen(mFbFd, false);
-
+ return true;}
-
+ QRegion QLinuxFbScreen::doRedraw(){QRegion touched = QFbScreen::doRedraw();
-
+ if (touched.isEmpty())return touched;
-
+ if (!mBlitter)mBlitter = new QPainter(&mFbScreenImage);
-
+
+  const QVector<QRect> rects = touched.rects();mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
-    for (const QRect &rect : touched)
-        mBlitter->drawImage(rect, mScreenImage, rect);
-
+  for (int i = 0; i < rects.size(); ++i)
+  {+      if( 90 == mRotation || 270 == mRotation )
+        {+          mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
+        }
+        else if( 180 == mRotation )
+        {+            mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
+        }
+        if( mRotation != 0 )
+        {+            mBlitter->rotate(mRotation);
+            mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
+        }
+        mBlitter->drawImage(rects[i], mScreenImage, rects[i]);
+      mBlitter->resetTransform();
+    }return touched;}
-
+ // grabWindow() grabs "from the screen" not from the backingstores.// In linuxfb's case it will also include the mouse cursor.QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
@@ -430,7 +474,7 @@height = mFbScreenImage.height() - y;return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);}
-
+ QFbWindow *window = windowForId(wid);if (window) {const QRect geom = window->geometry();
@@ -442,9 +486,9 @@rect &= window->geometry();return QPixmap::fromImage(mFbScreenImage).copy(rect);}
-
+ return QPixmap();}
-
+ QT_END_NAMESPACE
-
+

四.Qt运行脚本配置

//触摸翻转export QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event$i:rotate=180//界面翻转export QT_QPA_PLATFORM=linuxfb:tty=/dev/fb0:rotation=180

Qt LinuxFB旋转界面和触摸相关推荐

  1. android 酷狗demo_Android仿酷狗旋转界面功能-自定义控件实现

    引言 该旋转界面主要是仿照IOS酷狗版的旋转界面来实现,本项目通过结合ValueAnimator.Rotation.PivotX和PivotY来实现,目前主要实现了左旋转和右旋转,该功能主要是在我的乐 ...

  2. Qt designer设计界面

    1.利用 Qt designer 设计界面,保存为ui文件,例如 test.ui 2.将此文件放入 Creater 工程目录,在.pro 文件末尾处加入语句 FORMS += test.ui 3.点击 ...

  3. QT:触摸屏支持手指触摸,增加touch事件touchevent,记录前后touch坐标并处理

    QT:触摸屏支持手指触摸,增加touch事件touchevent,记录前后touch坐标并处理 1.手指触摸事件当做鼠标事件去响应的可行性 2.触摸事件touchEvent的添加 3.重写touch事 ...

  4. linux QT 结束当前进程_软件特攻队|为什么 Qt 成为 c++ 界面编程的第一选择?

    一.前言 为什么说QT越来越成为界面编程的第一选择,这要从当初为什么从MFC转到QT开始说.若想把MFC开发界面想做得好看一些是十分困难的一件事,引用第三方基于MFC的界面库代码也比较混乱,而当时看到 ...

  5. 超详细且简单的Qt Designer设置界面背景图

    ---------------------------------------------------------- 这里介绍的主要是一种放置界面底层的背景图方式 首先,先新建一个框,并填充你所需要的 ...

  6. 使用qt设计登录界面初学者_初学者素描:设计登录表单界面

    使用qt设计登录界面初学者 由Bohemian Coding的好伙伴制作的Sketch是界面设计的出色程序. 本入门级教程将向您介绍使用Sketch进行设计. 您将不需要任何程序经验,只需要一些空闲时 ...

  7. qtcreator 界面样式_Office Ribbon 界面开发入门教程:如何用Qt实现Office界面样式

    Ribbon是什么? Ribbon是一种以面板及标签页为架构的用户界面.相当于它是一个收藏了命令按钮和图标的面板(把命令组织成一组"标签",每一组包含了相关的命令.每一个应用程序都 ...

  8. Qt编写主界面顶部和左侧导航

    界面效果: 资源文件 :  Qt编写主界面顶部和左侧导航代码及资源文件 (http://www.qtcn.org/bbs/read-htm-tid-65515.html) 1.工程目录 2.main. ...

  9. qt如何设计界面更美观_8个更好的界面设计的黄金法则

    qt如何设计界面更美观 设计师每天都需要解决问题,找到正确的解决方案需要深入的研究和精心计划的测试. 发现一种万能的方法或一个秘密公式可以自动解决我们所有的界面设计问题,将是非常不错的. 我们可能还没 ...

最新文章

  1. Pascal's Triangle
  2. ViewPager 入门一
  3. SSM解决Mapper映射文件不发布
  4. 小白零基础怎么学习Java?不要慌
  5. 企业级数据库新型研发模式——数据管理DMS实践
  6. java实现次方的运算_【技术干货】Java 面试宝典:Java 基础部分(1)
  7. Servlet 介绍
  8. eclipse中git分支创建与合并(-)
  9. JAVA集合一:ArrayList和LinkedList
  10. [Markdown]纯文本标记语言MarkdowPad2--MD语法知识
  11. IT桔子2013年度中国互联网创业投资盘点(简版): 群雄逐鹿中,你还在这里坚持
  12. 基于Java实现的禁忌搜索算法
  13. UMD 被淘汰了吗?不考虑的 UMD 的库如何在纯 UMD 前端项目中运行?
  14. 欧拉公式求四面体的体积
  15. Jpress的基本使用
  16. 使用VS+VisualGDB编译Linux版本RCF
  17. 图像处理3D 人体模型
  18. DDOS防御----CENTOS 内核TCP参数优化
  19. 外报分析中国房价上涨三原因 指开发商行为怪异
  20. 小程序实现通讯录查询

热门文章

  1. java爬虫解析script_详解java爬虫jsoup解析多空格class数据
  2. 高通WLAN框架学习(31)-- Power save
  3. 怎样用计算机算游戏时间,计算器:游戏通关攻略详解 计算器:游戏用法
  4. 如何基于Flink+TensorFlow打造实时智能异常检测平台?只看这一篇就够了
  5. 数据库获取当前服务器时间
  6. (二)移动端 Web 开发进阶
  7. linux 运行函数名,JavaScript匿名函数的各种执行形式
  8. Java Swing 主题(LF)推荐 - FlatLaf
  9. hdu2553 N皇后问题【二进制状态压缩基础】
  10. 计算机作业win7操作流程,win7电脑硬盘进行分区的操作流程