summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-03-09 10:22:45 +0100
committerFrederik Gladhorn <frederik.gladhorn@theqtcompany.com>2015-03-09 10:23:15 +0100
commit6cef72d0b4f6cd676203688a2562f0a9a620c7fb (patch)
treed45d59493e942e4489c6428e40ea979eb373eec5 /src/platformsupport
parentf7118e7f1b495fc0a0b8d83dff1a207dfddb09aa (diff)
parent1cd8d67d5f9bb0cd17147481544db8fb9342354d (diff)
Merge remote-tracking branch 'origin/5.5' into dev
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor.cpp51
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcursor_p.h21
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration_p.h2
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler.cpp138
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler_p.h19
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm36
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h3
-rw-r--r--src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm8
8 files changed, 181 insertions, 97 deletions
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
index fc6e4bad8d..bf23d52465 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp
@@ -62,7 +62,7 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen)
m_textureCoordEntry(0),
m_textureEntry(0),
m_deviceListener(0),
- m_updater(screen)
+ m_updateRequested(false)
{
QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR");
if (!hideCursorVal.isEmpty())
@@ -246,30 +246,43 @@ bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor)
}
#endif
-void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn)
+class CursorUpdateEvent : public QEvent
{
- m_active = false;
- QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn);
- QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
-}
-
-void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn)
+public:
+ CursorUpdateEvent(const QPoint &pos, const QRegion &rgn)
+ : QEvent(QEvent::Type(QEvent::User + 1)),
+ m_pos(pos),
+ m_region(rgn)
+ { }
+ QPoint pos() const { return m_pos; }
+ QRegion region() const { return m_region; }
+
+private:
+ QPoint m_pos;
+ QRegion m_region;
+};
+
+bool QEGLPlatformCursor::event(QEvent *e)
{
- if (m_active)
- return;
-
- m_active = true;
-
- // Must not flush the window system events directly from here since we are likely to
- // be a called directly from QGuiApplication's processMouseEvents. Flushing events
- // could cause reentering by dispatching more queued mouse events.
- QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection,
- Q_ARG(QPoint, pos), Q_ARG(QRegion, rgn));
+ if (e->type() == QEvent::User + 1) {
+ CursorUpdateEvent *ev = static_cast<CursorUpdateEvent *>(e);
+ m_updateRequested = false;
+ QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region());
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+ return true;
+ }
+ return QPlatformCursor::event(e);
}
void QEGLPlatformCursor::update(const QRegion &rgn)
{
- m_updater.scheduleUpdate(m_cursor.pos, rgn);
+ if (!m_updateRequested) {
+ // Must not flush the window system events directly from here since we are likely to
+ // be a called directly from QGuiApplication's processMouseEvents. Flushing events
+ // could cause reentering by dispatching more queued mouse events.
+ m_updateRequested = true;
+ QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn));
+ }
}
QRect QEGLPlatformCursor::cursorRect() const
diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
index 1c05a06b63..481bb3c74c 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h
@@ -70,24 +70,6 @@ private:
QEGLPlatformCursor *m_cursor;
};
-class QEGLPlatformCursorUpdater : public QObject
-{
- Q_OBJECT
-
-public:
- QEGLPlatformCursorUpdater(QPlatformScreen *screen)
- : m_screen(screen), m_active(false) { }
-
- void scheduleUpdate(const QPoint &pos, const QRegion &rgn);
-
-private slots:
- void update(const QPoint &pos, const QRegion &rgn);
-
-private:
- QPlatformScreen *m_screen;
- bool m_active;
-};
-
class QEGLPlatformCursor : public QPlatformCursor, protected QOpenGLFunctions
{
Q_OBJECT
@@ -109,6 +91,7 @@ public:
void updateMouseStatus();
private:
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
#ifndef QT_NO_CURSOR
bool setCurrentCursor(QCursor *cursor);
#endif
@@ -150,7 +133,7 @@ private:
int m_textureCoordEntry;
int m_textureEntry;
QEGLPlatformCursorDeviceListener *m_deviceListener;
- QEGLPlatformCursorUpdater m_updater;
+ bool m_updateRequested;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
index 3b6c862333..42fbf8c8a1 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h
@@ -90,6 +90,8 @@ public:
QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE;
+ QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
+
protected:
virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0;
virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format,
diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp
index d534985129..84844d8eda 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler.cpp
+++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp
@@ -32,72 +32,148 @@
****************************************************************************/
#include "qfbvthandler_p.h"
-#include <QtCore/private/qcrashhandler_p.h>
-#include <QtGui/private/qguiapplication_p.h>
+#include <QtCore/QSocketNotifier>
-#if defined(Q_OS_LINUX) && !defined(QT_NO_EVDEV)
-#define HAS_VT
-#endif
+#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && (!defined(QT_NO_EVDEV) || !defined(QT_NO_LIBINPUT))
-#ifdef HAS_VT
+#define VTH_ENABLED
+#include <unistd.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/signalfd.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
+#ifndef KDSKBMUTE
+#define KDSKBMUTE 0x4B51
+#endif
+
#ifdef K_OFF
#define KBD_OFF_MODE K_OFF
#else
#define KBD_OFF_MODE K_RAW
#endif
-#endif // HAS_VT
+#endif
QT_BEGIN_NAMESPACE
-QFbVtHandler *QFbVtHandler::self = 0;
-
QFbVtHandler::QFbVtHandler(QObject *parent)
- : QObject(parent), m_tty(-1)
+ : QObject(parent),
+ m_tty(-1),
+ m_signalFd(-1),
+ m_signalNotifier(0)
{
- Q_ASSERT(!self);
- self = this;
+#ifdef VTH_ENABLED
+ if (isatty(0)) {
+ m_tty = 0;
+ ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
+
+ if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) {
+ // Disable the tty keyboard.
+ ioctl(m_tty, KDSKBMUTE, 1);
+ ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
+ }
+ }
-#ifdef HAS_VT
- if (!isatty(0))
- return;
+ // SIGSEGV and such cannot safely be blocked. We cannot handle them in an
+ // async-safe manner either. Restoring the keyboard, video mode, etc. may
+ // all contain calls that cannot safely be made from a signal handler.
- m_tty = 0;
- ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode);
- if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) {
- ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE);
- QGuiApplicationPrivate *appd = QGuiApplicationPrivate::instance();
- Q_ASSERT(appd);
- QSegfaultHandler::initialize(appd->argv, appd->argc);
- QSegfaultHandler::installCrashHandler(crashHandler);
+ // Other signals: block them and use signalfd.
+ sigset_t mask;
+ sigemptyset(&mask);
+
+ // Catch Ctrl+C.
+ sigaddset(&mask, SIGINT);
+
+ // Ctrl+Z. Up to the platform plugins to handle it in a meaningful way.
+ sigaddset(&mask, SIGTSTP);
+ sigaddset(&mask, SIGCONT);
+
+ // Default signal used by kill. To overcome the common issue of no cleaning
+ // up when killing a locally started app via a remote session.
+ sigaddset(&mask, SIGTERM);
+
+ m_signalFd = signalfd(-1, &mask, SFD_CLOEXEC);
+ if (m_signalFd < 0) {
+ qErrnoWarning(errno, "signalfd() failed");
+ } else {
+ m_signalNotifier = new QSocketNotifier(m_signalFd, QSocketNotifier::Read, this);
+ connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal);
+
+ // Block the signals that are handled via signalfd. Applies only to the current
+ // thread, but new threads will inherit the creator's signal mask.
+ pthread_sigmask(SIG_BLOCK, &mask, 0);
}
#endif
}
QFbVtHandler::~QFbVtHandler()
{
- self->cleanup();
- self = 0;
+#ifdef VTH_ENABLED
+ restoreKeyboard();
+
+ if (m_signalFd != -1)
+ close(m_signalFd);
+#endif
}
-void QFbVtHandler::cleanup()
+void QFbVtHandler::restoreKeyboard()
{
+#ifdef VTH_ENABLED
if (m_tty == -1)
return;
-#ifdef HAS_VT
- ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
+ ioctl(m_tty, KDSKBMUTE, 0);
+ ioctl(m_tty, KDSKBMODE, m_oldKbdMode);
+#endif
+}
+
+// To be called from the slot connected to suspendRequested() in case the
+// platform plugin does in fact allow suspending on Ctrl+Z.
+void QFbVtHandler::suspend()
+{
+#ifdef VTH_ENABLED
+ kill(getpid(), SIGSTOP);
+#endif
+}
+
+void QFbVtHandler::handleSignal()
+{
+#ifdef VTH_ENABLED
+ m_signalNotifier->setEnabled(false);
+
+ signalfd_siginfo sig;
+ if (read(m_signalFd, &sig, sizeof(sig)) == sizeof(sig)) {
+ switch (sig.ssi_signo) {
+ case SIGINT: // fallthrough
+ case SIGTERM:
+ handleInt();
+ break;
+ case SIGTSTP:
+ emit suspendRequested();
+ break;
+ case SIGCONT:
+ emit resumed();
+ break;
+ default:
+ break;
+ }
+ }
+
+ m_signalNotifier->setEnabled(true);
#endif
}
-void QFbVtHandler::crashHandler()
+void QFbVtHandler::handleInt()
{
- Q_ASSERT(self);
- self->cleanup();
+#ifdef VTH_ENABLED
+ emit interrupted();
+ restoreKeyboard();
+ _exit(1);
+#endif
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h
index 53a39fd58b..3681def9f0 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler_p.h
+++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
+class QSocketNotifier;
+
class QFbVtHandler : public QObject
{
Q_OBJECT
@@ -57,13 +59,24 @@ public:
QFbVtHandler(QObject *parent = 0);
~QFbVtHandler();
+ void suspend();
+
+signals:
+ void interrupted();
+ void suspendRequested();
+ void resumed();
+
+private slots:
+ void handleSignal();
+
private:
- void cleanup();
- static void crashHandler();
+ void restoreKeyboard();
+ void handleInt();
- static QFbVtHandler *self;
int m_tty;
int m_oldKbdMode;
+ int m_signalFd;
+ QSocketNotifier *m_signalNotifier;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index a022587e11..99f54237bc 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -270,23 +270,29 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
fd->fixedPitch = false;
if (QCFType<CTFontRef> tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) {
- uint length = 0;
uint tag = MAKE_TAG('O', 'S', '/', '2');
CTFontRef tempFontRef = tempFont;
void *userData = reinterpret_cast<void *>(&tempFontRef);
- if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, 0, &length)) {
- QVarLengthArray<uchar> os2Table(length);
- if (length >= 86 && QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length)) {
- quint32 unicodeRange[4] = {
- qFromBigEndian<quint32>(os2Table.data() + 42),
- qFromBigEndian<quint32>(os2Table.data() + 46),
- qFromBigEndian<quint32>(os2Table.data() + 50),
- qFromBigEndian<quint32>(os2Table.data() + 54)
- };
- quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78),
- qFromBigEndian<quint32>(os2Table.data() + 82) };
- fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ uint length = 128;
+ QVarLengthArray<uchar, 128> os2Table(length);
+ if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) {
+ if (length > os2Table.length()) {
+ os2Table.resize(length);
+ if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length))
+ Q_UNREACHABLE();
+ Q_ASSERT(length >= 86);
}
+ quint32 unicodeRange[4] = {
+ qFromBigEndian<quint32>(os2Table.data() + 42),
+ qFromBigEndian<quint32>(os2Table.data() + 46),
+ qFromBigEndian<quint32>(os2Table.data() + 50),
+ qFromBigEndian<quint32>(os2Table.data() + 54)
+ };
+ quint32 codePageRange[2] = {
+ qFromBigEndian<quint32>(os2Table.data() + 78),
+ qFromBigEndian<quint32>(os2Table.data() + 82)
+ };
+ fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
}
}
@@ -342,11 +348,7 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font)
{
FontDescription fd;
getFontDescription(font, &fd);
- populateFromFontDescription(font, fd);
-}
-void QCoreTextFontDatabase::populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd)
-{
CFRetain(font);
QPlatformFontDatabase::registerFont(fd.familyName, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch,
true /* antialiased */, true /* scalable */,
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 42c8701a71..822d6f9b9c 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -70,8 +70,6 @@ Q_DECLARE_METATYPE(ATSFontContainerRef);
QT_BEGIN_NAMESPACE
-struct FontDescription;
-
class QCoreTextFontDatabase : public QPlatformFontDatabase
{
public:
@@ -96,7 +94,6 @@ public:
private:
void populateFromDescriptor(CTFontDescriptorRef font);
- void populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd);
mutable QString defaultFontName;
diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
index 64de364bfb..7e1dfd9275 100644
--- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
+++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
@@ -250,11 +250,9 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
int glyph_pos = 0;
for (int i = 0; i < len; ++i) {
- if (cgGlyphs[i]) {
- glyphs->glyphs[glyph_pos] = cgGlyphs[i];
- if (glyph_pos < i)
- cgGlyphs[glyph_pos] = cgGlyphs[i];
- }
+ glyphs->glyphs[glyph_pos] = cgGlyphs[i];
+ if (glyph_pos < i)
+ cgGlyphs[glyph_pos] = cgGlyphs[i];
glyph_pos++;
// If it's a non-BMP char, skip the lower part of surrogate pair and go