From 0edf1390ca0cd70cd2b4d4c971a9631f0f35c24c Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Jul 2013 11:40:43 +0200 Subject: Windows: Mark window margins as dirty when the theme changes. Task-number: QTBUG-31523 Change-Id: Ibd8ed4e3fc5b6d1723f94dc32b3bf86b74e71020 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscontext.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 872fd07729..42b0ee9bfe 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -848,10 +848,15 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::CloseEvent: QWindowSystemInterface::handleCloseEvent(platformWindow->window()); return true; - case QtWindows::ThemeChanged: // ### fixme: Compress these events? + case QtWindows::ThemeChanged: { + // Switch from Aero to Classic changes margins. + const Qt::WindowFlags flags = platformWindow->window()->flags(); + if ((flags & Qt::WindowType_Mask) != Qt::Desktop && !(flags & Qt::FramelessWindowHint)) + platformWindow->setFlag(QWindowsWindow::FrameDirty); if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; + } #ifndef Q_OS_WINCE case QtWindows::ActivateWindowEvent: if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) -- cgit v1.2.3 From ec2aa7d282e007dcf62c79a7098286bdd9a6e1f5 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 19 Jul 2013 15:27:16 +0200 Subject: xcb: Fix minor leaks in XSettings code If some of the X11 requests fail, QXcbXSettings::QXcbXSettings() prints a warning and returns. These error paths all caused memory leaks. Change-Id: Idfecf03dd412c35552c3bbbebdda9c039aeadc13 Signed-off-by: Uli Schlachter Reviewed-by: Laszlo Papp Reviewed-by: Dmitry Shachnev Reviewed-by: Robin Burchell --- src/plugins/platforms/xcb/qxcbxsettings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index c106bd00f8..1423c6262d 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -221,6 +221,7 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen) xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error); if (error) { qWarning() << Q_FUNC_INFO << "Failed to find XSETTINGS_S atom"; + free(error); return; } xcb_atom_t selection_owner_atom = atom_reply->atom; @@ -233,14 +234,15 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen) xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error); if (error) { qWarning() << Q_FUNC_INFO << "Failed to get selection owner for XSETTINGS_S atom"; + free(error); return; } d_ptr->x_settings_window = selection_result->owner; + free(selection_result); if (!d_ptr->x_settings_window) { return; } - free(selection_result); const uint32_t event = XCB_CW_EVENT_MASK; const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE }; -- cgit v1.2.3 From 9fabb548daed933a54d24871eade9f60f9c2ae55 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 28 Jun 2013 15:54:09 +0200 Subject: EGLFS and MinimalEGL windows are not marked as OpenGL surfaces Several QOpenGLContext methods fails incorrectly on QWindows from EGL or MinimalEGL. This is happens because they are incorrectly marked as raster surfaces instead of OpenGL surfaces. Change-Id: Ic9b3859915a9049fce442216b01dce89521fa5ee Reviewed-by: Paul Olav Tvete --- src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 2 -- src/plugins/platforms/eglfs/qeglfswindow.cpp | 1 + src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp | 3 --- src/plugins/platforms/minimalegl/qminimaleglwindow.cpp | 1 + 4 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index 1898cde886..eccb7f42c5 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -192,8 +192,6 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo void QEglFSBackingStore::makeCurrent() { - // needed to prevent QOpenGLContext::makeCurrent() from failing - window()->setSurfaceType(QSurface::OpenGLSurface); (static_cast(window()->handle()))->create(); m_context->makeCurrent(window()); } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 98c54e0ee0..9aece1ea83 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -59,6 +59,7 @@ QEglFSWindow::QEglFSWindow(QWindow *w) #ifdef QEGL_EXTRA_DEBUG qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_winid)); #endif + w->setSurfaceType(QSurface::OpenGLSurface); } QEglFSWindow::~QEglFSWindow() diff --git a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp index cb245f2e5c..db6e5d94da 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp @@ -80,9 +80,6 @@ void QMinimalEglBackingStore::flush(QWindow *window, const QRegion ®ion, cons void QMinimalEglBackingStore::beginPaint(const QRegion &) { - // needed to prevent QOpenGLContext::makeCurrent() from failing - window()->setSurfaceType(QSurface::OpenGLSurface); - m_context->makeCurrent(window()); m_device = new QOpenGLPaintDevice(window()->size()); } diff --git a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp index 13640b73d6..956b5470e5 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp @@ -58,6 +58,7 @@ QMinimalEglWindow::QMinimalEglWindow(QWindow *w) if (w->geometry() != screenGeometry) { QWindowSystemInterface::handleGeometryChange(w, screenGeometry); } + w->setSurfaceType(QSurface::OpenGLSurface); } void QMinimalEglWindow::setGeometry(const QRect &) -- cgit v1.2.3 From 71535ad6bcad71793e29a7cd92197dda5274b331 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 29 Jul 2013 10:16:00 +0200 Subject: Build offscreen plugin only if freetype is available on Windows. Task-number: QTBUG-29685 Change-Id: I0d80437d07ad7f9e11343bfa7afbdeb30583f8c5 Reviewed-by: Shawn Rutledge Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/plugins/platforms/platforms.pro | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 92664826ab..377ca32e64 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,7 +2,9 @@ TEMPLATE = subdirs android:!android-no-sdk: SUBDIRS += android -SUBDIRS += minimal offscreen +SUBDIRS += minimal + +!win32|contains(QT_CONFIG, freetype):SUBDIRS += offscreen contains(QT_CONFIG, xcb) { SUBDIRS += xcb -- cgit v1.2.3 From 9eeb1bd4d44b71c4251090e9f3b7427a493d873d Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 29 Jul 2013 13:49:42 +0200 Subject: Add workaround for GL on Android emulator On the Android Emulator, the shaders will be compiled by a desktop GL driver, since the GL driver in the emulator is just a thin wrapper. The GL driver does not necessarily support the precision qualifiers, which can cause applications to break. We detect this at runtime in the platform plugin and set a workaround flag to Task-number: QTBUG-32557 Change-Id: Ied00cfe8e804d1f7862697dd379a14f3bed3d980 Reviewed-by: Gunnar Sletta --- .../android/src/opengl/qandroidopenglcontext.cpp | 15 +++++++++++++++ .../platforms/android/src/opengl/qandroidopenglcontext.h | 1 + 2 files changed, 16 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp index 4d741807d0..9d6d4003f7 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp @@ -46,6 +46,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE QAndroidOpenGLContext::QAndroidOpenGLContext(const QAndroidPlatformIntegration *integration, @@ -75,4 +77,17 @@ void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface) } } +bool QAndroidOpenGLContext::makeCurrent(QPlatformSurface *surface) +{ + bool ret = QEglFSContext::makeCurrent(surface); + + const char *rendererString = reinterpret_cast(glGetString(GL_RENDERER)); + if (rendererString != 0 && qstrncmp(rendererString, "Android Emulator", 16) == 0) { + QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); + ctx_d->workaround_missingPrecisionQualifiers = true; + } + + return ret; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h index c4c5a430ad..c419ae8392 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h @@ -58,6 +58,7 @@ public: EGLenum eglApi = EGL_OPENGL_ES_API); void swapBuffers(QPlatformSurface *surface); + bool makeCurrent(QPlatformSurface *surface); private: const QAndroidPlatformIntegration *m_platformIntegration; -- cgit v1.2.3 From 88f4baf089fddb227a22c5bc220d4a64610c0821 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 29 Jul 2013 12:25:48 +0200 Subject: Windows: Clear window under mouse in destruction of platform window. Task-number: QTBUG-32042 Change-Id: I8aa5df84b7ca6deb47e0c3eff9a6a7d2c4793553 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 +++++ src/plugins/platforms/windows/qwindowscontext.h | 1 + src/plugins/platforms/windows/qwindowsmousehandler.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 5 ++++- 4 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 872fd07729..7c6e82d0dc 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -582,6 +582,11 @@ QWindow *QWindowsContext::windowUnderMouse() const return d->m_mouseHandler.windowUnderMouse(); } +void QWindowsContext::clearWindowUnderMouse() +{ + d->m_mouseHandler.clearWindowUnderMouse(); +} + /*! \brief Find a child window at a screen point. diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index d60b632beb..6b80075379 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -166,6 +166,7 @@ public: unsigned cwex_flags) const; QWindow *windowUnderMouse() const; + void clearWindowUnderMouse(); inline bool windowsProc(HWND hwnd, UINT message, QtWindows::WindowsEventType et, diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index caf30e6b1a..7a7b92ca7e 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -72,6 +72,7 @@ public: static Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); } + void clearWindowUnderMouse() { m_windowUnderMouse = 0; } private: inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd, diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index dc51dbfc88..6549b9da3e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -871,6 +871,9 @@ void QWindowsWindow::destroyWindow() qDebug() << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); + QWindowsContext *context = QWindowsContext::instance(); + if (context->windowUnderMouse() == window()) + context->clearWindowUnderMouse(); if (hasMouseCapture()) setMouseGrabEnabled(false); unregisterDropSite(); @@ -893,7 +896,7 @@ void QWindowsWindow::destroyWindow() #endif // !Q_OS_WINCE if (m_data.hwnd != GetDesktopWindow()) DestroyWindow(m_data.hwnd); - QWindowsContext::instance()->removeWindow(m_data.hwnd); + context->removeWindow(m_data.hwnd); m_data.hwnd = 0; } } -- cgit v1.2.3 From cf3e435299ef2705fb217279bb5e93847cfc7d8c Mon Sep 17 00:00:00 2001 From: Nils Jeisecke Date: Fri, 26 Jul 2013 17:51:42 +0200 Subject: Cocoa: Make sure that resizeEvent is invoked after calling resize The QWindow::resizeEvent documentation states that resizeEvent is invoked after the windowing system has acknowledged a setGeometry() or resize() request. The Cocoa plugin however did set the platform window geometry immediately so that the qnsview's updateGeometry returned too early. Task-number: QTBUG-32706 Change-Id: I1f359ab368833d174ab6740f4467b0848c290f13 Reviewed-by: Friedemann Kleint Reviewed-by: Gunnar Sletta --- src/plugins/platforms/cocoa/qcocoawindow.mm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 057eb7e144..bba5b6fdf1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -267,7 +267,6 @@ void QCocoaWindow::setGeometry(const QRect &rect) #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::setGeometry" << this << rect; #endif - QPlatformWindow::setGeometry(rect); setCocoaGeometry(rect); } @@ -275,8 +274,10 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) { QCocoaAutoReleasePool pool; - if (m_contentViewIsEmbedded) + if (m_contentViewIsEmbedded) { + QPlatformWindow::setGeometry(rect); return; + } if (m_nsWindow) { NSRect bounds = qt_mac_flipRect(rect, window()); @@ -284,6 +285,8 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) } else { [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } + + // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) } void QCocoaWindow::setVisible(bool visible) -- cgit v1.2.3 From 130f43c9c17669ce02747176a7b3c2bf5f667204 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 30 Jul 2013 07:20:35 +0200 Subject: Gtk theme: emit currentFontChanged() in font dialog helper There is no signal for it in gtk font selection. We should emit this signal just before accept() was emitted. Change-Id: Ie31d96b789436607b134c84dd77a4b9be9e9a550 Reviewed-by: J-P Nurmi --- src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp index 77a78d2140..91a23afac5 100644 --- a/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk2/qgtk2dialoghelpers.cpp @@ -587,6 +587,7 @@ QFont QGtk2FontDialogHelper::currentFont() const void QGtk2FontDialogHelper::onAccepted() { + emit currentFontChanged(currentFont()); emit accept(); emit fontSelected(currentFont()); } -- cgit v1.2.3 From e54ef7f23bf976f264ecb5ca77e080b324f18a62 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 23 Jul 2013 13:54:37 +0200 Subject: xcb: mouse wheel does not focus a window The window should react to the wheel event (e.g. scroll content) but without becoming focused; this is the X11 convention. Task-number: QTBUG-32517 Change-Id: I7e12425e5a6e1549b7f23dc318612a436c24d14b Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0325338a13..5006aab35b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1641,7 +1641,8 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) { - if (window() != QGuiApplication::focusWindow()) { + const bool isWheel = event->detail >= 4 && event->detail <= 7; + if (!isWheel && window() != QGuiApplication::focusWindow()) { QWindow *w = static_cast(QObjectPrivate::get(window()))->eventReceiver(); if (!(w->flags() & Qt::WindowDoesNotAcceptFocus)) w->requestActivate(); @@ -1663,7 +1664,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); - if (event->detail >= 4 && event->detail <= 7) { + if (isWheel) { // Logic borrowed from qapplication_x11.cpp int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); bool hor = (((event->detail == 4 || event->detail == 5) -- cgit v1.2.3 From 87a30db468b187c9c667feefdb31a63028ee9fad Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 30 Jul 2013 10:13:31 +0200 Subject: eglfs: Fix updates when resizing backing store We would resize the backing store without resizing the viewport, which would cause all subsequent blits of the backing store to the screen to look broken. Task-number: QTBUG-32146 Change-Id: I65bae051b7cfbbc61fc285e4baa74685d5639569 Reviewed-by: Gunnar Sletta --- src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index eccb7f42c5..e09154bb59 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -79,6 +79,9 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo makeCurrent(); + QRectF sr = window->screen()->geometry(); + glViewport(0, 0, sr.width(), sr.height()); + #ifdef QEGL_EXTRA_DEBUG qWarning("QEglBackingStore::flush %p", window); #endif @@ -120,7 +123,6 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo }; QRectF r = window->geometry(); - QRectF sr = window->screen()->geometry(); GLfloat x1 = (r.left() / sr.width()) * 2 - 1; GLfloat x2 = (r.right() / sr.width()) * 2 - 1; -- cgit v1.2.3 From 7654f71f80266fd35f3c8b04d2534c876afec3a6 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 16 Jul 2013 14:18:58 +0200 Subject: Fix handling of non-latin1 shortcuts This patch enables non-latin1 shortcut handling on Qt5/X11. Task-number: QTBUG-32274 Change-Id: Ia084258b956128ffade8eddfbcb18af334d79a59 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 69 +++++++++++++++++++++--------- src/plugins/platforms/xcb/qxcbkeyboard.h | 4 +- 2 files changed, 51 insertions(+), 22 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index ae8bcb802b..38cbfaf183 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -575,7 +575,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::AltModifier | Qt::ShiftModifier, // 5 Qt::AltModifier | Qt::ControlModifier, // 6 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::NoModifier // Fall-back to raw Key_* + Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts }; Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const @@ -594,8 +594,9 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const return ret; } -void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) +void QXcbKeyboard::readXKBConfig() { + clearXKBConfig(); xcb_generic_error_t *error; xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *config_reply; @@ -626,15 +627,30 @@ void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) length -= len + 1; } while (p < end || i < 5); - xkb_names->rules = qstrdup(names[0]); - xkb_names->model = qstrdup(names[1]); - xkb_names->layout = qstrdup(names[2]); - xkb_names->variant = qstrdup(names[3]); - xkb_names->options = qstrdup(names[4]); + xkb_names.rules = qstrdup(names[0]); + xkb_names.model = qstrdup(names[1]); + xkb_names.layout = qstrdup(names[2]); + xkb_names.variant = qstrdup(names[3]); + xkb_names.options = qstrdup(names[4]); free(config_reply); } +void QXcbKeyboard::clearXKBConfig() +{ + if (xkb_names.rules) + delete[] xkb_names.rules; + if (xkb_names.model) + delete[] xkb_names.model; + if (xkb_names.layout) + delete[] xkb_names.layout; + if (xkb_names.variant) + delete[] xkb_names.variant; + if (xkb_names.options) + delete[] xkb_names.options; + memset(&xkb_names, 0, sizeof(xkb_names)); +} + void QXcbKeyboard::updateKeymap() { m_config = true; @@ -646,22 +662,13 @@ void QXcbKeyboard::updateKeymap() return; } } - - struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0}; - - readXKBConfig(&xkb_names); + readXKBConfig(); // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names if (xkb_keymap) xkb_keymap_unref(xkb_keymap); xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0); - delete[] xkb_names.rules; - delete[] xkb_names.model; - delete[] xkb_names.layout; - delete[] xkb_names.variant; - delete[] xkb_names.options; - if (!xkb_keymap) { qWarning("Qt: Failed to compile a keymap"); m_config = false; @@ -830,7 +837,7 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); xkb_mod_mask_t depressed; - + struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; //obtain a list of possible shortcuts for the given key event for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) { @@ -846,8 +853,23 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << controlMod); // update a keyboard state from a set of explicit masks - xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + if (i == 8) { + // Add a fall back key for layouts with non Latin-1 characters + if (baseQtKey > 255) { + struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; + fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); + if (!fallback_keymap) + continue; + xkb_state_unref(kb_state); + kb_state = xkb_state_new(fallback_keymap); + if (!kb_state) + continue; + } else + continue; + } else { + xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, + baseLayout, latchedLayout, lockedLayout); + } sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); if (sym == XKB_KEY_NoSymbol) @@ -862,8 +884,11 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const result += (qtKey + mods); } } + if (kb_state) + xkb_state_unref(kb_state); + if (fallback_keymap) + xkb_keymap_unref(fallback_keymap); - xkb_state_unref(kb_state); return result; } @@ -933,6 +958,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) , core_device_id(0) #endif { + memset(&xkb_names, 0, sizeof(xkb_names)); updateKeymap(); #ifndef QT_NO_XKB if (connection->hasXKB()) { @@ -974,6 +1000,7 @@ QXcbKeyboard::~QXcbKeyboard() #ifdef QT_NO_XKB xcb_key_symbols_free(m_key_symbols); #endif + clearXKBConfig(); } #ifndef QT_NO_XKB diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 770a7eabea..0256602782 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -91,7 +91,8 @@ protected: int keysymToQtKey(xcb_keysym_t keysym) const; int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, QString text) const; - void readXKBConfig(struct xkb_rule_names *names); + void readXKBConfig(); + void clearXKBConfig(); #ifdef QT_NO_XKB void updateModifiers(); @@ -107,6 +108,7 @@ private: struct xkb_context *xkb_context; struct xkb_keymap *xkb_keymap; struct xkb_state *xkb_state; + struct xkb_rule_names xkb_names; struct _mod_masks { uint alt; -- cgit v1.2.3 From c837dbecdd9ab6707798cd26ae7979063eb8d93b Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Mon, 29 Jul 2013 14:39:15 +0300 Subject: eglfs: allow egl native window to be zero Change the checking for created EGLNativeWindowType so that zero is a valid value. This is the case e.g, with BeagleBoard, where widget application cannot be run without this change. Change-Id: I36c30091e1a5a0598ae3822d0be8dc4362779c0b Reviewed-by: Gunnar Sletta --- src/plugins/platforms/eglfs/qeglfswindow.cpp | 10 ++++++---- src/plugins/platforms/eglfs/qeglfswindow.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 9aece1ea83..3b0c7de8e7 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -53,6 +53,7 @@ QEglFSWindow::QEglFSWindow(QWindow *w) : QPlatformWindow(w) , m_surface(0) , m_window(0) + , has_window(false) { static int serialNo = 0; m_winid = ++serialNo; @@ -69,7 +70,7 @@ QEglFSWindow::~QEglFSWindow() void QEglFSWindow::create() { - if (m_window) + if (has_window) return; setWindowState(Qt::WindowFullScreen); @@ -91,7 +92,7 @@ void QEglFSWindow::create() void QEglFSWindow::invalidateSurface() { // Native surface has been deleted behind our backs - m_window = 0; + has_window = false; if (m_surface != 0) { EGLDisplay display = (static_cast(window()->screen()->handle()))->display(); eglDestroySurface(display, m_surface); @@ -104,6 +105,7 @@ void QEglFSWindow::resetSurface() EGLDisplay display = static_cast(screen())->display(); m_window = QEglFSHooks::hooks()->createNativeWindow(QEglFSHooks::hooks()->screenSize(), m_format); + has_window = true; m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); if (m_surface == EGL_NO_SURFACE) { EGLint error = eglGetError(); @@ -120,9 +122,9 @@ void QEglFSWindow::destroy() m_surface = 0; } - if (m_window) { + if (has_window) { QEglFSHooks::hooks()->destroyNativeWindow(m_window); - m_window = 0; + has_window = false; } } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 67a64973ce..a119c9f815 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -76,6 +76,7 @@ private: WId m_winid; EGLConfig m_config; QSurfaceFormat m_format; + bool has_window; }; QT_END_NAMESPACE #endif // QEGLFSWINDOW_H -- cgit v1.2.3 From c707bb441486656b88748f0dfb29810181ce3460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Wed, 31 Jul 2013 13:38:17 +0100 Subject: Don't run this code on WinCE, the variable will be unused. Change-Id: Id472e6e18759227943a24aa723963671bdb52164 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowstheme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 844e46eec5..0fcd20f7bb 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -226,7 +226,6 @@ static inline QPalette menuPalette(const QPalette &systemPalette) const QColor menuColor(getSysColor(COLOR_MENU)); const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); const QColor disabled(getSysColor(COLOR_GRAYTEXT)); - const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); // we might need a special color group for the result. result.setColor(QPalette::Active, QPalette::Button, menuColor); result.setColor(QPalette::Active, QPalette::Text, menuTextColor); @@ -235,6 +234,7 @@ static inline QPalette menuPalette(const QPalette &systemPalette) result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); #ifndef Q_OS_WINCE + const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); result.setColor(QPalette::Disabled, QPalette::Highlight, getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); #else -- cgit v1.2.3 From 0ec917123f49e398e884b887b9de22f2b8b82425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Wed, 31 Jul 2013 13:29:17 +0100 Subject: Fix build with QT_NO_CURSOR. Just moved applyCursor() and defaultCursor() to a #ifndef block. Change-Id: I14c21aa509395fb1bd72d389cfc46f0f34ab7649 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowswindow.cpp | 36 +++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index dc51dbfc88..dcab51ce3e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1795,6 +1795,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const } #endif // !Q_OS_WINCE +#ifndef QT_NO_CURSOR // Return the default cursor (Arrow) from QWindowsCursor's cache. static inline QWindowsWindowCursor defaultCursor(const QWindow *w) { @@ -1805,6 +1806,24 @@ static inline QWindowsWindowCursor defaultCursor(const QWindow *w) return QWindowsWindowCursor(Qt::ArrowCursor); } +// Check whether to apply a new cursor. Either the window in question is +// currently under mouse, or it is the parent of the window under mouse and +// there is no other window with an explicitly set cursor in-between. +static inline bool applyNewCursor(const QWindow *w) +{ + const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse(); + if (underMouse == w) + return true; + for (const QWindow *p = underMouse; p ; p = p->parent()) { + if (p == w) + return true; + if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) + return false; + } + return false; +} +#endif // !QT_NO_CURSOR + /*! \brief Applies to cursor property set on the window to the global cursor. @@ -1826,23 +1845,6 @@ void QWindowsWindow::applyCursor() #endif } -// Check whether to apply a new cursor. Either the window in question is -// currently under mouse, or it is the parent of the window under mouse and -// there is no other window with an explicitly set cursor in-between. -static inline bool applyNewCursor(const QWindow *w) -{ - const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse(); - if (underMouse == w) - return true; - for (const QWindow *p = underMouse; p ; p = p->parent()) { - if (p == w) - return true; - if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) - return false; - } - return false; -} - void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) { #ifndef QT_NO_CURSOR -- cgit v1.2.3 From b59c257a04f16dfefc6a7a8a1a920a8277db1326 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 31 Jul 2013 15:40:40 +0200 Subject: Fix stuck modifier issue in the non-xcb_xkb code path Since updating the xkb_state throght core events is more tricky (opposed to the xcb-xkb code path) where we have to use xkb_state_update_key, we need to make sure that our local state is in sync with the X server's state. The local state was getting out of sync if key was pressed down in a Qt application and released in other X client (by changing the focus to another window with a mouse, for example). Task-number: QTBUG-32660 Change-Id: I662bf5aad3ab0e8591109994e746d85ff61ad6ef Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 43 +++++++++++++++++------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index ae8bcb802b..14893d9acc 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -716,14 +716,14 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) if (connection()->hasXKB()) { - xkb_state_component newState; - newState = xkb_state_update_mask(xkb_state, - state->baseMods, - state->latchedMods, - state->lockedMods, - state->baseGroup, - state->latchedGroup, - state->lockedGroup); + const xkb_state_component newState + = xkb_state_update_mask(xkb_state, + state->baseMods, + state->latchedMods, + state->lockedMods, + state->baseGroup, + state->latchedGroup, + state->lockedGroup); if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) { //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); @@ -737,17 +737,22 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state) if (!m_config) return; - quint32 modsDepressed, modsLatched, modsLocked; - modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); - modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); - - quint32 xkbMask = xkbModMask(state); - xkb_state_component newState; - newState = xkb_state_update_mask(xkb_state, - modsDepressed & xkbMask, - modsLatched & xkbMask, - modsLocked & xkbMask, + const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); + const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); + const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); + const quint32 xkbMask = xkbModMask(state); + + const quint32 latched = modsLatched & xkbMask; + const quint32 locked = modsLocked & xkbMask; + quint32 depressed = modsDepressed & xkbMask; + // set modifiers in depressed if they don't appear in any of the final masks + depressed |= ~(depressed | latched | locked) & xkbMask; + + const xkb_state_component newState + = xkb_state_update_mask(xkb_state, + depressed, + latched, + locked, 0, 0, (state >> 13) & 3); // bits 13 and 14 report the state keyboard group -- cgit v1.2.3 From c6e32b740ca7893e74c97b38073dbc7cf0ae0a97 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 31 Jul 2013 14:20:37 +0200 Subject: OSX: do not force a plain window to be on the same level as its parent 2af0a778f464980594c36098e4a8ba4448edfd29 the fix for QTBUG-27410 caused this Designer bug. Doing the automatic level escalation only for "special" windows and avoiding it for plain Qt::Window type windows is one way of fixing the Designer problem. Task-number: QTBUG-31779 Change-Id: I1da5454f31111f36480fac3b53be6d5f0ce40047 Reviewed-by: Friedemann Kleint Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoawindow.mm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index bba5b6fdf1..1126315126 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -423,11 +423,13 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags) if (type == Qt::ToolTip) windowLevel = NSScreenSaverWindowLevel; - // A window should be in at least the same level as its parent. - const QWindow * const transientParent = window()->transientParent(); - const QCocoaWindow * const transientParentWindow = transientParent ? static_cast(transientParent->handle()) : 0; - if (transientParentWindow) - windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel); + // Any "special" window should be in at least the same level as its parent. + if (type != Qt::Window) { + const QWindow * const transientParent = window()->transientParent(); + const QCocoaWindow * const transientParentWindow = transientParent ? static_cast(transientParent->handle()) : 0; + if (transientParentWindow) + windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel); + } return windowLevel; } -- cgit v1.2.3 From 03285044a087c854e0c35f01dcc832e43894c44c Mon Sep 17 00:00:00 2001 From: Jorgen Lind Date: Fri, 14 Jun 2013 14:00:36 +0200 Subject: Add how to create a udev rule for the evdev plugins Change-Id: Icd7a192701958673fe216f40ddab710f5f63a8b8 Reviewed-by: Paul Olav Tvete Reviewed-by: Andy Nichols --- src/plugins/generic/evdevkeyboard/README | 7 +++++++ src/plugins/generic/evdevmouse/README | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/plugins/generic/evdevkeyboard/README (limited to 'src/plugins') diff --git a/src/plugins/generic/evdevkeyboard/README b/src/plugins/generic/evdevkeyboard/README new file mode 100644 index 0000000000..751cc99aa9 --- /dev/null +++ b/src/plugins/generic/evdevkeyboard/README @@ -0,0 +1,7 @@ +On development machines it might be useful to add the input devices +to a group that your development user i part of. Ie add: +KERNEL=="event*", SUBSYSTEM=="input", MODE="0640", GROUP="users" + +to a file such as: +/etc/udev/rules.d/10-local.rules + diff --git a/src/plugins/generic/evdevmouse/README b/src/plugins/generic/evdevmouse/README index 76ee76bc91..526106e338 100644 --- a/src/plugins/generic/evdevmouse/README +++ b/src/plugins/generic/evdevmouse/README @@ -12,3 +12,11 @@ initial position. Touchpads reporting absolute events will work too, the positions will be turned into relative. Touchscreens are however not supported. + +On development machines it might be useful to add the input devices +to a group that your development user i part of. Ie add: +KERNEL=="event*", SUBSYSTEM=="input", MODE="0640", GROUP="users" + +to a file such as: +/etc/udev/rules.d/10-local.rules + -- cgit v1.2.3 From 521f2163b16148361d3dfa052a00c597c171d8a4 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Sat, 3 Aug 2013 13:28:06 +0200 Subject: Fix typos Change-Id: I27cbcd8c59bdc34493931f341341cc25b4aba9e7 Reviewed-by: Kurt Pattyn Reviewed-by: Paul Olav Tvete --- src/plugins/generic/evdevkeyboard/README | 2 +- src/plugins/generic/evdevmouse/README | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/generic/evdevkeyboard/README b/src/plugins/generic/evdevkeyboard/README index 751cc99aa9..0d7b52bd24 100644 --- a/src/plugins/generic/evdevkeyboard/README +++ b/src/plugins/generic/evdevkeyboard/README @@ -1,5 +1,5 @@ On development machines it might be useful to add the input devices -to a group that your development user i part of. Ie add: +to a group that your development user is part of. I.e. add: KERNEL=="event*", SUBSYSTEM=="input", MODE="0640", GROUP="users" to a file such as: diff --git a/src/plugins/generic/evdevmouse/README b/src/plugins/generic/evdevmouse/README index 526106e338..c0dd3db8b3 100644 --- a/src/plugins/generic/evdevmouse/README +++ b/src/plugins/generic/evdevmouse/README @@ -14,7 +14,7 @@ Touchpads reporting absolute events will work too, the positions will be turned into relative. Touchscreens are however not supported. On development machines it might be useful to add the input devices -to a group that your development user i part of. Ie add: +to a group that your development user is part of. I.e. add: KERNEL=="event*", SUBSYSTEM=="input", MODE="0640", GROUP="users" to a file such as: -- cgit v1.2.3 From 58a4bf2c9906797ca281c4f6f8d9568f8445e97a Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 24 May 2013 15:20:56 +0200 Subject: [Mac] Fix modifier reporting issue in the key events This issue was introduced when porting key handling code from Qt4 to Qt5. To conform to the implementation of QKeyEvent::modifiers() we have to invert modifier state logic before sending them as QKeyEvents. Task-number: QTBUG-31332 Change-Id: I3bb41169f8ab2a4b0a13a224bb461d2792d3a65f Reviewed-by: Frederik Gladhorn Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/cocoa/qnsview.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 66a1b95ad8..aff93dd133 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1036,7 +1036,7 @@ static QTouchDevice *touchDevice = 0; timestamp, (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress, modifier_key_symbols[i].qt_code, - qmodifiers); + qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]); } } -- cgit v1.2.3 From 3e078cf36db538c95fd9b491a69196e882c24e0a Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 8 Aug 2013 11:05:26 +0200 Subject: Don't release the printer after using it to change a property The printer should not be released after changing a property on it as it is still needed by QPrinter elsewhere. It is released as appropriate automatically already. Task-number: QTBUG-32831 Change-Id: Idb2d98b25b62f343015a0a0fb3c9a0d506546132 Reviewed-by: Liang Qi Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index 2dedf99582..ee8d7ea157 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -187,10 +187,8 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) if (PMSessionGetCurrentPrinter(session(), &printer) == noErr) { CFArrayRef array; - if (PMPrinterGetPaperList(printer, &array) != noErr) { - PMRelease(printer); + if (PMPrinterGetPaperList(printer, &array) != noErr) return; - } int count = CFArrayGetCount(array); for (int i = 0; i < count; ++i) { PMPaper paper = static_cast(const_cast(CFArrayGetValueAtIndex(array, i))); @@ -208,7 +206,6 @@ void QMacPrintEnginePrivate::setPaperName(const QString &name) } } } - PMRelease(printer); } } -- cgit v1.2.3 From 071c48a5ff8842d43fcdc95db08b561d340a2bfd Mon Sep 17 00:00:00 2001 From: Alexey Chernov <4ernov@gmail.com> Date: Tue, 30 Jul 2013 00:06:24 +0400 Subject: Return EGLNativeWindowType instead of window number in winId() QEglFSWindow::winId() method was changed to return EGLNativeWindowType EGL window handle instead of static window number as it recommends in documentation. QPlatformWindow documentation reads: "The platform specific window handle can be retrieved by the winId function." and also for winId() method itself: "Reimplement in subclasses to return a handle to the native window". Task-number: QTBUG-32564 Change-Id: I634c5b4d966b6aebde72518a2c39717d1b39af08 Reviewed-by: Andrew Knight Reviewed-by: Gunnar Sletta --- src/plugins/platforms/eglfs/qeglfswindow.cpp | 6 ++---- src/plugins/platforms/eglfs/qeglfswindow.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 3b0c7de8e7..28ce8c8a33 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -55,10 +55,8 @@ QEglFSWindow::QEglFSWindow(QWindow *w) , m_window(0) , has_window(false) { - static int serialNo = 0; - m_winid = ++serialNo; #ifdef QEGL_EXTRA_DEBUG - qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_winid)); + qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window)); #endif w->setSurfaceType(QSurface::OpenGLSurface); } @@ -144,7 +142,7 @@ void QEglFSWindow::setWindowState(Qt::WindowState) WId QEglFSWindow::winId() const { - return m_winid; + return WId(m_window); } QSurfaceFormat QEglFSWindow::format() const diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index a119c9f815..0997f80e74 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -73,7 +73,6 @@ protected: EGLNativeWindowType m_window; private: - WId m_winid; EGLConfig m_config; QSurfaceFormat m_format; bool has_window; -- cgit v1.2.3 From 4a195b020ef1175771be391f925c661f1758c5fd Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Sat, 3 Aug 2013 22:42:57 +1000 Subject: Do not use QWindowsFileDialogHelper for Windows Server 2003 Windows Server 2003 is based on Windows XP and should use QWindowsXpFileDialogHelper as it does not support the CLSID-based IFileDialog interfaces that are available from Windows Vista onwards. Change-Id: Idd973f9ec4c98d1f2fb7e835de64532edeccfc72 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsdialoghelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 33bed61398..27a7044868 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -2103,7 +2103,7 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) || QSysInfo::windowsVersion() <= QSysInfo::WV_2003) { return new QWindowsXpFileDialogHelper(); } - if (QSysInfo::windowsVersion() > QSysInfo::WV_XP) + if (QSysInfo::windowsVersion() > QSysInfo::WV_2003) return new QWindowsFileDialogHelper(); #else return new QWindowsFileDialogHelper(); -- cgit v1.2.3 From 79ccb4fcb5b36e694b84477cdde3a179015061be Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 9 Jul 2013 18:43:32 +0200 Subject: Make QCoreWlan plugin compile on 10.9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We take the path of least resistence and keep the old API code for 10.6 while updating the code for 10.7 and newer. This means we have some code duplication. It also means that we only compile the 10.6 code for QCoreWlanEngine when the deploymen target is 10.6. The 10.6 version file should be removed once we drop support for Snow Leopard. Change-Id: If4702b155bcdb7522800bf99a4dd37d4efed803a Reviewed-by: Gabriel de Dietrich Reviewed-by: Tor Arne Vestbø Reviewed-by: Peter Hartmann Reviewed-by: Lorn Potter --- src/plugins/bearer/corewlan/qcorewlanengine.mm | 228 ++--- .../bearer/corewlan/qcorewlanengine_10_6.mm | 916 +++++++++++++++++++++ 2 files changed, 989 insertions(+), 155 deletions(-) create mode 100644 src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm (limited to 'src/plugins') diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 7549b4a9f7..b0ed4076da 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -52,23 +52,18 @@ #include #include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include + +extern "C" { // Otherwise it won't find CWKeychain* symbols at link time +#import +} + #include "private/qcore_mac_p.h" #include #include +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_NA) + @interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject { NSNotificationCenter *notificationCenter; @@ -94,7 +89,7 @@ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; notificationCenter = [NSNotificationCenter defaultCenter]; currentInterface = [CWInterface interfaceWithName:nil]; - [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil]; + [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:CWPowerDidChangeNotification object:nil]; [locker unlock]; [autoreleasepool release]; return self; @@ -131,7 +126,7 @@ } @end -QT_MANGLE_NAMESPACE(QNSListener) *listener = 0; +static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0; QT_BEGIN_NAMESPACE @@ -171,33 +166,25 @@ void QScanThread::run() CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)]; mutex.unlock(); - if([currentInterface power]) { + if (currentInterface.powerOn) { NSError *err = nil; - NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], kCWScanKeyMerge, - [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, - [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; - NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; - CWNetwork *apNetwork; + NSSet* apSet = [currentInterface scanForNetworksWithName:nil error:&err]; if (!err) { - - for(uint row=0; row < [apArray count]; row++ ) { - apNetwork = [apArray objectAtIndex:row]; - + for (CWNetwork *apNetwork in apSet) { const QString networkSsid = QCFString::toQString([apNetwork ssid]); const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); found.append(id); QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; bool known = isKnownSsid(networkSsid); - if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if (currentInterface.serviceActive) { if( networkSsid == QCFString::toQString( [currentInterface ssid])) { state = QNetworkConfiguration::Active; } } - if(state == QNetworkConfiguration::Undefined) { + if (state == QNetworkConfiguration::Undefined) { if(known) { state = QNetworkConfiguration::Discovered; } else { @@ -205,7 +192,7 @@ void QScanThread::run() } } QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose; - if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) { + if ([apNetwork supportsSecurity:kCWSecurityNone]) { purpose = QNetworkConfiguration::PublicPurpose; } else { purpose = QNetworkConfiguration::PrivatePurpose; @@ -235,7 +222,7 @@ void QScanThread::run() interfaceName = ij.value(); } - if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if (currentInterface.serviceActive) { if( networkSsid == QCFString::toQString([currentInterface ssid])) { state = QNetworkConfiguration::Active; } @@ -298,14 +285,14 @@ void QScanThread::getUserConfigurations() NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; userProfiles.clear(); - NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; - for(uint row=0; row < [wifiInterfaces count]; row++ ) { + NSSet *wifiInterfaces = [CWInterface interfaceNames]; + for (NSString *ifName in wifiInterfaces) { - CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; - if ( ![wifiInterface power] ) + CWInterface *wifiInterface = [CWInterface interfaceWithName: ifName]; + if (!wifiInterface.powerOn) continue; - NSString *nsInterfaceName = [wifiInterface name]; + NSString *nsInterfaceName = wifiInterface.ssid; // add user configured system networks SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); @@ -314,7 +301,7 @@ void QScanThread::getUserConfigurations() NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; - for(NSString *ssidkey in thisSsidarray) { + for (NSString *ssidkey in thisSsidarray) { QString thisSsid = QCFString::toQString(ssidkey); if(!userProfiles.contains(thisSsid)) { QMap map; @@ -442,7 +429,7 @@ void QCoreWlanEngine::initialize() QMutexLocker locker(&mutex); NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - if([[CWInterface supportedInterfaces] count] > 0 && !listener) { + if ([[CWInterface interfaceNames] count] > 0 && !listener) { listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init]; listener.engine = this; hasWifi = true; @@ -479,135 +466,62 @@ void QCoreWlanEngine::connectToId(const QString &id) CWInterface *wifiInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; - if ([wifiInterface power]) { + if (wifiInterface.powerOn) { NSError *err = nil; - NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; - QString wantedSsid; - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name))); - bool using8021X = false; - if (idHash2 != id) { - NSArray *array = [CW8021XProfile allUser8021XProfiles]; - - for (NSUInteger i = 0; i < [array count]; ++i) { - const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] userDefinedName]))); - - const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] ssid]))); - - if (id == networkNameHashCheck || id == ssidHash) { - const QString thisName = scanThread->getSsidFromNetworkName(id); - if (thisName.isEmpty()) - wantedSsid = id; - else - wantedSsid = thisName; - - [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; - using8021X = true; - break; - } + QString wantedNetwork; + QMapIterator > i(scanThread->userProfiles); + while (i.hasNext()) { + i.next(); + wantedNetwork = i.key(); + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); + if (id == networkNameHash) { + wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); + break; } } - if (!using8021X) { - QString wantedNetwork; - QMapIterator > i(scanThread->userProfiles); - while (i.hasNext()) { - i.next(); - wantedNetwork = i.key(); - const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); - if (id == networkNameHash) { - wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); - break; - } - } - } - NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithBool:YES], kCWScanKeyMerge, - [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, - [NSNumber numberWithInteger:100], kCWScanKeyRestTime, - QCFString::toNSString(wantedSsid), kCWScanKeySSID, - nil]; - - NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:scanParameters error:&err]; + NSSet *scanSet = [wifiInterface scanForNetworksWithName:QCFString::toNSString(wantedSsid) error:&err]; if(!err) { - for(uint row=0; row < [scanArray count]; row++ ) { - CWNetwork *apNetwork = [scanArray objectAtIndex:row]; - - if(wantedSsid == QCFString::toQString([apNetwork ssid])) { - - if(!using8021X) { - SecKeychainAttribute attributes[3]; - - NSString *account = [apNetwork ssid]; - NSString *keyKind = @"AirPort network password"; - NSString *keyName = account; - - attributes[0].tag = kSecAccountItemAttr; - attributes[0].data = (void *)[account UTF8String]; - attributes[0].length = [account length]; - - attributes[1].tag = kSecDescriptionItemAttr; - attributes[1].data = (void *)[keyKind UTF8String]; - attributes[1].length = [keyKind length]; - - attributes[2].tag = kSecLabelItemAttr; - attributes[2].data = (void *)[keyName UTF8String]; - attributes[2].length = [keyName length]; - - SecKeychainAttributeList attributeList = {3,attributes}; - - SecKeychainSearchRef searchRef; - SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); - - NSString *password = @""; - SecKeychainItemRef searchItem; - - if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) { - UInt32 realPasswordLength; - SecKeychainAttribute attributesW[8]; - attributesW[0].tag = kSecAccountItemAttr; - SecKeychainAttributeList listW = {1,attributesW}; - char *realPassword; - OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); - - if (status == noErr) { - if (realPassword != NULL) { - - QByteArray pBuf; - pBuf.resize(realPasswordLength); - pBuf.prepend(realPassword); - pBuf.insert(realPasswordLength,'\0'); - - password = [NSString stringWithUTF8String:pBuf]; - } - SecKeychainItemFreeContent(&listW, realPassword); - } - - CFRelease(searchItem); - } else { - qDebug() << "SecKeychainSearchCopyNext error"; - } - [params setValue: password forKey: kCWAssocKeyPassphrase]; - } // end using8021X - - - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + for (CWNetwork *apNetwork in scanSet) { + CFDataRef ssidData = (CFDataRef)[apNetwork ssidData]; + bool result = false; + + SecIdentityRef identity = 0; + // Check first whether we require IEEE 802.1X authentication for the wanted SSID + if (CWKeychainCopyEAPIdentity(ssidData, &identity) == errSecSuccess) { + CFStringRef username = 0; + CFStringRef password = 0; + if (CWKeychainCopyEAPUsernameAndPassword(ssidData, &username, &password) == errSecSuccess) { + result = [wifiInterface associateToEnterpriseNetwork:apNetwork + identity:identity username:(NSString *)username password:(NSString *)password + error:&err]; + CFRelease(username); + CFRelease(password); + } + CFRelease(identity); + } else { + CFStringRef password = 0; + if (CWKeychainCopyPassword(ssidData, &password) == errSecSuccess) { + result = [wifiInterface associateToNetwork:apNetwork password:(NSString *)password error:&err]; + CFRelease(password); + } + } - if(!err) { - if(!result) { - emit connectionError(id, ConnectError); - } else { - return; - } + if (!err) { + if (!result) { + emit connectionError(id, ConnectError); } else { - qDebug() <<"associate ERROR"<< QCFString::toQString([err localizedDescription ]); + return; } + } else { + qDebug() <<"associate ERROR"<< QCFString::toQString([err localizedDescription ]); } } //end scan network } else { @@ -632,7 +546,7 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; [wifiInterface disassociate]; - if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + if (wifiInterface.serviceActive) { locker.unlock(); emit connectionError(id, DisconnectionError); locker.relock(); @@ -652,9 +566,9 @@ void QCoreWlanEngine::doRequestUpdate() NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; - for (uint row = 0; row < [wifiInterfaces count]; ++row) { - scanThread->interfaceName = QCFString::toQString([wifiInterfaces objectAtIndex:row]); + NSSet *wifiInterfaces = [CWInterface interfaceNames]; + for (NSString *ifName in wifiInterfaces) { + scanThread->interfaceName = QCFString::toQString(ifName); scanThread->start(); } locker.unlock(); @@ -668,7 +582,7 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) if(hasWifi) { NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)]; - if([defaultInterface power]) { + if (defaultInterface.powerOn) { haswifi = true; } [autoreleasepool release]; @@ -942,3 +856,7 @@ quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b) } QT_END_NAMESPACE + +#else // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE +#include "qcorewlanengine_10_6.mm" +#endif diff --git a/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm b/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm new file mode 100644 index 0000000000..1b95ae29ad --- /dev/null +++ b/src/plugins/bearer/corewlan/qcorewlanengine_10_6.mm @@ -0,0 +1,916 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +@interface QT_MANGLE_NAMESPACE(QNSListener) : NSObject +{ + NSNotificationCenter *notificationCenter; + CWInterface *currentInterface; + QCoreWlanEngine *engine; + NSLock *locker; +} +- (void)notificationHandler;//:(NSNotification *)notification; +- (void)remove; +- (void)setEngine:(QCoreWlanEngine *)coreEngine; +- (QCoreWlanEngine *)engine; +- (void)dealloc; + +@property (assign) QCoreWlanEngine* engine; + +@end + +@implementation QT_MANGLE_NAMESPACE(QNSListener) + +- (id) init +{ + [locker lock]; + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + notificationCenter = [NSNotificationCenter defaultCenter]; + currentInterface = [CWInterface interfaceWithName:nil]; + [notificationCenter addObserver:self selector:@selector(notificationHandler:) name:kCWPowerDidChangeNotification object:nil]; + [locker unlock]; + [autoreleasepool release]; + return self; +} + +-(void)dealloc +{ + [super dealloc]; +} + +-(void)setEngine:(QCoreWlanEngine *)coreEngine +{ + [locker lock]; + if(!engine) + engine = coreEngine; + [locker unlock]; +} + +-(QCoreWlanEngine *)engine +{ + return engine; +} + +-(void)remove +{ + [locker lock]; + [notificationCenter removeObserver:self]; + [locker unlock]; +} + +- (void)notificationHandler//:(NSNotification *)notification +{ + engine->requestUpdate(); +} +@end + +static QT_MANGLE_NAMESPACE(QNSListener) *listener = 0; + +QT_BEGIN_NAMESPACE + +void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) +{ + for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) { + + QString changed = QCFString::toQString((CFStringRef)CFArrayGetValueAtIndex(changedKeys, i)); + if( changed.contains("/Network/Global/IPv4")) { + QCoreWlanEngine* wlanEngine = static_cast(info); + wlanEngine->requestUpdate(); + } + } + return; +} + + +QScanThread::QScanThread(QObject *parent) + :QThread(parent) +{ +} + +QScanThread::~QScanThread() +{ +} + +void QScanThread::quit() +{ + wait(); +} + +void QScanThread::run() +{ + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QStringList found; + mutex.lock(); + CWInterface *currentInterface = [CWInterface interfaceWithName: QCFString::toNSString(interfaceName)]; + mutex.unlock(); + + if([currentInterface power]) { + NSError *err = nil; + NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kCWScanKeyMerge, + [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, + [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; + + NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; + CWNetwork *apNetwork; + + if (!err) { + + for(uint row=0; row < [apArray count]; row++ ) { + apNetwork = [apArray objectAtIndex:row]; + + const QString networkSsid = QCFString::toQString([apNetwork ssid]); + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); + found.append(id); + + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; + bool known = isKnownSsid(networkSsid); + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( networkSsid == QCFString::toQString( [currentInterface ssid])) { + state = QNetworkConfiguration::Active; + } + } + if(state == QNetworkConfiguration::Undefined) { + if(known) { + state = QNetworkConfiguration::Discovered; + } else { + state = QNetworkConfiguration::Undefined; + } + } + QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose; + if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) { + purpose = QNetworkConfiguration::PublicPurpose; + } else { + purpose = QNetworkConfiguration::PrivatePurpose; + } + + found.append(foundNetwork(id, networkSsid, state, interfaceName, purpose)); + + } + } + } + // add known configurations that are not around. + QMapIterator > i(userProfiles); + while (i.hasNext()) { + i.next(); + + QString networkName = i.key(); + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); + + if(!found.contains(id)) { + QString networkSsid = getSsidFromNetworkName(networkName); + const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; + QString interfaceName; + QMapIterator ij(i.value()); + while (ij.hasNext()) { + ij.next(); + interfaceName = ij.value(); + } + + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( networkSsid == QCFString::toQString([currentInterface ssid])) { + state = QNetworkConfiguration::Active; + } + } + if(state == QNetworkConfiguration::Undefined) { + if( userProfiles.contains(networkName) + && found.contains(ssidId)) { + state = QNetworkConfiguration::Discovered; + } + } + + if(state == QNetworkConfiguration::Undefined) { + state = QNetworkConfiguration::Defined; + } + + found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose)); + } + } + emit networksChanged(); + [autoreleasepool release]; +} + +QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose) +{ + QStringList found; + QMutexLocker locker(&mutex); + QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate; + + ptr->name = name; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->bearerType = QNetworkConfiguration::BearerWLAN; + ptr->purpose = purpose; + + fetchedConfigurations.append( ptr); + configurationInterface.insert(ptr->id, interfaceName); + + locker.unlock(); + locker.relock(); + found.append(id); + return found; +} + +QList QScanThread::getConfigurations() +{ + QMutexLocker locker(&mutex); + + QList foundConfigurations = fetchedConfigurations; + fetchedConfigurations.clear(); + + return foundConfigurations; +} + +void QScanThread::getUserConfigurations() +{ + QMutexLocker locker(&mutex); + + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + userProfiles.clear(); + + NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; + for(uint row=0; row < [wifiInterfaces count]; row++ ) { + + CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; + if ( ![wifiInterface power] ) + continue; + + NSString *nsInterfaceName = [wifiInterface name]; +// add user configured system networks + SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); + NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]); + CFRelease(dynRef); + if(airportPlist != nil) { + NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; + + NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; + for(NSString *ssidkey in thisSsidarray) { + QString thisSsid = QCFString::toQString(ssidkey); + if(!userProfiles.contains(thisSsid)) { + QMap map; + map.insert(thisSsid, QCFString::toQString(nsInterfaceName)); + userProfiles.insert(thisSsid, map); + } + } + CFRelease(airportPlist); + } + + // 802.1X user profiles + QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; + NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile: QCFString::toNSString(userProfilePath)] autorelease]; + if(eapDict != nil) { + NSString *profileStr= @"Profiles"; + NSString *nameStr = @"UserDefinedName"; + NSString *networkSsidStr = @"Wireless Network"; + for (id profileKey in eapDict) { + if ([profileStr isEqualToString:profileKey]) { + NSDictionary *itemDict = [eapDict objectForKey:profileKey]; + for (id itemKey in itemDict) { + + NSInteger dictSize = [itemKey count]; + id objects[dictSize]; + id keys[dictSize]; + + [itemKey getObjects:objects andKeys:keys]; + QString networkName; + QString ssid; + for(int i = 0; i < dictSize; i++) { + if([nameStr isEqualToString:keys[i]]) { + networkName = QCFString::toQString(objects[i]); + } + if([networkSsidStr isEqualToString:keys[i]]) { + ssid = QCFString::toQString(objects[i]); + } + if(!userProfiles.contains(networkName) + && !ssid.isEmpty()) { + QMap map; + map.insert(ssid, QCFString::toQString(nsInterfaceName)); + userProfiles.insert(networkName, map); + } + } + } + } + } + } + } + [autoreleasepool release]; +} + +QString QScanThread::getSsidFromNetworkName(const QString &name) +{ + QMutexLocker locker(&mutex); + + QMapIterator > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap map = i.value(); + QMapIterator ij(i.value()); + while (ij.hasNext()) { + ij.next(); + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); + if(name == i.key() || name == networkNameHash) { + return ij.key(); + } + } + } + return QString(); +} + +QString QScanThread::getNetworkNameFromSsid(const QString &ssid) +{ + QMutexLocker locker(&mutex); + + QMapIterator > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap map = i.value(); + QMapIterator ij(i.value()); + while (ij.hasNext()) { + ij.next(); + if(ij.key() == ssid) { + return i.key(); + } + } + } + return QString(); +} + +bool QScanThread::isKnownSsid(const QString &ssid) +{ + QMutexLocker locker(&mutex); + + QMapIterator > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap map = i.value(); + if(map.keys().contains(ssid)) { + return true; + } + } + return false; +} + + +QCoreWlanEngine::QCoreWlanEngine(QObject *parent) +: QBearerEngineImpl(parent), scanThread(0) +{ + scanThread = new QScanThread(this); + connect(scanThread, SIGNAL(networksChanged()), + this, SLOT(networksChanged())); +} + +QCoreWlanEngine::~QCoreWlanEngine() +{ + while (!foundConfigurations.isEmpty()) + delete foundConfigurations.takeFirst(); + [listener remove]; + [listener release]; +} + +void QCoreWlanEngine::initialize() +{ + QMutexLocker locker(&mutex); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + if([[CWInterface supportedInterfaces] count] > 0 && !listener) { + listener = [[QT_MANGLE_NAMESPACE(QNSListener) alloc] init]; + listener.engine = this; + hasWifi = true; + } else { + hasWifi = false; + } + storeSession = NULL; + + startNetworkChangeLoop(); + [autoreleasepool release]; +} + + +QString QCoreWlanEngine::getInterfaceFromId(const QString &id) +{ + QMutexLocker locker(&mutex); + + return scanThread->configurationInterface.value(id); +} + +bool QCoreWlanEngine::hasIdentifier(const QString &id) +{ + QMutexLocker locker(&mutex); + + return scanThread->configurationInterface.contains(id); +} + +void QCoreWlanEngine::connectToId(const QString &id) +{ + QMutexLocker locker(&mutex); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QString interfaceString = getInterfaceFromId(id); + + CWInterface *wifiInterface = + [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; + + if ([wifiInterface power]) { + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; + + QString wantedSsid; + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); + const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + scanThread->getNetworkNameFromSsid(ptr->name))); + + bool using8021X = false; + if (idHash2 != id) { + NSArray *array = [CW8021XProfile allUser8021XProfiles]; + + for (NSUInteger i = 0; i < [array count]; ++i) { + const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] userDefinedName]))); + + const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString([[array objectAtIndex:i] ssid]))); + + if (id == networkNameHashCheck || id == ssidHash) { + const QString thisName = scanThread->getSsidFromNetworkName(id); + if (thisName.isEmpty()) + wantedSsid = id; + else + wantedSsid = thisName; + + [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; + using8021X = true; + break; + } + } + } + + if (!using8021X) { + QString wantedNetwork; + QMapIterator > i(scanThread->userProfiles); + while (i.hasNext()) { + i.next(); + wantedNetwork = i.key(); + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); + if (id == networkNameHash) { + wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork); + break; + } + } + } + NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kCWScanKeyMerge, + [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, + [NSNumber numberWithInteger:100], kCWScanKeyRestTime, + QCFString::toNSString(wantedSsid), kCWScanKeySSID, + nil]; + + NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:scanParameters error:&err]; + + if(!err) { + for(uint row=0; row < [scanArray count]; row++ ) { + CWNetwork *apNetwork = [scanArray objectAtIndex:row]; + + if(wantedSsid == QCFString::toQString([apNetwork ssid])) { + + if(!using8021X) { + SecKeychainAttribute attributes[3]; + + NSString *account = [apNetwork ssid]; + NSString *keyKind = @"AirPort network password"; + NSString *keyName = account; + + attributes[0].tag = kSecAccountItemAttr; + attributes[0].data = (void *)[account UTF8String]; + attributes[0].length = [account length]; + + attributes[1].tag = kSecDescriptionItemAttr; + attributes[1].data = (void *)[keyKind UTF8String]; + attributes[1].length = [keyKind length]; + + attributes[2].tag = kSecLabelItemAttr; + attributes[2].data = (void *)[keyName UTF8String]; + attributes[2].length = [keyName length]; + + SecKeychainAttributeList attributeList = {3,attributes}; + + SecKeychainSearchRef searchRef; + SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); + + NSString *password = @""; + SecKeychainItemRef searchItem; + + if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) { + UInt32 realPasswordLength; + SecKeychainAttribute attributesW[8]; + attributesW[0].tag = kSecAccountItemAttr; + SecKeychainAttributeList listW = {1,attributesW}; + char *realPassword; + OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); + + if (status == noErr) { + if (realPassword != NULL) { + + QByteArray pBuf; + pBuf.resize(realPasswordLength); + pBuf.prepend(realPassword); + pBuf.insert(realPasswordLength,'\0'); + + password = [NSString stringWithUTF8String:pBuf]; + } + SecKeychainItemFreeContent(&listW, realPassword); + } + + CFRelease(searchItem); + } else { + qDebug() << "SecKeychainSearchCopyNext error"; + } + [params setValue: password forKey: kCWAssocKeyPassphrase]; + } // end using8021X + + + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + + if(!err) { + if(!result) { + emit connectionError(id, ConnectError); + } else { + return; + } + } else { + qDebug() <<"associate ERROR"<< QCFString::toQString([err localizedDescription ]); + } + } + } //end scan network + } else { + qDebug() <<"scan ERROR"<< QCFString::toQString([err localizedDescription ]); + } + emit connectionError(id, InterfaceLookupError); + } + + locker.unlock(); + emit connectionError(id, InterfaceLookupError); + [autoreleasepool release]; +} + +void QCoreWlanEngine::disconnectFromId(const QString &id) +{ + QMutexLocker locker(&mutex); + + QString interfaceString = getInterfaceFromId(id); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CWInterface *wifiInterface = + [CWInterface interfaceWithName: QCFString::toNSString(interfaceString)]; + + [wifiInterface disassociate]; + if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + locker.unlock(); + emit connectionError(id, DisconnectionError); + locker.relock(); + } + [autoreleasepool release]; +} + +void QCoreWlanEngine::requestUpdate() +{ + scanThread->getUserConfigurations(); + doRequestUpdate(); +} + +void QCoreWlanEngine::doRequestUpdate() +{ + QMutexLocker locker(&mutex); + + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; + for (uint row = 0; row < [wifiInterfaces count]; ++row) { + scanThread->interfaceName = QCFString::toQString([wifiInterfaces objectAtIndex:row]); + scanThread->start(); + } + locker.unlock(); + [autoreleasepool release]; +} + +bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) +{ + QMutexLocker locker(&mutex); + bool haswifi = false; + if(hasWifi) { + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + CWInterface *defaultInterface = [CWInterface interfaceWithName: QCFString::toNSString(wifiDeviceName)]; + if([defaultInterface power]) { + haswifi = true; + } + [autoreleasepool release]; + } + return haswifi; +} + + +QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id) +{ + QMutexLocker locker(&mutex); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) { + return QNetworkSession::Invalid; + } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return QNetworkSession::Connected; + } else if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + return QNetworkSession::Disconnected; + } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { + return QNetworkSession::NotAvailable; + } else if ((ptr->state & QNetworkConfiguration::Undefined) == + QNetworkConfiguration::Undefined) { + return QNetworkSession::NotAvailable; + } + + return QNetworkSession::Invalid; +} + +QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const +{ + return QNetworkConfigurationManager::ForcedRoaming; +} + +void QCoreWlanEngine::startNetworkChangeLoop() +{ + + SCDynamicStoreContext dynStoreContext = { 0, this/*(void *)storeSession*/, NULL, NULL, NULL }; + storeSession = SCDynamicStoreCreate(NULL, + CFSTR("networkChangeCallback"), + networkChangeCallback, + &dynStoreContext); + if (!storeSession ) { + qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError()); + return; + } + + CFMutableArrayRef notificationKeys; + notificationKeys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFMutableArrayRef patternsArray; + patternsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + + CFStringRef storeKey; + storeKey = SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, + kSCDynamicStoreDomainState, + kSCEntNetIPv4); + CFArrayAppendValue(notificationKeys, storeKey); + CFRelease(storeKey); + + storeKey = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, + kSCDynamicStoreDomainState, + kSCCompAnyRegex, + kSCEntNetIPv4); + CFArrayAppendValue(patternsArray, storeKey); + CFRelease(storeKey); + + if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) { + qWarning() << "register notification error:"<< SCErrorString(SCError()); + CFRelease(storeSession ); + CFRelease(notificationKeys); + CFRelease(patternsArray); + return; + } + CFRelease(notificationKeys); + CFRelease(patternsArray); + + runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0); + if (!runloopSource) { + qWarning() << "runloop source error:"<< SCErrorString(SCError()); + CFRelease(storeSession ); + return; + } + + CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode); + return; +} + +QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend() +{ + return new QNetworkSessionPrivateImpl; +} + +QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration() +{ + return QNetworkConfigurationPrivatePointer(); +} + +bool QCoreWlanEngine::requiresPolling() const +{ + return true; +} + +void QCoreWlanEngine::networksChanged() +{ + QMutexLocker locker(&mutex); + + QStringList previous = accessPointConfigurations.keys(); + + QList foundConfigurations = scanThread->getConfigurations(); + while (!foundConfigurations.isEmpty()) { + QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst(); + + previous.removeAll(cpPriv->id); + + if (accessPointConfigurations.contains(cpPriv->id)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); + + bool changed = false; + + ptr->mutex.lock(); + + if (ptr->isValid != cpPriv->isValid) { + ptr->isValid = cpPriv->isValid; + changed = true; + } + + if (ptr->name != cpPriv->name) { + ptr->name = cpPriv->name; + changed = true; + } + + if (ptr->bearerType != cpPriv->bearerType) { + ptr->bearerType = cpPriv->bearerType; + changed = true; + } + + if (ptr->state != cpPriv->state) { + ptr->state = cpPriv->state; + changed = true; + } + + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); + } + + delete cpPriv; + } else { + QNetworkConfigurationPrivatePointer ptr(cpPriv); + + accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); + emit configurationAdded(ptr); + locker.relock(); + } + } + + while (!previous.isEmpty()) { + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.take(previous.takeFirst()); + + locker.unlock(); + emit configurationRemoved(ptr); + locker.relock(); + } + + locker.unlock(); + emit updateCompleted(); + +} + +quint64 QCoreWlanEngine::bytesWritten(const QString &id) +{ + QMutexLocker locker(&mutex); + const QString interfaceStr = getInterfaceFromId(id); + return getBytes(interfaceStr,false); +} + +quint64 QCoreWlanEngine::bytesReceived(const QString &id) +{ + QMutexLocker locker(&mutex); + const QString interfaceStr = getInterfaceFromId(id); + return getBytes(interfaceStr,true); +} + +quint64 QCoreWlanEngine::startTime(const QString &identifier) +{ + QMutexLocker locker(&mutex); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + quint64 timestamp = 0; + + NSString *filePath = @"/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist"; + NSDictionary* plistDict = [[[NSDictionary alloc] initWithContentsOfFile:filePath] autorelease]; + if(plistDict == nil) + return timestamp; + NSString *input = @"KnownNetworks"; + NSString *timeStampStr = @"_timeStamp"; + + NSString *ssidStr = @"SSID_STR"; + + for (id key in plistDict) { + if ([input isEqualToString:key]) { + + NSDictionary *knownNetworksDict = [plistDict objectForKey:key]; + if(knownNetworksDict == nil) + return timestamp; + for (id networkKey in knownNetworksDict) { + bool isFound = false; + NSDictionary *itemDict = [knownNetworksDict objectForKey:networkKey]; + if(itemDict == nil) + return timestamp; + NSInteger dictSize = [itemDict count]; + id objects[dictSize]; + id keys[dictSize]; + + [itemDict getObjects:objects andKeys:keys]; + bool ok = false; + for(int i = 0; i < dictSize; i++) { + if([ssidStr isEqualToString:keys[i]]) { + const QString ident = QString::number(qHash(QLatin1String("corewlan:") + QCFString::toQString(objects[i]))); + if(ident == identifier) { + ok = true; + } + } + if(ok && [timeStampStr isEqualToString:keys[i]]) { + timestamp = (quint64)[objects[i] timeIntervalSince1970]; + isFound = true; + break; + } + } + if(isFound) + break; + } + } + } + [autoreleasepool release]; + return timestamp; +} + +quint64 QCoreWlanEngine::getBytes(const QString &interfaceName, bool b) +{ + struct ifaddrs *ifAddressList, *ifAddress; + struct if_data *if_data; + + quint64 bytes = 0; + ifAddressList = nil; + if(getifaddrs(&ifAddressList) == 0) { + for(ifAddress = ifAddressList; ifAddress; ifAddress = ifAddress->ifa_next) { + if(interfaceName == ifAddress->ifa_name) { + if_data = (struct if_data*)ifAddress->ifa_data; + if(b) { + bytes = if_data->ifi_ibytes; + break; + } else { + bytes = if_data->ifi_obytes; + break; + } + } + } + freeifaddrs(ifAddressList); + } + return bytes; +} + +QT_END_NAMESPACE -- cgit v1.2.3 From 0819c48e1bba1dd447f100d2f4a80ce5a3351ea8 Mon Sep 17 00:00:00 2001 From: Balazs Domjan Date: Wed, 7 Aug 2013 17:24:38 +0200 Subject: Fix QDialog position shift bug after resize. On Linux (XCB), resizing a dialog shifts its position. The fix corrigates the geometry of the dialog to the right values. Task-number: QTBUG-32473 Change-Id: I6d38539a3ebc3b95eacc7f13a76f83fc9e4d821c Reviewed-by: Uli Schlachter Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5006aab35b..028cd9ab72 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1302,6 +1302,9 @@ QRect QXcbWindow::windowToWmGeometry(QRect r) const r.translate(m_frameMargins.left(), m_frameMargins.top()); } else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) { r.translate(-m_frameMargins.left(), -m_frameMargins.top()); + } else if (!frameInclusive && m_gravity == XCB_GRAVITY_CENTER) { + r.translate(-(m_frameMargins.left() - m_frameMargins.right())/2, + -(m_frameMargins.top() - m_frameMargins.bottom())/2); } return r; } -- cgit v1.2.3 From 8c3b31182cbf53aad8d1979f612eefb93a548940 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 9 Aug 2013 14:09:06 +0200 Subject: Cocoa: Allow to hide menu items in menubar Task-number: QTBUG-32899 Change-Id: I423ac2d636306303d39e973f19032c9004957095 Reviewed-by: Jens Bache-Wiig --- src/plugins/platforms/cocoa/qcocoamenu.h | 3 +++ src/plugins/platforms/cocoa/qcocoamenu.mm | 2 ++ src/plugins/platforms/cocoa/qcocoamenubar.mm | 18 ++++++++++-------- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 7224ee2ff8..59fda96dff 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -84,6 +84,8 @@ public: inline NSMenuItem *nsMenuItem() const { return m_nativeItem; } + inline bool isVisible() const { return m_visible; } + virtual QPlatformMenuItem *menuItemAt(int position) const; virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const; @@ -100,6 +102,7 @@ private: NSMenuItem *m_nativeItem; NSObject *m_delegate; bool m_enabled; + bool m_visible; quintptr m_tag; QCocoaMenuBar *m_menuBar; }; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index bd406ee176..f9e033d21b 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -216,6 +216,7 @@ QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : m_enabled(true), + m_visible(true), m_tag(0), m_menuBar(0) { @@ -421,6 +422,7 @@ void QCocoaMenu::setEnabled(bool enabled) void QCocoaMenu::setVisible(bool visible) { [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; + m_visible = visible; } void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 8d1ca88b8e..ddfa9fff96 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -149,15 +149,17 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items()) cocoaMenu->syncMenuItem(item); - // If the NSMenu has no visble items, or only separators, we should hide it - // on the menubar. This can happen after syncing the menu items since they - // can be moved to other menus. BOOL shouldHide = YES; - for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) - if (![item isSeparatorItem] && ![item isHidden]) { - shouldHide = NO; - break; - } + if (cocoaMenu->isVisible()) { + // If the NSMenu has no visble items, or only separators, we should hide it + // on the menubar. This can happen after syncing the menu items since they + // can be moved to other menus. + for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) + if (![item isSeparatorItem] && ![item isHidden]) { + shouldHide = NO; + break; + } + } [cocoaMenu->nsMenuItem() setHidden:shouldHide]; } -- cgit v1.2.3