Reputation: 1455
I have an embedded linux application running directly on the linux framebuffer (no x-Windows). We now have to physically rotate the display 180 degrees. How do I get my Qt application to rotate so it doesn't appear upside down? I saw reference to using the following option:
-platform linuxfb:fb=/dev/fb0:rotation:180
However, the rotation option seems to be ignored.
Using Qt 5.9.2 on Ubuntu server 16.04.6
Upvotes: 7
Views: 5458
Reputation: 69
It's an old thread, but at least for me in 2024 this was still useful. However, when doing this the keyPress event was being received up to 4 times in our GUI. Probably something was not being done properly in the event handling and adding the view and scene exposed it. Anyways, we managed to rotate the GUI using this solution by BorkedLabs: https://borkedlabs.com/blog/2015/06-01-qt5-linuxfb-rotation-for-lcds/ But I had to modify the patch to use in QT 5.14.2
Since we are using Yocto, I had to add the patch in meta-qt5/recipes-qt/qt5/qtbase/0023-linuxfb_rotation.patch
and modify meta-qt5/recipes-qt/qt5/qtbase/qtbase_git.bb
to include it among the other patches.
The patch:
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
index a66c9fa..a5b5f13 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp
@@ -287,7 +287,7 @@ static void blankScreen(int fd, bool on)
}
QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
- : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0)
+ : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0), mRotation(180)
{
mMmap.data = 0;
}
@@ -313,6 +313,7 @@ bool QLinuxFbScreen::initialize()
QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
+ QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
QString fbDevice, ttyDevice;
QSize userMmSize;
@@ -334,6 +335,8 @@ bool QLinuxFbScreen::initialize()
ttyDevice = match.captured(1);
else if (arg.contains(fbRx, &match))
fbDevice = match.captured(1);
+ else if (arg.contains(rotationRx, &match))
+ mRotation = match.captured(1).toInt();
}
if (fbDevice.isEmpty()) {
@@ -372,10 +375,17 @@ bool QLinuxFbScreen::initialize()
mDepth = determineDepth(vinfo);
mBytesPerLine = finfo.line_length;
QRect geometry = determineGeometry(vinfo, userGeometry);
+ QRect originalGeometry = geometry;
+ if( mRotation == 90 || mRotation == 270 )
+ {
+ int tmp = geometry.width();
+ geometry.setWidth(geometry.height());
+ geometry.setHeight(tmp);
+ }
+
mGeometry = QRect(QPoint(0, 0), geometry.size());
mFormat = determineFormat(vinfo, mDepth);
- mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
-
+ mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
// mmap the framebuffer
mMmap.size = finfo.smem_len;
uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
@@ -384,11 +394,11 @@ bool QLinuxFbScreen::initialize()
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);
@@ -414,8 +424,27 @@ QRegion QLinuxFbScreen::doRedraw()
mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
for (const QRect &rect : touched)
+ {
+ if( mRotation == 90 || mRotation == 270 )
+ {
+ mBlitter->translate(mGeometry.height()/2, mGeometry.width()/2);
+ }
+ else if( mRotation == 180 )
+ {
+ mBlitter->translate(mGeometry.width()/2, mGeometry.height()/2);
+ }
+
+ if( mRotation != 0 )
+ {
+ mBlitter->rotate(mRotation);
+ mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
+ }
+
mBlitter->drawImage(rect, mScreenImage, rect);
+ mBlitter->resetTransform();
+ }
+
return touched;
}
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
index 1997d46..a34414f 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
+++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h
@@ -57,6 +57,7 @@ private:
QStringList mArgs;
int mFbFd;
int mTtyFd;
+ int mRotation;
QImage mFbScreenImage;
int mBytesPerLine;
Upvotes: 0
Reputation: 879
You could handle it on application level. With QML thats easy, but with QWidgets the best I could come up with is to render the Widget on a QGraphicsScene
and rotate it like this:
#include "mainwindow.h"
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QGraphicsScene *scene = new QGraphicsScene();
QGraphicsView *view = new QGraphicsView();
view->setGeometry(w.geometry());
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scene->addWidget(&w);
view->setScene(scene);
view->show();
view->rotate(180);
//w.show();
return a.exec();
}
It seems a bit glitchy, but you could give it a try.
Also I think the correct syntax is -platform linuxfb:fb=/dev/fb0:rotation=180
note the =
instead of :
Edit: but that did not make a difference for me either.
Upvotes: 6