summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm15
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm144
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm25
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm37
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.cpp3
-rw-r--r--src/plugins/platforms/eglfs/qeglfswindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxsystemsettings.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp7
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h2
-rw-r--r--src/plugins/platforms/windows/main.cpp5
-rw-r--r--src/plugins/platforms/windows/qtwindows_additional.h15
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h5
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp93
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h10
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp103
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h23
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp230
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h3
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp42
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h18
-rw-r--r--src/plugins/platforms/xcb/README4
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
30 files changed, 695 insertions, 152 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index d98c49a1ce..67881d8680 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -119,7 +119,11 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o)
m_drag = o;
m_executed_drop_action = Qt::IgnoreAction;
- NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(m_drag->pixmap()));
+ QPixmap pm = m_drag->pixmap();
+ if (pm.isNull())
+ pm = defaultPixmap();
+
+ NSImage *nsimage = static_cast<NSImage *>(qt_mac_create_nsimage(pm));
QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacPasteboardMime::MIME_DND);
m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy"));
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h
index 050a2e69d1..45c35cccbf 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.h
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.h
@@ -73,9 +73,12 @@ NSImage *qt_mac_cgimage_to_nsimage(CGImageRef iamge);
NSImage *qt_mac_create_nsimage(const QPixmap &pm);
NSSize qt_mac_toNSSize(const QSize &qtSize);
+NSRect qt_mac_toNSRect(const QRect &rect);
+QRect qt_mac_toQRect(const NSRect &rect);
QColor qt_mac_toQColor(const NSColor *color);
+
// Creates a mutable shape, it's the caller's responsibility to release.
HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion &region);
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 8841a65844..bd89f26fca 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -135,7 +135,10 @@ NSImage *qt_mac_cgimage_to_nsimage(CGImageRef image)
NSImage *qt_mac_create_nsimage(const QPixmap &pm)
{
QImage image = pm.toImage();
- return qt_mac_cgimage_to_nsimage(qt_mac_image_to_cgimage(image));
+ CGImageRef cgImage = qt_mac_image_to_cgimage(image);
+ NSImage *nsImage = qt_mac_cgimage_to_nsimage(cgImage);
+ CGImageRelease(cgImage);
+ return nsImage;
}
HIMutableShapeRef qt_mac_QRegionToHIMutableShape(const QRegion &region)
@@ -159,6 +162,16 @@ NSSize qt_mac_toNSSize(const QSize &qtSize)
return NSMakeSize(qtSize.width(), qtSize.height());
}
+NSRect qt_mac_toNSRect(const QRect &rect)
+{
+ return NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height());
+}
+
+QRect qt_mac_toQRect(const NSRect &rect)
+{
+ return QRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
+}
+
QColor qt_mac_toQColor(const NSColor *color)
{
QColor qtColor;
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index e4baaab3d3..4d35b3202e 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -218,10 +218,9 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
NSMenuItem *oldItem = [m_nativeMenu itemWithTag:(NSInteger) cocoaItem];
if (cocoaItem->sync() != oldItem) {
- // native item was changed for some reason
- if (!wasMerged) {
+ // native item was changed for some reason
+ if (!wasMerged && oldItem)
[m_nativeMenu removeItem:oldItem];
- }
QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1);
insertNative(cocoaItem, beforeItem);
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index a747a82d09..0ff160957f 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -67,6 +67,8 @@ public:
const QPalette *palette(Palette type = SystemPalette) const;
const QFont *font(Font type = SystemFont) const;
+ QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
+ QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
QVariant themeHint(ThemeHint hint) const;
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index ddb550dd5f..967d65faec 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -54,7 +54,9 @@
#include "qcocoamenu.h"
#include "qcocoamenubar.h"
+#include <QtCore/qfileinfo.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/qpainter.h>
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformnativeinterface.h>
@@ -135,6 +137,143 @@ const QFont *QCocoaTheme::font(Font type) const
return m_fonts.value(type, 0);
}
+// Defined in qpaintengine_mac.mm
+extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
+
+//! \internal
+QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height)
+{
+ QPixmap ret(width, height);
+ ret.fill(QColor(0, 0, 0, 0));
+
+ CGRect rect = CGRectMake(0, 0, width, height);
+
+ CGContextRef ctx = qt_mac_cg_context(&ret);
+ CGAffineTransform old_xform = CGContextGetCTM(ctx);
+ CGContextConcatCTM(ctx, CGAffineTransformInvert(old_xform));
+ CGContextConcatCTM(ctx, CGAffineTransformIdentity);
+
+ ::RGBColor b;
+ b.blue = b.green = b.red = 255*255;
+ PlotIconRefInContext(ctx, &rect, kAlignNone, kTransformNone, &b, kPlotIconRefNormalFlags, icon);
+ CGContextRelease(ctx);
+ return ret;
+}
+
+QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
+{
+ OSType iconType = 0;
+ switch (sp) {
+ case MessageBoxQuestion:
+ iconType = kQuestionMarkIcon;
+ break;
+ case MessageBoxInformation:
+ iconType = kAlertNoteIcon;
+ break;
+ case MessageBoxWarning:
+ iconType = kAlertCautionIcon;
+ break;
+ case MessageBoxCritical:
+ iconType = kAlertStopIcon;
+ break;
+ case DesktopIcon:
+ iconType = kDesktopIcon;
+ break;
+ case TrashIcon:
+ iconType = kTrashIcon;
+ break;
+ case ComputerIcon:
+ iconType = kComputerIcon;
+ break;
+ case DriveFDIcon:
+ iconType = kGenericFloppyIcon;
+ break;
+ case DriveHDIcon:
+ iconType = kGenericHardDiskIcon;
+ break;
+ case DriveCDIcon:
+ case DriveDVDIcon:
+ iconType = kGenericCDROMIcon;
+ break;
+ case DriveNetIcon:
+ iconType = kGenericNetworkIcon;
+ break;
+ case DirOpenIcon:
+ iconType = kOpenFolderIcon;
+ break;
+ case DirClosedIcon:
+ case DirLinkIcon:
+ iconType = kGenericFolderIcon;
+ break;
+ case FileLinkIcon:
+ case FileIcon:
+ iconType = kGenericDocumentIcon;
+ break;
+ default:
+ break;
+ }
+ if (iconType != 0) {
+ QPixmap pixmap;
+ IconRef icon;
+ IconRef overlayIcon = 0;
+ if (iconType != kGenericApplicationIcon) {
+ GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon);
+ } else {
+ FSRef fsRef;
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ GetProcessBundleLocation(&psn, &fsRef);
+ GetIconRefFromFileInfo(&fsRef, 0, 0, 0, 0, kIconServicesNormalUsageFlag, &icon, 0);
+ if (sp == MessageBoxCritical) {
+ overlayIcon = icon;
+ GetIconRef(kOnSystemDisk, kSystemIconsCreator, kAlertCautionIcon, &icon);
+ }
+ }
+
+ if (icon) {
+ pixmap = qt_mac_convert_iconref(icon, size.width(), size.height());
+ ReleaseIconRef(icon);
+ }
+
+ if (overlayIcon) {
+ QSizeF littleSize = size / 2;
+ QPixmap overlayPix = qt_mac_convert_iconref(overlayIcon, littleSize.width(), littleSize.height());
+ QPainter painter(&pixmap);
+ painter.drawPixmap(littleSize.width(), littleSize.height(), overlayPix);
+ ReleaseIconRef(overlayIcon);
+ }
+
+ return pixmap;
+ }
+
+ return QPlatformTheme::standardPixmap(sp, size);
+}
+
+QPixmap QCocoaTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+{
+ FSRef macRef;
+ OSStatus status = FSPathMakeRef(reinterpret_cast<const UInt8*>(fileInfo.canonicalFilePath().toUtf8().constData()),
+ &macRef, 0);
+ if (status != noErr)
+ return QPixmap();
+ FSCatalogInfo info;
+ HFSUniStr255 macName;
+ status = FSGetCatalogInfo(&macRef, kIconServicesCatalogInfoMask, &info, &macName, 0, 0);
+ if (status != noErr)
+ return QPixmap();
+ IconRef iconRef;
+ SInt16 iconLabel;
+ status = GetIconRefFromFileInfo(&macRef, macName.length, macName.unicode,
+ kIconServicesCatalogInfoMask, &info, kIconServicesNormalUsageFlag,
+ &iconRef, &iconLabel);
+ if (status != noErr)
+ return QPixmap();
+
+ QPixmap pixmap = qt_mac_convert_iconref(iconRef, size.width(), size.height());
+ ReleaseIconRef(iconRef);
+
+ return pixmap;
+}
+
QVariant QCocoaTheme::themeHint(ThemeHint hint) const
{
switch (hint) {
@@ -146,6 +285,11 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
return QVariant(int(MacKeyboardScheme));
case TabAllWidgets:
return QVariant(bool([[NSApplication sharedApplication] isFullKeyboardAccessEnabled]));
+ case IconPixmapSizes: {
+ QList<int> sizes;
+ sizes << 16 << 32 << 64 << 128;
+ return QVariant::fromValue(sizes);
+ }
default:
break;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 014db378e7..d5dbe58de9 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -99,9 +99,10 @@ public:
void setCocoaGeometry(const QRect &rect);
void setVisible(bool visible);
void setWindowFlags(Qt::WindowFlags flags);
- Qt::WindowState setWindowState(Qt::WindowState state);
+ void setWindowState(Qt::WindowState state);
void setWindowTitle(const QString &title);
void setWindowFilePath(const QString &filePath);
+ void setWindowIcon(const QIcon &icon);
void raise();
void lower();
void propagateSizeHints();
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index f4a4936c28..b9ad35600e 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -400,12 +400,10 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
m_windowFlags = flags;
}
-Qt::WindowState QCocoaWindow::setWindowState(Qt::WindowState state)
+void QCocoaWindow::setWindowState(Qt::WindowState state)
{
if ([m_nsWindow isVisible])
syncWindowState(state); // Window state set for hidden windows take effect when show() is called.
-
- return state;
}
void QCocoaWindow::setWindowTitle(const QString &title)
@@ -429,6 +427,26 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
[m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""];
}
+void QCocoaWindow::setWindowIcon(const QIcon &icon)
+{
+ QCocoaAutoReleasePool pool;
+
+ NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
+ if (iconButton == nil) {
+ NSString *title = QCFString::toNSString(window()->windowTitle());
+ [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]];
+ iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
+ }
+ if (icon.isNull()) {
+ [iconButton setImage:nil];
+ } else {
+ QPixmap pixmap = icon.pixmap(QSize(22, 22));
+ NSImage *image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ [iconButton setImage:image];
+ [image release];
+ }
+}
+
void QCocoaWindow::raise()
{
//qDebug() << "raise" << this;
@@ -695,6 +713,7 @@ void QCocoaWindow::setNSWindow(NSWindow *window)
void QCocoaWindow::clearNSWindow(NSWindow *window)
{
+ [window setContentView:nil];
[window setDelegate:nil];
[window clearPlatformWindow];
[[NSNotificationCenter defaultCenter] removeObserver:m_contentView];
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index f23fd3045f..33d0fb4bae 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -89,6 +89,14 @@ static QTouchDevice *touchDevice = 0;
return self;
}
+- (void)dealloc
+{
+ CGImageRelease(m_cgImage);
+ m_cgImage = 0;
+ m_window = 0;
+ [super dealloc];
+}
+
- (id)initWithQWindow:(QWindow *)window platformWindow:(QCocoaWindow *) platformWindow
{
self = [self init];
@@ -129,22 +137,29 @@ static QTouchDevice *touchDevice = 0;
- (void)updateGeometry
{
- NSRect rect = [self frame];
- NSRect windowRect = [[self window] frame];
- QRect geo(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
+ QRect geometry;
+ if (m_platformWindow->m_nsWindow) {
+ // top level window, get window rect and flip y.
+ NSRect rect = [self frame];
+ NSRect windowRect = [[self window] frame];
+ geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
+ } else {
+ // child window, use the frame rect
+ geometry = qt_mac_toQRect([self frame]);
+ }
#ifdef QT_COCOA_ENABLE_WINDOW_DEBUG
- qDebug() << "QNSView::udpateGeometry" << geo;
+ qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry;
#endif
// Call setGeometry on QPlatformWindow. (not on QCocoaWindow,
// doing that will initiate a geometry change it and possibly create
// an infinite loop when this notification is triggered again.)
- m_platformWindow->QPlatformWindow::setGeometry(geo);
+ m_platformWindow->QPlatformWindow::setGeometry(geometry);
// Send a geometry change event to Qt, if it's ready to handle events
if (!m_platformWindow->m_inConstructor) {
- QWindowSystemInterface::handleGeometryChange(m_window, geo);
+ QWindowSystemInterface::handleGeometryChange(m_window, geometry);
QWindowSystemInterface::flushWindowSystemEvents();
}
}
@@ -343,11 +358,15 @@ static QTouchDevice *touchDevice = 0;
}
NSWindow *window = [self window];
- int windowHeight = [window frame].size.height;
NSPoint windowPoint = [theEvent locationInWindow];
+
+ int windowScreenY = [window frame].origin.y + [window frame].size.height;
+ int viewScreenY = [window convertBaseToScreen:[self convertPoint:[self frame].origin toView:nil]].y;
+ int titleBarHeight = windowScreenY - viewScreenY;
+
NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil];
- QPoint qtWindowPoint = QPoint(nsViewPoint.x, windowHeight - nsViewPoint.y);
- NSPoint screenPoint = [window convertBaseToScreen : windowPoint];
+ QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y);
+ NSPoint screenPoint = [window convertBaseToScreen:windowPoint];
QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y));
ulong timestamp = [theEvent timestamp] * 1000;
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp
index 9822262127..036b26a165 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp
@@ -117,10 +117,9 @@ void QEglFSWindow::setGeometry(const QRect &)
QPlatformWindow::setGeometry(rect);
}
-Qt::WindowState QEglFSWindow::setWindowState(Qt::WindowState)
+void QEglFSWindow::setWindowState(Qt::WindowState)
{
setGeometry(QRect());
- return Qt::WindowFullScreen;
}
WId QEglFSWindow::winId() const
diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h
index c9ef60ac9c..40a38fcb26 100644
--- a/src/plugins/platforms/eglfs/qeglfswindow.h
+++ b/src/plugins/platforms/eglfs/qeglfswindow.h
@@ -56,7 +56,7 @@ public:
~QEglFSWindow();
void setGeometry(const QRect &);
- Qt::WindowState setWindowState(Qt::WindowState state);
+ void setWindowState(Qt::WindowState state);
WId winId() const;
EGLSurface surface() const { return m_surface; }
diff --git a/src/plugins/platforms/qnx/qqnxsystemsettings.cpp b/src/plugins/platforms/qnx/qqnxsystemsettings.cpp
index ae7cb67314..6194a61012 100644
--- a/src/plugins/platforms/qnx/qqnxsystemsettings.cpp
+++ b/src/plugins/platforms/qnx/qqnxsystemsettings.cpp
@@ -48,11 +48,13 @@ QT_BEGIN_NAMESPACE
QHash<QPlatformTheme::Font, QFont *> qt_qnx_createRoleFonts(QPlatformFontDatabase *fontDatabase)
{
- // See http://docs.blackberry.com/en/developers/deliverables/27299/Text_tablet_1526156_11.jsp
- // which recommends using normal font size of 21 pixels and 36 pixels for titles (not covered
- // by the theme system).
+ // See http://docs.blackberry.com/en/developers/deliverables/41577/typography.jsp
+ // which recommends using
+ // - small font size of 6 points
+ // - normal font size of 8 points
+ // - 11 points for titles (not covered by the theme system).
QFont baseFont = fontDatabase->defaultFont();
- baseFont.setPixelSize(21);
+ baseFont.setPointSize(8);
QHash<QPlatformTheme::Font, QFont *> fonts;
fonts.insert(QPlatformTheme::SystemFont, new QFont(baseFont));
@@ -70,7 +72,7 @@ QHash<QPlatformTheme::Font, QFont *> qt_qnx_createRoleFonts(QPlatformFontDatabas
fonts.insert(QPlatformTheme::ComboLineEditFont, new QFont(baseFont));
QFont smallFont(baseFont);
- smallFont.setPixelSize(15);
+ smallFont.setPointSize(6);
fonts.insert(QPlatformTheme::SmallFont, new QFont(smallFont));
fonts.insert(QPlatformTheme::MiniFont, new QFont(smallFont));
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 9dd8ad7a71..097b5788f6 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -580,13 +580,13 @@ void QQnxWindow::requestActivateWindow()
}
-Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state)
+void QQnxWindow::setWindowState(Qt::WindowState state)
{
qWindowDebug() << Q_FUNC_INFO << "state =" << state;
// Prevent two calls with Qt::WindowFullScreen from changing m_unmaximizedGeometry
if (m_windowState == state)
- return state;
+ return;
switch (state) {
@@ -594,7 +594,7 @@ Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state)
// WindowActive is not an accepted parameter according to the docs
case Qt::WindowMinimized:
case Qt::WindowActive:
- return m_windowState;
+ return;
case Qt::WindowMaximized:
case Qt::WindowFullScreen:
@@ -609,7 +609,6 @@ Qt::WindowState QQnxWindow::setWindowState(Qt::WindowState state)
}
m_windowState = state;
- return state;
}
void QQnxWindow::gainedFocus()
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index d79c6785dd..90226bb9a4 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -101,7 +101,7 @@ public:
void raise();
void lower();
void requestActivateWindow();
- Qt::WindowState setWindowState(Qt::WindowState state);
+ void setWindowState(Qt::WindowState state);
void gainedFocus();
diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp
index d337234671..7557b80191 100644
--- a/src/plugins/platforms/windows/main.cpp
+++ b/src/plugins/platforms/windows/main.cpp
@@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
\section1 Tips
\list
- \li The environment variable \c QT_LIGHTHOUSE_WINDOWS_VERBOSE controls
+ \li The environment variable \c QT_QPA_VERBOSE controls
the debug level. It takes the form
\c{<keyword1>:<level1>,<keyword2>:<level2>}, where
keyword is one of \c integration, \c windows, \c backingstore and
@@ -112,9 +112,8 @@ public:
QPlatformIntegration *QWindowsIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
- Q_UNUSED(paramList);
if (system.compare(system, QStringLiteral("windows"), Qt::CaseInsensitive) == 0)
- return new QWindowsIntegration;
+ return new QWindowsIntegration(paramList);
return 0;
}
diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h
index f5ea2cf6bf..a35a513579 100644
--- a/src/plugins/platforms/windows/qtwindows_additional.h
+++ b/src/plugins/platforms/windows/qtwindows_additional.h
@@ -83,6 +83,21 @@
#define CHILDID_SELF 0
#define WM_GETOBJECT 0x003D
+#ifndef SHGFI_ADDOVERLAYS // Shell structures for icons.
+typedef struct _SHSTOCKICONINFO
+{
+ DWORD cbSize;
+ HICON hIcon;
+ int iSysImageIndex;
+ int iIcon;
+ WCHAR szPath[MAX_PATH];
+} SHSTOCKICONINFO;
+
+# define SIID_SHIELD 77
+# define SHGFI_ADDOVERLAYS 0x20
+# define SHGFI_OVERLAYINDEX 0x40
+#endif // SIID_SHIELD
+
#if !defined(__MINGW64_VERSION_MAJOR)
#define STATE_SYSTEM_HASPOPUP 0x40000000
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 98c17deba9..3d4871d7a2 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -210,7 +210,9 @@ bool QWindowsUser32DLL::initTouch()
\ingroup qt-lighthouse-win
*/
-QWindowsShell32DLL::QWindowsShell32DLL() : sHCreateItemFromParsingName(0)
+QWindowsShell32DLL::QWindowsShell32DLL()
+ : sHCreateItemFromParsingName(0)
+ , sHGetStockIconInfo(0)
{
}
@@ -218,6 +220,7 @@ void QWindowsShell32DLL::init()
{
QSystemLibrary library(QStringLiteral("shell32"));
sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName"));
+ sHGetStockIconInfo = (SHGetStockIconInfo)library.resolve("SHGetStockIconInfo");
}
QWindowsUser32DLL QWindowsContext::user32dll;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 450d6c8f4b..dcc636bfc0 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -49,6 +49,7 @@
#include <QtCore/QSharedPointer>
struct IBindCtx;
+struct _SHSTOCKICONINFO;
QT_BEGIN_NAMESPACE
@@ -99,8 +100,10 @@ struct QWindowsShell32DLL
inline void init();
typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
+ typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
SHCreateItemFromParsingName sHCreateItemFromParsingName;
+ SHGetStockIconInfo sHGetStockIconInfo;
};
#endif // Q_OS_WINCE
@@ -115,7 +118,7 @@ public:
SI_SupportsTouch = 0x2
};
- // Verbose flag set by environment variable QT_LIGHTHOUSE_WINDOWS_VERBOSE
+ // Verbose flag set by environment variable QT_QPA_VERBOSE
static int verboseIntegration;
static int verboseWindows;
static int verboseBackingStore;
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 1c9a7d36f5..b50a858f96 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -42,6 +42,7 @@
#include "qwindowsglcontext.h"
#include "qwindowscontext.h"
#include "qwindowswindow.h"
+#include "qwindowsintegration.h"
#include <QtCore/QDebug>
#include <QtCore/QSysInfo>
@@ -439,7 +440,7 @@ static int choosePixelFormat(HDC hdc,
iAttributes[i++] = WGL_SAMPLES_ARB;
samplesValuePosition = i;
iAttributes[i++] = format.samples();
- } else if (samples == 0 || samples == 1 ) {
+ } else {
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
iAttributes[i++] = FALSE;
}
@@ -855,16 +856,6 @@ QDebug operator<<(QDebug d, const QOpenGLStaticContext &s)
return d;
}
-// Use ARB unless explicitly turned off on command line.
-static inline bool useARB()
-{
- const QVariant glExtension = qApp->platformNativeInterface()->property("gl");
- if (glExtension.type() == QVariant::String
- && !glExtension.toString().compare(QStringLiteral("gdi"), Qt::CaseInsensitive))
- return false;
- return true;
-}
-
/*!
\class QWindowsGLContext
\brief Open GL context.
@@ -914,12 +905,13 @@ QWindowsGLContext::QWindowsGLContext(const QOpenGLStaticContextPtr &staticContex
if (QWindowsContext::verboseGL > 1)
describeFormats(hdc);
- // Preferably use direct rendering and ARB extensions (unless pixmap)
+ // Preferably use direct rendering and ARB extensions (unless pixmap
+ // or explicitly turned off on command line).
const QWindowsOpenGLAdditionalFormat
requestedAdditional(QWindowsGLDirectRendering);
tryExtensions = m_staticContext->hasExtensions()
&& !testFlag(requestedAdditional.formatFlags, QWindowsGLRenderToPixmap)
- && useARB();
+ && !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb);
QWindowsOpenGLAdditionalFormat obtainedAdditional;
if (tryExtensions) {
m_pixelFormat =
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 1f26ec5bab..50ffb85b01 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -187,6 +187,40 @@ void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTempl
\class QWindowsIntegration
\brief QPlatformIntegration implementation for Windows.
\internal
+
+ \section1 Programming Considerations
+
+ The platform plugin should run on Desktop Windows from Windows XP onwards
+ and Windows Embedded.
+
+ It should compile with:
+ \list
+ \li Microsoft Visual Studio 2008 or later (using the Microsoft Windows SDK,
+ (\c Q_CC_MSVC).
+ \li Stock \l{http://mingw.org/}{MinGW} (\c Q_CC_MINGW).
+ This version ships with headers that are missing a lot of WinAPI.
+ \li MinGW distributions using GCC 4.7 or higher and a recent MinGW-w64 runtime API,
+ such as \l{http://tdm-gcc.tdragon.net/}{TDM-GCC}, or
+ \l{http://mingwbuilds.sourceforge.net/}{MinGW-builds}
+ (\c Q_CC_MINGW and \c __MINGW64_VERSION_MAJOR indicating the version).
+ MinGW-w64 provides more complete headers (compared to stock MinGW from mingw.org),
+ including a considerable part of the Windows SDK.
+ \li Visual Studio 2008 for Windows Embedded (\c Q_OS_WINCE).
+ \endlist
+
+ The file \c qtwindows_additional.h contains defines and declarations that
+ are missing in MinGW. When encountering missing declarations, it should
+ be added there so that \c #ifdefs for MinGW can be avoided. Similarly,
+ \c qplatformfunctions_wince.h contains defines and declarations for
+ Windows Embedded.
+
+ When using a function from the WinAPI, the minimum supported Windows version
+ and Windows Embedded support should be checked. If the function is not supported
+ on Windows XP or is not present in the MinGW-headers, it should be dynamically
+ resolved. For this purpose, QWindowsContext has static structs like
+ QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to
+ these structs to avoid lookups in several places.
+
\ingroup qt-lighthouse-win
*/
@@ -198,9 +232,10 @@ struct QWindowsIntegrationPrivate
typedef QSharedPointer<QOpenGLStaticContext> QOpenGLStaticContextPtr;
#endif
- QWindowsIntegrationPrivate();
+ explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
+ const unsigned m_options;
QWindowsContext m_context;
QPlatformFontDatabase *m_fontDatabase;
QWindowsNativeInterface m_nativeInterface;
@@ -221,8 +256,27 @@ struct QWindowsIntegrationPrivate
QWindowsServices m_services;
};
-QWindowsIntegrationPrivate::QWindowsIntegrationPrivate()
- : m_fontDatabase(0), m_eventDispatcher(new QWindowsGuiEventDispatcher)
+static inline unsigned parseOptions(const QStringList &paramList)
+{
+ unsigned options = 0;
+ foreach (const QString &param, paramList) {
+ if (param.startsWith(QLatin1String("fontengine="))) {
+ if (param.endsWith(QLatin1String("freetype"))) {
+ options |= QWindowsIntegration::FontDatabaseFreeType;
+ } else if (param.endsWith(QLatin1String("native"))) {
+ options |= QWindowsIntegration::FontDatabaseNative;
+ }
+ } else if (param == QLatin1String("gl=gdi")) {
+ options |= QWindowsIntegration::DisableArb;
+ }
+ }
+ return options;
+}
+
+QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramList)
+ : m_options(parseOptions(paramList))
+ , m_fontDatabase(0)
+ , m_eventDispatcher(new QWindowsGuiEventDispatcher)
{
}
@@ -232,8 +286,8 @@ QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
delete m_fontDatabase;
}
-QWindowsIntegration::QWindowsIntegration() :
- d(new QWindowsIntegrationPrivate)
+QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
+ d(new QWindowsIntegrationPrivate(paramList))
{
QGuiApplicationPrivate::instance()->setEventDispatcher(d->m_eventDispatcher);
#ifndef QT_NO_CLIPBOARD
@@ -337,25 +391,6 @@ QPlatformOpenGLContext
/* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for
* QML2 applications. */
-enum FontDatabaseOption {
- FontDatabaseFreeType,
- FontDatabaseNative,
- FontDatabaseAuto
-};
-
-static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface)
-{
- const QVariant argumentV = nativeInterface.property("fontengine");
- if (argumentV.isValid()) {
- const QString argument = argumentV.toString();
- if (argument == QLatin1String("freetype"))
- return FontDatabaseFreeType;
- if (argument == QLatin1String("native"))
- return FontDatabaseNative;
- }
- return FontDatabaseAuto;
-}
-
#ifdef Q_OS_WINCE
// It's not easy to detect if we are running a QML application
// Let's try to do so by checking if the QtQuick module is loaded.
@@ -377,10 +412,9 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
#ifdef QT_NO_FREETYPE
d->m_fontDatabase = new QWindowsFontDatabase();
#else // QT_NO_FREETYPE
- FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface);
- if (option == FontDatabaseFreeType) {
+ if (d->m_options & QWindowsIntegration::FontDatabaseFreeType) {
d->m_fontDatabase = new QWindowsFontDatabaseFT;
- } else if (option == FontDatabaseNative){
+ } else if (d->m_options & QWindowsIntegration::FontDatabaseNative){
d->m_fontDatabase = new QWindowsFontDatabase;
} else {
#ifndef Q_OS_WINCE
@@ -486,6 +520,11 @@ QWindowsIntegration *QWindowsIntegration::instance()
return static_cast<QWindowsIntegration *>(QGuiApplicationPrivate::platformIntegration());
}
+unsigned QWindowsIntegration::options() const
+{
+ return d->m_options;
+}
+
QAbstractEventDispatcher * QWindowsIntegration::guiThreadEventDispatcher() const
{
return d->m_eventDispatcher;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 49780566dd..ca47dabb4b 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -53,7 +53,13 @@ struct QWindowsIntegrationPrivate;
class QWindowsIntegration : public QPlatformIntegration
{
public:
- QWindowsIntegration();
+ enum Options { // Options to be passed on command line.
+ FontDatabaseFreeType = 0x1,
+ FontDatabaseNative = 0x2,
+ DisableArb = 0x4
+ };
+
+ explicit QWindowsIntegration(const QStringList &paramList);
virtual ~QWindowsIntegration();
bool hasCapability(QPlatformIntegration::Capability cap) const;
@@ -87,6 +93,8 @@ public:
inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); }
+ unsigned options() const;
+
private:
QScopedPointer<QWindowsIntegrationPrivate> d;
};
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index b57a27acb4..c11bd8c53c 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -68,7 +68,6 @@ QWindowsKeyMapper::QWindowsKeyMapper()
QWindowsKeyMapper::~QWindowsKeyMapper()
{
- deleteLayouts();
}
#ifndef LANG_PASHTO
@@ -436,6 +435,8 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
Qt::NoModifier, // Fall-back to raw Key_*
};
+static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl;
+Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys));
/**
Remap return or action key to select key for windows mobile.
@@ -520,32 +521,10 @@ static inline bool isModifierKey(int code)
// Keyboard map private ----------------------------------------------------------------[ start ]---
-/*
- \internal
- A Windows KeyboardLayoutItem has 8 possible states:
- 1. Unmodified
- 2. Shift
- 3. Control
- 4. Control + Shift
- 5. Alt
- 6. Alt + Shift
- 7. Alt + Control
- 8. Alt + Control + Shift
-*/
-struct KeyboardLayoutItem {
- bool dirty;
- quint8 deadkeys;
- quint32 qtKey[9]; // Can by any Qt::Key_<foo>, or unicode character
-};
-
void QWindowsKeyMapper::deleteLayouts()
{
- for (int i = 0; i < 255; ++i) {
- if (keyLayout[i]) {
- delete keyLayout[i];
- keyLayout[i] = 0;
- }
- }
+ for (size_t i = 0; i < NumKeyboardLayoutItems; ++i)
+ keyLayout[i].exists = false;
}
void QWindowsKeyMapper::changeKeyboard()
@@ -594,12 +573,9 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode,
quint32 vk_key)
{
- if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty))
+ if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty))
return;
- if (!keyLayout[vk_key])
- keyLayout[vk_key] = new KeyboardLayoutItem;
-
// Copy keyboard state, so we can modify and query output for each possible permutation
unsigned char buffer[256];
memcpy(buffer, kbdBuffer, sizeof(buffer));
@@ -615,40 +591,41 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32
buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph
bool isDeadKey = false;
- keyLayout[vk_key]->deadkeys = 0;
- keyLayout[vk_key]->dirty = false;
+ keyLayout[vk_key].deadkeys = 0;
+ keyLayout[vk_key].dirty = false;
+ keyLayout[vk_key].exists = true;
setKbdState(buffer, false, false, false);
- keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0;
+ keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0;
setKbdState(buffer, true, false, false);
- keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0;
+ keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0;
setKbdState(buffer, false, true, false);
- keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0;
+ keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0;
setKbdState(buffer, true, true, false);
- keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0;
+ keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0;
setKbdState(buffer, false, false, true);
- keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0;
+ keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0;
setKbdState(buffer, true, false, true);
- keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0;
+ keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0;
setKbdState(buffer, false, true, true);
- keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0;
+ keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0;
setKbdState(buffer, true, true, true);
- keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
- keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0;
+ keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
+ keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0;
// Add a fall back key for layouts which don't do composition and show non-latin1 characters
int fallbackKey = winceKeyBend(vk_key);
if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
fallbackKey = 0;
- if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F)
+ if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key < 0x5B && vk_key > 0x2F)
fallbackKey = vk_key;
}
- keyLayout[vk_key]->qtKey[8] = fallbackKey;
+ keyLayout[vk_key].qtKey[8] = fallbackKey;
// If this vk_key a Dead Key
if (MapVirtualKey(vk_key, 2) & 0x80000000) {
@@ -666,22 +643,22 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32
if (QWindowsContext::verboseEvents > 1) {
qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key);
- for (int i = 0; i < 9; ++i) {
- qDebug(" [%d] (%d,0x%02x,'%c') %s", i,
- keyLayout[vk_key]->qtKey[i],
- keyLayout[vk_key]->qtKey[i],
- keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03,
- keyLayout[vk_key]->deadkeys & (1<<i) ? "deadkey" : "");
+ for (size_t i = 0; i < NumMods; ++i) {
+ qDebug(" [%d] (%d,0x%02x,'%c') %s", int(i),
+ keyLayout[vk_key].qtKey[i],
+ keyLayout[vk_key].qtKey[i],
+ keyLayout[vk_key].qtKey[i] ? keyLayout[vk_key].qtKey[i] : 0x03,
+ keyLayout[vk_key].deadkeys & (1<<i) ? "deadkey" : "");
}
}
}
bool QWindowsKeyMapper::isADeadKey(unsigned int vk_key, unsigned int modifiers)
{
- if (keyLayout && (vk_key < 256) && keyLayout[vk_key]) {
- for (register int i = 0; i < 9; ++i) {
+ if ((vk_key < NumKeyboardLayoutItems) && keyLayout[vk_key].exists) {
+ for (register size_t i = 0; i < NumMods; ++i) {
if (uint(ModsTbl[i]) == modifiers)
- return bool(keyLayout[vk_key]->deadkeys & 1<<i);
+ return bool(keyLayout[vk_key].deadkeys & 1<<i);
}
}
return false;
@@ -1123,11 +1100,11 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
{
QList<int> result;
- KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()];
- if (!kbItem)
+ const KeyboardLayoutItem &kbItem = keyLayout[e->nativeVirtualKey()];
+ if (!kbItem.exists)
return result;
- quint32 baseKey = kbItem->qtKey[0];
+ quint32 baseKey = kbItem.qtKey[0];
Qt::KeyboardModifiers keyMods = e->modifiers();
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
result << int(Qt::Key_Enter + keyMods);
@@ -1135,9 +1112,9 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
}
result << int(baseKey + keyMods); // The base key is _always_ valid, of course
- for (int i = 1; i < 9; ++i) {
+ for (int i = 1; i < NumMods; ++i) {
Qt::KeyboardModifiers neededMods = ModsTbl[i];
- quint32 key = kbItem->qtKey[i];
+ quint32 key = kbItem.qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
result << int(key + (keyMods & ~neededMods));
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index 7b3f18a42d..6de255facf 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -51,7 +51,25 @@ QT_BEGIN_NAMESPACE
class QKeyEvent;
class QWindow;
-struct KeyboardLayoutItem;
+/*
+ \internal
+ A Windows KeyboardLayoutItem has 8 possible states:
+ 1. Unmodified
+ 2. Shift
+ 3. Control
+ 4. Control + Shift
+ 5. Alt
+ 6. Alt + Shift
+ 7. Alt + Control
+ 8. Alt + Control + Shift
+*/
+struct KeyboardLayoutItem {
+ uint dirty : 1;
+ uint exists : 1; // whether this item has been initialized (by updatePossibleKeyCodes)
+ quint8 deadkeys;
+ static const size_t NumQtKeys = 9;
+ quint32 qtKey[NumQtKeys]; // Can by any Qt::Key_<foo>, or unicode character
+};
class QWindowsKeyMapper
{
@@ -87,8 +105,9 @@ private:
bool isADeadKey(unsigned int vk_key, unsigned int modifiers);
void deleteLayouts();
- KeyboardLayoutItem *keyLayout[256];
QWindow *m_keyGrabber;
+ static const size_t NumKeyboardLayoutItems = 256;
+ KeyboardLayoutItem keyLayout[NumKeyboardLayoutItems];
};
enum WindowsNativeModifiers {
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 7b3ffc633f..d9de911914 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -55,9 +55,13 @@
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QSysInfo>
+#include <QtCore/QCache>
#include <QtGui/QPalette>
#include <QtGui/QGuiApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QPixmapCache>
#include <qpa/qwindowsysteminterface.h>
+#include <private/qsystemlibrary_p.h>
QT_BEGIN_NAMESPACE
@@ -348,6 +352,11 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
return QVariant(int(WindowsKeyboardScheme));
case UiEffects:
return QVariant(uiEffects());
+ case IconPixmapSizes: {
+ QList<int> sizes;
+ sizes << 16 << 32;
+ return QVariant::fromValue(sizes);
+ }
default:
break;
}
@@ -433,4 +442,225 @@ void QWindowsTheme::windowsThemeChanged(QWindow * window)
QWindowSystemInterface::handleThemeChange(window);
}
+// Defined in qpixmap_win.cpp
+Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
+
+static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
+{
+#ifdef Q_OS_WINCE
+ HMODULE hmod = LoadLibrary(L"ceshell");
+#else
+ HMODULE hmod = QSystemLibrary::load(L"shell32");
+#endif
+ if (hmod) {
+ HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size.width(), size.height(), 0);
+ if (iconHandle) {
+ QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle);
+ DestroyIcon(iconHandle);
+ return iconpixmap;
+ }
+ }
+ return QPixmap();
+}
+
+QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
+{
+ int resourceId = -1;
+ LPCTSTR iconName = 0;
+ switch (sp) {
+ case DriveCDIcon:
+ case DriveDVDIcon:
+ resourceId = 12;
+ break;
+ case DriveNetIcon:
+ resourceId = 10;
+ break;
+ case DriveHDIcon:
+ resourceId = 9;
+ break;
+ case DriveFDIcon:
+ resourceId = 7;
+ break;
+ case FileIcon:
+ case FileLinkIcon:
+ resourceId = 1;
+ break;
+ case DirIcon:
+ case DirLinkIcon:
+ case DirClosedIcon:
+ resourceId = 4;
+ break;
+ case DesktopIcon:
+ resourceId = 35;
+ break;
+ case ComputerIcon:
+ resourceId = 16;
+ break;
+ case DirOpenIcon:
+ case DirLinkOpenIcon:
+ resourceId = 5;
+ break;
+ case FileDialogNewFolder:
+ resourceId = 319;
+ break;
+ case DirHomeIcon:
+ resourceId = 235;
+ break;
+ case TrashIcon:
+ resourceId = 191;
+ break;
+ case MessageBoxInformation:
+ iconName = IDI_INFORMATION;
+ break;
+ case MessageBoxWarning:
+ iconName = IDI_WARNING;
+ break;
+ case MessageBoxCritical:
+ iconName = IDI_ERROR;
+ break;
+ case MessageBoxQuestion:
+ iconName = IDI_QUESTION;
+ break;
+ case VistaShield:
+ if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
+ && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
+ if (!QWindowsContext::shell32dll.sHGetStockIconInfo)
+ return QPixmap();
+ QPixmap pixmap;
+ SHSTOCKICONINFO iconInfo;
+ memset(&iconInfo, 0, sizeof(iconInfo));
+ iconInfo.cbSize = sizeof(iconInfo);
+ const int iconSize = size.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON;
+ if (QWindowsContext::shell32dll.sHGetStockIconInfo(SIID_SHIELD, SHGFI_ICON | iconSize, &iconInfo) == S_OK) {
+ pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon);
+ DestroyIcon(iconInfo.hIcon);
+ return pixmap;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (resourceId != -1) {
+ QPixmap pixmap = loadIconFromShell32(resourceId, size);
+ if (!pixmap.isNull()) {
+ if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) {
+ QPainter painter(&pixmap);
+ QPixmap link = loadIconFromShell32(30, size);
+ painter.drawPixmap(0, 0, size.width(), size.height(), link);
+ }
+ return pixmap;
+ }
+ }
+
+ if (iconName) {
+ HICON iconHandle = LoadIcon(NULL, iconName);
+ QPixmap pixmap = qt_pixmapFromWinHICON(iconHandle);
+ DestroyIcon(iconHandle);
+ if (!pixmap.isNull())
+ return pixmap;
+ }
+
+ return QPlatformTheme::standardPixmap(sp, size);
+}
+
+static QString dirIconPixmapCacheKey(int iIcon, int iconSize)
+{
+ QString key = QLatin1String("qt_dir_") + QString::number(iIcon);
+ if (iconSize == SHGFI_LARGEICON)
+ key += QLatin1Char('l');
+ return key;
+}
+
+template <typename T>
+class FakePointer
+{
+public:
+
+ Q_STATIC_ASSERT_X(sizeof(T) <= sizeof(void *), "FakePointers can only go that far.");
+
+ static FakePointer *create(T thing)
+ {
+ return reinterpret_cast<FakePointer *>(thing);
+ }
+
+ T operator * () const
+ {
+ return T(qintptr(this));
+ }
+
+ void operator delete (void *) {}
+};
+
+QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const
+{
+ /* We don't use the variable, but by storing it statically, we
+ * ensure CoInitialize is only called once. */
+ static HRESULT comInit = CoInitialize(NULL);
+ Q_UNUSED(comInit);
+
+ static QCache<QString, FakePointer<int> > dirIconEntryCache(1000);
+ static QMutex mx;
+
+ QPixmap pixmap;
+ const QString filePath = QDir::toNativeSeparators(fileInfo.filePath());
+ int iconSize = size.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON;
+
+ bool cacheableDirIcon = fileInfo.isDir() && !fileInfo.isRoot();
+ if (cacheableDirIcon) {
+ QMutexLocker locker(&mx);
+ int iIcon = **dirIconEntryCache.object(filePath);
+ if (iIcon) {
+ QPixmapCache::find(dirIconPixmapCacheKey(iIcon, iconSize), pixmap);
+ if (pixmap.isNull()) // Let's keep both caches in sync
+ dirIconEntryCache.remove(filePath);
+ else
+ return pixmap;
+ }
+ }
+
+ SHFILEINFO info;
+ unsigned int flags =
+#ifndef Q_OS_WINCE
+ SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX;
+#else
+ iconSize|SHGFI_SYSICONINDEX;
+#endif // Q_OS_WINCE
+ unsigned long val = SHGetFileInfo((const wchar_t *)filePath.utf16(), 0,
+ &info, sizeof(SHFILEINFO), flags);
+
+ // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases
+ if (val && info.hIcon) {
+ QString key;
+ if (cacheableDirIcon) {
+ //using the unique icon index provided by windows save us from duplicate keys
+ key = dirIconPixmapCacheKey(info.iIcon, iconSize);
+ QPixmapCache::find(key, pixmap);
+ if (!pixmap.isNull()) {
+ QMutexLocker locker(&mx);
+ dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon));
+ }
+ }
+
+ if (pixmap.isNull()) {
+ pixmap = qt_pixmapFromWinHICON(info.hIcon);
+ if (!pixmap.isNull()) {
+ if (cacheableDirIcon) {
+ QMutexLocker locker(&mx);
+ QPixmapCache::insert(key, pixmap);
+ dirIconEntryCache.insert(filePath, FakePointer<int>::create(info.iIcon));
+ }
+ } else {
+ qWarning("QWindowsTheme::fileIconPixmap() no icon found");
+ }
+ }
+ DestroyIcon(info.hIcon);
+ }
+
+ if (!pixmap.isNull())
+ return pixmap;
+ return QPlatformTheme::fileIconPixmap(fileInfo, size);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 7e885b8f3e..89ef527e76 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -67,6 +67,9 @@ public:
virtual const QFont *font(Font type = SystemFont) const
{ return m_fonts[type]; }
+ virtual QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const;
+ virtual QPixmap fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &size) const;
+
void windowsThemeChanged(QWindow *window);
static const char *name;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index f3830eb962..99b8922768 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -61,6 +61,8 @@
QT_BEGIN_NAMESPACE
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
+
static QByteArray debugWinStyle(DWORD style)
{
QByteArray rc = "0x";
@@ -699,13 +701,15 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
m_cursor(QWindowsScreen::screenOf(aWindow)->windowsCursor()->standardWindowCursor()),
m_dropTarget(0),
m_savedStyle(0),
- m_format(aWindow->format())
+ m_format(aWindow->format()),
#ifdef QT_OPENGL_ES_2
- , m_eglSurface(0)
+ m_eglSurface(0),
#endif
#ifdef Q_OS_WINCE
- , m_previouslyHidden(false)
+ m_previouslyHidden(false),
#endif
+ m_iconSmall(0),
+ m_iconBig(0)
{
if (aWindow->surfaceType() == QWindow::OpenGLSurface)
setFlag(OpenGLSurface);
@@ -730,6 +734,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) :
QWindowsWindow::~QWindowsWindow()
{
destroyWindow();
+ destroyIcon();
}
void QWindowsWindow::destroyWindow()
@@ -1230,13 +1235,12 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
-Qt::WindowState QWindowsWindow::setWindowState(Qt::WindowState state)
+void QWindowsWindow::setWindowState(Qt::WindowState state)
{
if (m_data.hwnd) {
setWindowState_sys(state);
m_windowState = state;
}
- return state;
}
bool QWindowsWindow::isFullScreen_sys() const
@@ -1754,4 +1758,32 @@ QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf)
return rc;
}
+static HICON createHIcon(const QIcon &icon, int xSize, int ySize)
+{
+ if (!icon.isNull()) {
+ const QPixmap pm = icon.pixmap(icon.actualSize(QSize(xSize, ySize)));
+ if (!pm.isNull())
+ return qt_pixmapToWinHICON(pm);
+ }
+ return 0;
+}
+
+void QWindowsWindow::setWindowIcon(const QIcon &icon)
+{
+ if (m_data.hwnd) {
+ destroyIcon();
+
+ m_iconSmall = createHIcon(icon, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+ m_iconBig = createHIcon(icon, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
+
+ if (m_iconBig) {
+ SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall);
+ SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconBig);
+ } else {
+ SendMessage(m_data.hwnd, WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)m_iconSmall);
+ SendMessage(m_data.hwnd, WM_SETICON, 1 /* ICON_BIG */, (LPARAM)m_iconSmall);
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 3b7666cf32..978d1d5a53 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -160,7 +160,7 @@ public:
virtual QPoint mapFromGlobal(const QPoint &pos) const;
virtual void setWindowFlags(Qt::WindowFlags flags);
- virtual Qt::WindowState setWindowState(Qt::WindowState state);
+ virtual void setWindowState(Qt::WindowState state);
HWND handle() const { return m_data.hwnd; }
@@ -238,6 +238,7 @@ public:
void setEnabled(bool enabled);
bool isEnabled() const;
+ void setWindowIcon(const QIcon &icon);
#ifndef Q_OS_WINCE
void alertWindow(int durationMs = 0);
@@ -259,6 +260,7 @@ private:
void unregisterDropSite();
void handleGeometryChange();
void handleWindowStateChange(Qt::WindowState state);
+ inline void destroyIcon();
mutable WindowData m_data;
mutable unsigned m_flags;
@@ -277,6 +279,8 @@ private:
#ifdef Q_OS_WINCE
bool m_previouslyHidden;
#endif
+ HICON m_iconSmall;
+ HICON m_iconBig;
};
// Conveniences for window frames.
@@ -346,6 +350,18 @@ void QWindowsWindow::setUserDataOf(HWND hwnd, void *ud)
SetWindowLongPtr(hwnd, GWLP_USERDATA, LONG_PTR(ud));
}
+inline void QWindowsWindow::destroyIcon()
+{
+ if (m_iconBig) {
+ DestroyIcon(m_iconBig);
+ m_iconBig = 0;
+ }
+ if (m_iconSmall) {
+ DestroyIcon(m_iconSmall);
+ m_iconSmall = 0;
+ }
+}
+
QT_END_NAMESPACE
#endif // QWINDOWSWINDOW_H
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README
index 6254d68ae8..264d28c6b4 100644
--- a/src/plugins/platforms/xcb/README
+++ b/src/plugins/platforms/xcb/README
@@ -9,3 +9,7 @@ The packages for xcb-render-util can be installed manually from http://packages.
On Ubuntu 12.04 icccm1 is replaced by icccm4 and xcb-render-util can be installed automatically:
libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev
+
+
+On Fedora, the following packages are required:
+libxcb libxcb-devel libXrender libXrender-devel xcb-util-wm xcb-util-wm-devel xcb-util xcb-util-devel xcb-util-image xcb-util-image-devel xcb-util-keysyms xcb-util-keysyms-devel
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index cefe1a7786..bab1884a9a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -847,10 +847,10 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
-Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
+void QXcbWindow::setWindowState(Qt::WindowState state)
{
if (state == m_windowState)
- return state;
+ return;
// unset old state
switch (m_windowState) {
@@ -905,7 +905,6 @@ Qt::WindowState QXcbWindow::setWindowState(Qt::WindowState state)
connection()->sync();
m_windowState = state;
- return m_windowState;
}
void QXcbWindow::setNetWmWindowFlags(Qt::WindowFlags flags)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index e2f62401dc..bd4d18a175 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -82,7 +82,7 @@ public:
void setVisible(bool visible);
void setWindowFlags(Qt::WindowFlags flags);
- Qt::WindowState setWindowState(Qt::WindowState state);
+ void setWindowState(Qt::WindowState state);
WId winId() const;
void setParent(const QPlatformWindow *window);