From be41c140594ccea16ce17ccca7251d614cc75e1e Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 6 Dec 2010 08:47:32 +0100 Subject: Propegate fullscreen screen size back to toplevel widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by: Jørgen Lind --- src/plugins/platforms/eglfs/qeglfswindow.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index d0e15d3..b5b7e05 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -62,6 +62,9 @@ void QEglFSWindow::setGeometry(const QRect &) QRect rect(m_screen->availableGeometry()); QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + // Since toplevels are fullscreen, propegate the screen size back to the widget + widget()->setGeometry(rect); + QPlatformWindow::setGeometry(rect); } -- cgit v0.12 From 3753b15e88f2c8220b887f27be79491c4135a291 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Mon, 6 Dec 2010 16:13:34 +0100 Subject: Added window focus handling to lighthouse The idea is that QPlatformWindows can request focus handling. And when actual focus shifting is done by windowsystem callbacks/events which are sent to QWindowSystemInterface --- src/gui/kernel/qapplication_p.h | 2 ++ src/gui/kernel/qapplication_qpa.cpp | 7 +++++++ src/gui/kernel/qplatformwindow_qpa.cpp | 19 +++++++++++++++++++ src/gui/kernel/qplatformwindow_qpa.h | 1 + src/gui/kernel/qwidget_qpa.cpp | 8 ++------ src/gui/kernel/qwindowsysteminterface_qpa.cpp | 6 ++++++ src/gui/kernel/qwindowsysteminterface_qpa.h | 1 + src/gui/kernel/qwindowsysteminterface_qpa_p.h | 9 +++++++++ src/plugins/platforms/testlite/qtestlitewindow.cpp | 22 ++++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitewindow.h | 3 +++ 10 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 7b49999..73c4462 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -508,6 +508,8 @@ public: static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e); static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e); + static void processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e); + static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); // static void reportScreenCount(int count); diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index ece035c..a587e8e 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -111,6 +111,9 @@ void QApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate case QWindowSystemInterfacePrivate::Leave: QApplicationPrivate::processLeaveEvent(static_cast(e)); break; + case QWindowSystemInterfacePrivate::ActivatedWindow: + QApplicationPrivate::processActivatedEvent(static_cast(e)); + break; case QWindowSystemInterfacePrivate::Close: QApplicationPrivate::processCloseEvent( static_cast(e)); @@ -823,6 +826,10 @@ void QApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::Leave } +void QApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate::ActivatedWindowEvent *e) +{ + QApplication::setActiveWindow(e->activated.data()); +} void QApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e) { diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp index 29eaa82..b6b6693 100644 --- a/src/gui/kernel/qplatformwindow_qpa.cpp +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -41,6 +41,7 @@ #include "qplatformwindow_qpa.h" +#include #include class QPlatformWindowPrivate @@ -171,6 +172,24 @@ void QPlatformWindow::setOpacity(qreal level) } /*! + Reimplement to let Qt be able to request activation/focus for a window + + Some window systems will probably not have callbacks for this functionality, + and then calling QWindowSystemInterface::handleWindowActivated(QWidget *w) + would be sufficient. + + If the window system has some event handling/callbacks then call + QWindowSystemInterface::handleWindowActivated(QWidget *w) when the window system + gives the notification. + + Default implementation calls QWindowSystem::handleWindowActivated(QWidget *w) +*/ +void QPlatformWindow::requestActivateWindow() +{ + QWindowSystemInterface::handleWindowActivated(widget()); +} + +/*! Reimplement to return the glContext associated with the window. */ QPlatformGLContext *QPlatformWindow::glContext() const diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h index 4f6fedc..abc35d1 100644 --- a/src/gui/kernel/qplatformwindow_qpa.h +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -80,6 +80,7 @@ public: virtual void lower(); virtual void setOpacity(qreal level); + virtual void requestActivateWindow(); virtual QPlatformGLContext *glContext() const; protected: diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index 617d984..1279e0a 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -379,9 +379,8 @@ QWidget *QWidget::keyboardGrabber() void QWidget::activateWindow() { - // XXX -// qDebug() << "QWidget::activateWindow" << this; - QApplication::setActiveWindow(this); //##### + if (platformWindow()) + platformWindow()->requestActivateWindow(); } void QWidgetPrivate::show_sys() @@ -409,9 +408,6 @@ void QWidgetPrivate::show_sys() } if (window) window->setVisible(true); - - if (q->isWindow() && q->windowType() != Qt::Popup && q->windowType() != Qt::ToolTip && !(q->windowFlags() & Qt::X11BypassWindowManagerHint)) - q->activateWindow(); //### QWindowSystemInterface should have callback function for when WS actually activates window. } } diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index bb29cbf..b6177b0 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -82,6 +82,12 @@ void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw) QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); } +void QWindowSystemInterface::handleWindowActivated(QWidget *tlw) +{ + QWindowSystemInterfacePrivate::ActivatedWindowEvent *e = new QWindowSystemInterfacePrivate::ActivatedWindowEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect) { if (tlw) { diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h index 1c79f2a..39c2f79 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -83,6 +83,7 @@ public: static void handleCloseEvent(QWidget *w); static void handleEnterEvent(QWidget *w); static void handleLeaveEvent(QWidget *w); + static void handleWindowActivated(QWidget *w); // Changes to the screen static void handleScreenGeometryChange(int screenIndex); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index 78e1f33..3491a1a 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -54,6 +54,7 @@ public: GeometryChange, Enter, Leave, + ActivatedWindow, Mouse, Wheel, Key, @@ -102,6 +103,14 @@ public: QWeakPointer leave; }; + class ActivatedWindowEvent : public WindowSystemEvent { + public: + ActivatedWindowEvent(QWidget *activatedWindow) + : WindowSystemEvent(ActivatedWindow), activated(activatedWindow) + { } + QWeakPointer activated; + }; + class UserEvent : public WindowSystemEvent { public: UserEvent(QWidget * w, ulong time, EventType t) diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index b52aae9..5f9d387 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -318,6 +318,16 @@ void QTestLiteWindow::handleLeaveEvent() QWindowSystemInterface::handleLeaveEvent(widget()); } +void QTestLiteWindow::handleFocusInEvent() +{ + QWindowSystemInterface::handleWindowActivated(widget()); +} + +void QTestLiteWindow::handleFocusOutEvent() +{ + QWindowSystemInterface::handleWindowActivated(0); +} + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Key event stuff -- not pretty either @@ -694,6 +704,10 @@ void QTestLiteWindow::paintEvent() surface->flush(widget(), QRect(xpos,ypos,width, height), QPoint()); } +void QTestLiteWindow::requestActivateWindow() +{ + XSetInputFocus(xd->display, x_window, XRevertToParent, CurrentTime); +} void QTestLiteWindow::resizeEvent(XConfigureEvent *e) { @@ -1456,6 +1470,14 @@ bool MyDisplay::handleEvent(XEvent *xe) xw->handleLeaveEvent(); break; + case XFocusIn: + xw->handleFocusInEvent(); + break; + + case XFocusOut: + xw->handleFocusOutEvent(); + break; + default: #ifdef MYX11_DEBUG qDebug() << hex << xe->xany.window << "Other X event" << xe->type; diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index dc628f1..69442f1 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -109,10 +109,13 @@ public: void handleCloseEvent(); void handleEnterEvent(); void handleLeaveEvent(); + void handleFocusInEvent(); + void handleFocusOutEvent(); void resizeEvent(XConfigureEvent *configure_event); void paintEvent(); + void requestActivateWindow(); void setGeometry(const QRect &rect); -- cgit v0.12 From f6c5b16768d45f196bab0a2766d4be6027991e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 8 Dec 2010 13:09:36 +0100 Subject: Add function QPlatformScreen::platformScreenForWidget This so there is some logical connection between what screen a widget belongs to --- src/gui/kernel/qdesktopwidget_qpa_p.h | 8 ++++++- src/gui/kernel/qplatformscreen_qpa.cpp | 15 ++++++++++++++ src/gui/kernel/qplatformscreen_qpa.h | 4 ++++ src/gui/kernel/qwidget.cpp | 5 ++--- src/gui/kernel/qwidget_p.h | 5 ++--- src/gui/kernel/qwidget_qpa.cpp | 38 ++++++---------------------------- 6 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/gui/kernel/qdesktopwidget_qpa_p.h b/src/gui/kernel/qdesktopwidget_qpa_p.h index 8bed09d..47ccca2 100644 --- a/src/gui/kernel/qdesktopwidget_qpa_p.h +++ b/src/gui/kernel/qdesktopwidget_qpa_p.h @@ -59,7 +59,13 @@ class QDesktopScreenWidget : public QWidget { Q_OBJECT public: - QDesktopScreenWidget(int screenNumber = -1) { setWindowFlags(Qt::Desktop); setVisible(false); d_func()->screenNumber = screenNumber; } + QDesktopScreenWidget(int screenNumber = -1) + { + setWindowFlags(Qt::Desktop); + setVisible(false); + QTLWExtra *topData = d_func()->topData(); + topData->screenIndex = screenNumber; + } }; class QDesktopWidgetPrivate : public QWidgetPrivate { diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp index 5e80ba8..118835f 100644 --- a/src/gui/kernel/qplatformscreen_qpa.cpp +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -41,7 +41,11 @@ #include "qplatformscreen_qpa.h" #include +#include #include +#include +#include +#include /*! Return the given top level widget for a given position. @@ -77,6 +81,17 @@ QSize QPlatformScreen::physicalSize() const return QSize(width,height); } +Q_GUI_EXPORT extern QWidgetPrivate *qt_widget_private(QWidget *widget); +QPlatformScreen * QPlatformScreen::platformScreenForWidget(const QWidget *widget) +{ + QWidget *window = widget->window(); + QWidgetPrivate *windowPrivate = qt_widget_private(window); + QTLWExtra * topData = windowPrivate->topData(); + QPlatformIntegration *integration = + QApplicationPrivate::platformIntegration(); + return integration->screens()[topData->screenIndex]; +} + /*! \class QPlatformScreen \since 4.8 diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h index 9080489..1f52764 100644 --- a/src/gui/kernel/qplatformscreen_qpa.h +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -73,6 +73,10 @@ public: //jl: should setDirty be removed. virtual void setDirty(const QRect &) {} virtual QWidget *topLevelAt(const QPoint &point) const; + + //jl: should this function be in QPlatformIntegration + //jl: maybe screenForWidget is a better name? + static QPlatformScreen *platformScreenForWidget(const QWidget *widget); }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 16f64ff..6a6a218 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -303,8 +303,6 @@ QWidgetPrivate::QWidgetPrivate(int version) , hasAlienChildren(0) , window_event(0) , qd_hd(0) -#elif defined (Q_WS_QPA) - , screenNumber(0) #endif { if (!qApp) { @@ -1277,7 +1275,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) } #elif defined(Q_WS_QPA) if (desktopWidget) { - int screen = desktopWidget->d_func()->screenNumber; + int screen = desktopWidget->d_func()->topData()->screenIndex; QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); platform->moveToScreen(q, screen); } @@ -1729,6 +1727,7 @@ void QWidgetPrivate::createTLExtra() #if defined(Q_WS_QPA) x->platformWindow = 0; x->platformWindowFormat = QPlatformWindowFormat::defaultFormat(); + x->screenIndex = 0; #endif } } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 6b85391..a0f0ec8 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -233,6 +233,7 @@ struct QTLWExtra { #elif defined(Q_WS_QPA) QPlatformWindow *platformWindow; QPlatformWindowFormat platformWindowFormat; + quint32 screenIndex; // index in qplatformscreenlist #endif }; @@ -885,11 +886,9 @@ public: void updateCursor() const; #endif QScreen* getScreen() const; -#elif defined(Q_WS_QPA) +#elif defined(Q_WS_QPA) // <--------------------------------------------------------- QPA void setMaxWindowState_helper(); void setFullScreenSize_helper(); - - int screenNumber; // screen the widget should be displayed on #ifndef QT_NO_CURSOR void updateCursor() const; #endif diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index 1279e0a..24ab8f7 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -53,7 +53,6 @@ #include QT_BEGIN_NAMESPACE -static QPlatformScreen *qt_screenForWidget(const QWidget *w); void q_createNativeChildrenAndSetParent(QPlatformWindow *parentWindow, const QWidget *parentWidget) { @@ -122,7 +121,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } - QApplicationPrivate::platformIntegration()->moveToScreen(q, screenNumber); + QApplicationPrivate::platformIntegration()->moveToScreen(q, topData()->screenIndex); // qDebug() << "create_sys" << q << q->internalWinId(); } @@ -173,7 +172,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) // programmer specified desktop widget // get the desktop's screen number - targetScreen = newparent->d_func()->screenNumber; + targetScreen = newparent->window()->d_func()->topData()->screenIndex; newparent = 0; } @@ -192,7 +191,7 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) f |= Qt::Window; if (targetScreen == -1) { if (parent) - targetScreen = qobject_cast(parent)->d_func()->screenNumber; + targetScreen = q->parentWidget()->window()->d_func()->topData()->screenIndex; } } @@ -228,7 +227,8 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) // move the window to the selected screen if (!newparent && targetScreen != -1) { - screenNumber = targetScreen; + if (maybeTopData()) + maybeTopData()->screenIndex = targetScreen; // only if it is already created if (q->testAttribute(Qt::WA_WState_Created)) { QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); @@ -643,37 +643,11 @@ void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) scrollRect(r, dx, dy); } -static QPlatformScreen *qt_screenForWidget(const QWidget *w) -{ - if (!w) - return 0; - QRect frame = w->frameGeometry(); - if (!w->isWindow()) - frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); - const QPoint p = (frame.topLeft() + frame.bottomRight()) / 2; - - QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); - QList screens = pi->screens(); - - for (int i = 0; i < screens.size(); ++i) { - if (screens[i]->geometry().contains(p)) - return screens[i]; - } - - // Assume screen zero if we have it. - if (!screens.isEmpty()) - return screens[0]; - else - qWarning("qt_screenForWidget: no screens"); - - return 0; -} - int QWidget::metric(PaintDeviceMetric m) const { Q_D(const QWidget); - QPlatformScreen *screen = qt_screenForWidget(this); + QPlatformScreen *screen = QPlatformScreen::platformScreenForWidget(this); if (!screen) { if (m == PdmDpiX || m == PdmDpiY) return 72; -- cgit v0.12 From 337f75854883fb93e1b4f41e10c79dc7c352f4a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Wed, 8 Dec 2010 13:11:30 +0100 Subject: Refactoring of testlite to conform with Lighthouse structure --- src/plugins/platforms/testlite/qglxintegration.cpp | 75 +- src/plugins/platforms/testlite/qglxintegration.h | 18 +- src/plugins/platforms/testlite/qtestlitecursor.cpp | 200 +++++ src/plugins/platforms/testlite/qtestlitecursor.h | 69 ++ .../platforms/testlite/qtestliteintegration.cpp | 65 +- .../platforms/testlite/qtestliteintegration.h | 29 +- src/plugins/platforms/testlite/qtestlitescreen.cpp | 430 ++++++++++ src/plugins/platforms/testlite/qtestlitescreen.h | 103 +++ src/plugins/platforms/testlite/qtestlitewindow.cpp | 871 ++------------------- src/plugins/platforms/testlite/qtestlitewindow.h | 96 +-- .../platforms/testlite/qtestlitewindowsurface.cpp | 34 +- .../platforms/testlite/qtestlitewindowsurface.h | 2 +- src/plugins/platforms/testlite/testlite.pro | 9 +- 13 files changed, 1005 insertions(+), 996 deletions(-) create mode 100644 src/plugins/platforms/testlite/qtestlitecursor.cpp create mode 100644 src/plugins/platforms/testlite/qtestlitecursor.h create mode 100644 src/plugins/platforms/testlite/qtestlitescreen.cpp create mode 100644 src/plugins/platforms/testlite/qtestlitescreen.h diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/testlite/qglxintegration.cpp index a4b7b69..1dffb3e 100644 --- a/src/plugins/platforms/testlite/qglxintegration.cpp +++ b/src/plugins/platforms/testlite/qglxintegration.cpp @@ -44,6 +44,7 @@ #include #include "qtestlitewindow.h" +#include "qtestlitescreen.h" #include #include @@ -57,9 +58,9 @@ QT_BEGIN_NAMESPACE -QMutex QGLXGLContext::m_defaultSharedContextMutex(QMutex::Recursive); +QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); -QVector QGLXGLContext::buildSpec(const QPlatformWindowFormat &format) +QVector QGLXContext::buildSpec(const QPlatformWindowFormat &format) { QVector spec(48); int i = 0; @@ -111,7 +112,7 @@ QVector QGLXGLContext::buildSpec(const QPlatformWindowFormat &format) return spec; } -GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindowFormat &format) +GLXFBConfig QGLXContext::findConfig(const QTestLiteScreen *screen, const QPlatformWindowFormat &format) { bool reduced = true; GLXFBConfig chosenConfig = 0; @@ -120,7 +121,7 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow QVector spec = buildSpec(reducedFormat); int confcount = 0; GLXFBConfig *configs; - configs = glXChooseFBConfig(xd->display,xd->screen,spec.constData(),&confcount); + configs = glXChooseFBConfig(screen->display(),screen->xScreenNumber(),spec.constData(),&confcount); if (confcount) { for (int i = 0; i < confcount; i++) { @@ -128,7 +129,7 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow // Make sure we try to get an ARGB visual if the format asked for an alpha: if (reducedFormat.alpha()) { int alphaSize; - glXGetFBConfigAttrib(xd->display,configs[i],GLX_ALPHA_SIZE,&alphaSize); + glXGetFBConfigAttrib(screen->display(),configs[i],GLX_ALPHA_SIZE,&alphaSize); if (alphaSize > 0) break; } else { @@ -147,14 +148,14 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow return chosenConfig; } -XVisualInfo *QGLXGLContext::findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format) +XVisualInfo *QGLXContext::findVisualInfo(const QTestLiteScreen *screen, const QPlatformWindowFormat &format) { - GLXFBConfig config = QGLXGLContext::findConfig(xd,format); - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + GLXFBConfig config = QGLXContext::findConfig(screen,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display(),config); return visualInfo; } -QPlatformWindowFormat QGLXGLContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) { QPlatformWindowFormat format; int redSize = 0; @@ -210,7 +211,7 @@ QPlatformWindowFormat QGLXGLContext::platformWindowFromGLXFBConfig(Display *disp return format; } -QPlatformWindowFormat QGLXGLContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) { QPlatformWindowFormat retFormat = format; *reduced = true; @@ -235,9 +236,9 @@ QPlatformWindowFormat QGLXGLContext::reducePlatformWindowFormat(const QPlatformW return retFormat; } -QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format) +QGLXContext::QGLXContext(Window window, QTestLiteScreen *screen, const QPlatformWindowFormat &format) : QPlatformGLContext() - , m_xd(xd) + , m_screen(screen) , m_drawable((Drawable)window) , m_context(0) { @@ -246,7 +247,7 @@ QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindow if (format.useDefaultSharedContext()) { if (!QPlatformGLContext::defaultSharedContext()) { if (m_defaultSharedContextMutex.tryLock()){ - createDefaultSharedContex(xd); + createDefaultSharedContex(screen); m_defaultSharedContextMutex.unlock(); } else { m_defaultSharedContextMutex.lock(); //wait to the the shared context is created @@ -259,32 +260,32 @@ QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindow } GLXContext shareGlxContext = 0; if (sharePlatformContext) - shareGlxContext = static_cast(sharePlatformContext)->glxContext(); + shareGlxContext = static_cast(sharePlatformContext)->glxContext(); - GLXFBConfig config = findConfig(xd,format); - m_context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,shareGlxContext,TRUE); - m_windowFormat = QGLXGLContext::platformWindowFromGLXFBConfig(xd->display,config,m_context); + GLXFBConfig config = findConfig(screen,format); + m_context = glXCreateNewContext(screen->display(),config,GLX_RGBA_TYPE,shareGlxContext,TRUE); + m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(screen->display(),config,m_context); #ifdef MYX11_DEBUG qDebug() << "QGLXGLContext::create context" << m_context; #endif } -QGLXGLContext::QGLXGLContext(MyDisplay *display, Drawable drawable, GLXContext context) - : QPlatformGLContext(), m_xd(display), m_drawable(drawable), m_context(context) +QGLXContext::QGLXContext(QTestLiteScreen *screen, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_screen(screen), m_drawable(drawable), m_context(context) { } -QGLXGLContext::~QGLXGLContext() +QGLXContext::~QGLXContext() { if (m_context) { qDebug("Destroying GLX context 0x%p", m_context); - glXDestroyContext(m_xd->display, m_context); + glXDestroyContext(m_screen->display(), m_context); } } -void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) +void QGLXContext::createDefaultSharedContex(QTestLiteScreen *screen) { int x = 0; int y = 0; @@ -293,45 +294,45 @@ void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); GLXContext context; - GLXFBConfig config = findConfig(xd,format); + GLXFBConfig config = findConfig(screen,format); if (config) { - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); - Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display(),config); + Colormap cmap = XCreateColormap(screen->display(),screen->rootWindow(),visualInfo->visual,AllocNone); XSetWindowAttributes a; a.colormap = cmap; - Window sharedWindow = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, + Window sharedWindow = XCreateWindow(screen->display(), screen->rootWindow(),x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWColormap, &a); - context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,0,TRUE); - QPlatformGLContext *sharedContext = new QGLXGLContext(xd,sharedWindow,context); + context = glXCreateNewContext(screen->display(),config,GLX_RGBA_TYPE,0,TRUE); + QPlatformGLContext *sharedContext = new QGLXContext(screen,sharedWindow,context); QPlatformGLContext::setDefaultSharedContext(sharedContext); } else { qWarning("Warning no shared context created"); } } -void QGLXGLContext::makeCurrent() +void QGLXContext::makeCurrent() { QPlatformGLContext::makeCurrent(); #ifdef MYX11_DEBUG qDebug("QGLXGLContext::makeCurrent(window=0x%x, ctx=0x%x)", m_drawable, m_context); #endif - glXMakeCurrent(m_xd->display, m_drawable, m_context); + glXMakeCurrent(m_screen->display(), m_drawable, m_context); } -void QGLXGLContext::doneCurrent() +void QGLXContext::doneCurrent() { QPlatformGLContext::doneCurrent(); - glXMakeCurrent(m_xd->display, 0, 0); + glXMakeCurrent(m_screen->display(), 0, 0); } -void QGLXGLContext::swapBuffers() +void QGLXContext::swapBuffers() { - glXSwapBuffers(m_xd->display, m_drawable); + glXSwapBuffers(m_screen->display(), m_drawable); } -void* QGLXGLContext::getProcAddress(const QString& procName) +void* QGLXContext::getProcAddress(const QString& procName) { typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; @@ -340,7 +341,7 @@ void* QGLXGLContext::getProcAddress(const QString& procName) if (resolved && !glXGetProcAddressARB) return 0; if (!glXGetProcAddressARB) { - QList glxExt = QByteArray(glXGetClientString(m_xd->display, GLX_EXTENSIONS)).split(' '); + QList glxExt = QByteArray(glXGetClientString(m_screen->display(), GLX_EXTENSIONS)).split(' '); if (glxExt.contains("GLX_ARB_get_proc_address")) { #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) void *handle = dlopen(NULL, RTLD_LAZY); @@ -364,7 +365,7 @@ void* QGLXGLContext::getProcAddress(const QString& procName) return glXGetProcAddressARB(reinterpret_cast(procName.toLatin1().data())); } -QPlatformWindowFormat QGLXGLContext::platformWindowFormat() const +QPlatformWindowFormat QGLXContext::platformWindowFormat() const { return m_windowFormat; } diff --git a/src/plugins/platforms/testlite/qglxintegration.h b/src/plugins/platforms/testlite/qglxintegration.h index e17790e..5ae0b2a 100644 --- a/src/plugins/platforms/testlite/qglxintegration.h +++ b/src/plugins/platforms/testlite/qglxintegration.h @@ -53,13 +53,11 @@ QT_BEGIN_NAMESPACE -class MyDisplay; - -class QGLXGLContext : public QPlatformGLContext +class QGLXContext : public QPlatformGLContext { public: - QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format); - ~QGLXGLContext(); + QGLXContext(Window window, QTestLiteScreen *xd, const QPlatformWindowFormat &format); + ~QGLXContext(); virtual void makeCurrent(); virtual void doneCurrent(); @@ -70,22 +68,22 @@ public: QPlatformWindowFormat platformWindowFormat() const; - static XVisualInfo *findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format); + static XVisualInfo *findVisualInfo(const QTestLiteScreen *xd, const QPlatformWindowFormat &format); private: - static GLXFBConfig findConfig(const MyDisplay *xd,const QPlatformWindowFormat &format); + static GLXFBConfig findConfig(const QTestLiteScreen *xd,const QPlatformWindowFormat &format); static QVector buildSpec(const QPlatformWindowFormat &format); static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); - MyDisplay *m_xd; + QTestLiteScreen *m_screen; Drawable m_drawable; GLXContext m_context; QPlatformWindowFormat m_windowFormat; - QGLXGLContext (MyDisplay *display, Drawable drawable, GLXContext context); + QGLXContext (QTestLiteScreen *screen, Drawable drawable, GLXContext context); static QMutex m_defaultSharedContextMutex; - static void createDefaultSharedContex(MyDisplay *xd); + static void createDefaultSharedContex(QTestLiteScreen *xd); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitecursor.cpp b/src/plugins/platforms/testlite/qtestlitecursor.cpp new file mode 100644 index 0000000..4f3f0cb --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitecursor.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtestlitecursor.h" + +#include "qtestliteintegration.h" +#include "qtestlitescreen.h" +#include "qtestlitewindow.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +QTestLiteCursor::QTestLiteCursor(QTestLiteScreen *screen) + : QPlatformCursor(screen) +{ +} + +void QTestLiteCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + QTestLiteWindow *w = 0; + if (widget) { + QWidget *window = widget->window(); + w = static_cast(window->platformWindow()); + } else { + // No X11 cursor control when there is no widget under the cursor + return; + } + + if (!w) + return; + + int id = cursor->handle(); + if (id == currentCursor) + return; + Cursor c; + if (!cursorMap.contains(id)) { + if (cursor->shape() == Qt::BitmapCursor) + c = createCursorBitmap(cursor); + else + c = createCursorShape(cursor->shape()); + if (!c) { + return; + } + cursorMap.insert(id, c); + } else { + c = cursorMap.value(id); + } + + w->setCursor(c); +} + +Cursor QTestLiteCursor::createCursorBitmap(QCursor * cursor) +{ + XColor bg, fg; + bg.red = 255 << 8; + bg.green = 255 << 8; + bg.blue = 255 << 8; + fg.red = 0; + fg.green = 0; + fg.blue = 0; + QPoint spot = cursor->hotSpot(); + Window rootwin = testLiteScreen()->rootWindow(); + + QImage mapImage = cursor->bitmap()->toImage().convertToFormat(QImage::Format_MonoLSB); + QImage maskImage = cursor->mask()->toImage().convertToFormat(QImage::Format_MonoLSB); + + int width = cursor->bitmap()->width(); + int height = cursor->bitmap()->height(); + int bytesPerLine = mapImage.bytesPerLine(); + int destLineSize = width / 8; + if (width % 8) + destLineSize++; + + const uchar * map = mapImage.bits(); + const uchar * mask = maskImage.bits(); + + char * mapBits = new char[height * destLineSize]; + char * maskBits = new char[height * destLineSize]; + for (int i = 0; i < height; i++) { + memcpy(mapBits + (destLineSize * i),map + (bytesPerLine * i), destLineSize); + memcpy(maskBits + (destLineSize * i),mask + (bytesPerLine * i), destLineSize); + } + + Pixmap cp = XCreateBitmapFromData(testLiteScreen()->display(), rootwin, mapBits, width, height); + Pixmap mp = XCreateBitmapFromData(testLiteScreen()->display(), rootwin, maskBits, width, height); + Cursor c = XCreatePixmapCursor(testLiteScreen()->display(), cp, mp, &fg, &bg, spot.x(), spot.y()); + XFreePixmap(testLiteScreen()->display(), cp); + XFreePixmap(testLiteScreen()->display(), mp); + delete[] mapBits; + delete[] maskBits; + + return c; +} + +Cursor QTestLiteCursor::createCursorShape(int cshape) +{ + Cursor cursor = 0; + + if (cshape < 0 || cshape > Qt::LastCursor) + return 0; + + switch (cshape) { + case Qt::ArrowCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_left_ptr); + break; + case Qt::UpArrowCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_center_ptr); + break; + case Qt::CrossCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_crosshair); + break; + case Qt::WaitCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_watch); + break; + case Qt::IBeamCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_xterm); + break; + case Qt::SizeAllCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_fleur); + break; + case Qt::PointingHandCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_hand2); + break; + case Qt::SizeBDiagCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_top_right_corner); + break; + case Qt::SizeFDiagCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_bottom_right_corner); + break; + case Qt::SizeVerCursor: + case Qt::SplitVCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_sb_v_double_arrow); + break; + case Qt::SizeHorCursor: + case Qt::SplitHCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_sb_h_double_arrow); + break; + case Qt::WhatsThisCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_question_arrow); + break; + case Qt::ForbiddenCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_circle); + break; + case Qt::BusyCursor: + cursor = XCreateFontCursor(testLiteScreen()->display(), XC_watch); + break; + + default: //default cursor for all the rest + break; + } + return cursor; +} + +QTestLiteScreen * QTestLiteCursor::testLiteScreen() const +{ + return static_cast(screen); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitecursor.h b/src/plugins/platforms/testlite/qtestlitecursor.h new file mode 100644 index 0000000..15a5b2a --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitecursor.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITECURSOR_H +#define QTESTLITECURSOR_H + +#include + +#include "qtestliteintegration.h" + +QT_BEGIN_NAMESPACE + +class QTestLiteCursor : QPlatformCursor +{ +public: + QTestLiteCursor(QTestLiteScreen *screen); + + void changeCursor(QCursor * cursor, QWidget * widget); +private: + + Cursor createCursorBitmap(QCursor * cursor); + Cursor createCursorShape(int cshape); + + QTestLiteScreen *testLiteScreen() const; + int currentCursor; + QMap cursorMap; +}; + +QT_END_NAMESPACE + +#endif // QTESTLITECURSOR_H diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp index 68e9051..fc2a89c 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -39,17 +39,14 @@ ** ****************************************************************************/ - - #include "qtestliteintegration.h" #include "qtestlitewindowsurface.h" #include #include -#include - #include "qtestlitewindow.h" #include "qgenericunixfontdatabase.h" +#include "qtestlitescreen.h" #ifndef QT_NO_OPENGL #include @@ -59,50 +56,13 @@ QT_BEGIN_NAMESPACE -class MyCursor : QPlatformCursor -{ -public: - MyCursor(QPlatformScreen *screen) : QPlatformCursor(screen) {} - - void changeCursor(QCursor * cursor, QWidget * widget) { - QTestLiteWindow *w = 0; - if (widget) { - QWidget *window = widget->window(); - w = static_cast(window->platformWindow()); - } else { - // No X11 cursor control when there is no widget under the cursor - return; - } - - //qDebug() << "changeCursor" << widget << ws; - if (!w) - return; - - w->setCursor(cursor); - } -}; - QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) : mUseOpenGL(useOpenGL) , mFontDb(new QGenericUnixFontDatabase()) { - xd = new MyDisplay; - mPrimaryScreen = new QTestLiteScreen(); - - mPrimaryScreen->mGeometry = QRect - (0, 0, xd->width, xd->height); - mPrimaryScreen->mDepth = 32; - mPrimaryScreen->mFormat = QImage::Format_RGB32; - mPrimaryScreen->mPhysicalSize = - QSize(xd->physicalWidth, xd->physicalHeight); - mScreens.append(mPrimaryScreen); - - - (void)new MyCursor(mPrimaryScreen); - } QPixmapData *QTestLiteIntegration::createPixmapData(QPixmapData::PixelType type) const @@ -120,21 +80,33 @@ QWindowSurface *QTestLiteIntegration::createWindowSurface(QWidget *widget, WId) if (mUseOpenGL) return new QGLWindowSurface(widget); #endif - return new QTestLiteWindowSurface(mPrimaryScreen, widget); + return new QTestLiteWindowSurface(widget); } QPlatformWindow *QTestLiteIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const { - return new QTestLiteWindow(this, mPrimaryScreen, widget); + return new QTestLiteWindow(widget); } QPixmap QTestLiteIntegration::grabWindow(WId window, int x, int y, int width, int height) const { - QImage img = xd->grabWindow(window, x, y, width, height); - return QPixmap::fromImage(img); + QImage image; + QWidget *widget = QWidget::find(window); + if (widget) { + QTestLiteScreen *screen = QTestLiteScreen::testLiteScreenForWidget(widget); + image = screen->grabWindow(window,x,y,width,height); + } else { + for (int i = 0; i < mScreens.size(); i++) { + QTestLiteScreen *screen = static_cast(mScreens[i]); + if (screen->rootWindow() == window) { + image = screen->grabWindow(window,x,y,width,height); + } + } + } + return QPixmap::fromImage(image); } QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const @@ -145,7 +117,8 @@ QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const bool QTestLiteIntegration::hasOpenGL() const { #ifndef QT_NO_OPENGL - return glXQueryExtension(xd->display, 0, 0) != 0; + QTestLiteScreen *screen = static_cast(mScreens.at(0)); + return glXQueryExtension(screen->display(), 0, 0) != 0; #endif return false; } diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h index 8286ef0..37d09f5 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.h +++ b/src/plugins/platforms/testlite/qtestliteintegration.h @@ -42,34 +42,17 @@ #ifndef QGRAPHICSSYSTEM_TESTLITE_H #define QGRAPHICSSYSTEM_TESTLITE_H -#include -#include - //make sure textstream is included before any X11 headers #include -QT_BEGIN_NAMESPACE +#include +#include -class MyDisplay; +#include -class QTestLiteScreen : public QPlatformScreen -{ -public: - QTestLiteScreen() - : mDepth(16), mFormat(QImage::Format_RGB16) {} - ~QTestLiteScreen() {} - - QRect geometry() const { return mGeometry; } - int depth() const { return mDepth; } - QImage::Format format() const { return mFormat; } - QSize physicalSize() const { return mPhysicalSize; } +QT_BEGIN_NAMESPACE -public: - QRect mGeometry; - int mDepth; - QImage::Format mFormat; - QSize mPhysicalSize; -}; +class QTestLiteScreen; class QTestLiteIntegration : public QPlatformIntegration { @@ -88,8 +71,6 @@ public: bool hasOpenGL() const; - MyDisplay *xd; - private: bool mUseOpenGL; QTestLiteScreen *mPrimaryScreen; diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp new file mode 100644 index 0000000..919506e --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp @@ -0,0 +1,430 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtestlitescreen.h" + +#include "qtestlitecursor.h" +#include "qtestlitewindow.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); +static bool seen_badwindow; + +static int qt_x_errhandler(Display *dpy, XErrorEvent *err) +{ + +qDebug() << "qt_x_errhandler" << err->error_code; + + switch (err->error_code) { + case BadAtom: +#if 0 + if (err->request_code == 20 /* X_GetProperty */ + && (err->resourceid == XA_RESOURCE_MANAGER + || err->resourceid == XA_RGB_DEFAULT_MAP + || err->resourceid == ATOM(_NET_SUPPORTED) + || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) + || err->resourceid == ATOM(KDE_FULL_SESSION) + || err->resourceid == ATOM(KWIN_RUNNING) + || err->resourceid == ATOM(XdndProxy) + || err->resourceid == ATOM(XdndAware)) + + + ) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } +#endif + qDebug() << "BadAtom"; + break; + + case BadWindow: + if (err->request_code == 2 /* X_ChangeWindowAttributes */ + || err->request_code == 38 /* X_QueryPointer */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } + } + seen_badwindow = true; + if (err->request_code == 25 /* X_SendEvent */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } +#if 0 + if (X11->xdndHandleBadwindow()) { + qDebug("xdndHandleBadwindow returned true"); + return 0; + } +#endif + } +#if 0 + if (X11->ignore_badwindow) + return 0; +#endif + break; + + case BadMatch: + if (err->request_code == 42 /* X_SetInputFocus */) + return 0; + break; + + default: +#if 0 //!defined(QT_NO_XINPUT) + if (err->request_code == X11->xinput_major + && err->error_code == (X11->xinput_errorbase + XI_BadDevice) + && err->minor_code == 3 /* X_OpenDevice */) { + return 0; + } +#endif + break; + } + + char errstr[256]; + XGetErrorText( dpy, err->error_code, errstr, 256 ); + char buffer[256]; + char request_str[256]; + qsnprintf(buffer, 256, "%d", err->request_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); + if (err->request_code < 128) { + // X error for a normal protocol request + qWarning( "X Error: %s %d\n" + " Major opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + request_str, + err->resourceid ); + } else { + // X error for an extension request + const char *extensionName = 0; +#if 0 + if (err->request_code == X11->xrender_major) + extensionName = "RENDER"; + else if (err->request_code == X11->xrandr_major) + extensionName = "RANDR"; + else if (err->request_code == X11->xinput_major) + extensionName = "XInputExtension"; + else if (err->request_code == X11->mitshm_major) + extensionName = "MIT-SHM"; +#endif + char minor_str[256]; + if (extensionName) { + qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); + } else { + extensionName = "Uknown extension"; + qsnprintf(minor_str, 256, "Unknown request"); + } + qWarning( "X Error: %s %d\n" + " Extension: %d (%s)\n" + " Minor opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + extensionName, + err->minor_code, + minor_str, + err->resourceid ); + } + + // ### we really should distinguish between severe, non-severe and + // ### application specific errors + + return 0; +} + +QTestLiteScreen::QTestLiteScreen() + : mFormat(QImage::Format_RGB32) + , mWmProtocolsAtom(0) + , mWmDeleteWindowAtom(0) +{ + char *display_name = getenv("DISPLAY"); + mDisplay = XOpenDisplay(display_name); + if (!mDisplay) { + fprintf(stderr, "Cannot connect to X server: %s\n", + display_name); + exit(1); + } + +#ifndef DONT_USE_MIT_SHM + Status MIT_SHM_extension_supported = XShmQueryExtension (mDisplay); + Q_ASSERT(MIT_SHM_extension_supported == True); +#endif + original_x_errhandler = XSetErrorHandler(qt_x_errhandler); + + if (qgetenv("DO_X_SYNCHRONIZE").toInt()) + XSynchronize(mDisplay, true); + + mScreen = DefaultScreen(mDisplay); + int width = DisplayWidth(mDisplay, mScreen); + int height = DisplayHeight(mDisplay, mScreen); + mGeometry = QRect(0,0,width,height); + + int physicalWidth = DisplayWidthMM(mDisplay, mScreen); + int physicalHeight = DisplayHeightMM(mDisplay, mScreen); + mPhysicalSize = QSize(physicalWidth,physicalHeight); + + int xSocketNumber = XConnectionNumber(mDisplay); + + mDepth = DefaultDepth(mDisplay,mScreen); +#ifdef MYX11_DEBUG + qDebug() << "X socket:"<< xSocketNumber; +#endif + QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); + connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + mWmProtocolsAtom = XInternAtom (mDisplay, "WM_PROTOCOLS", False); + mWmDeleteWindowAtom = XInternAtom (mDisplay, "WM_DELETE_WINDOW", False); + + mWmMotifHintAtom = XInternAtom(mDisplay, "_MOTIF_WM_HINTS\0", False); + + mCursor = new QTestLiteCursor(this); +} + +QTestLiteScreen::~QTestLiteScreen() +{ + delete mCursor; + XCloseDisplay(mDisplay); +} + +#ifdef KeyPress +#undef KeyPress +#endif +#ifdef KeyRelease +#undef KeyRelease +#endif + +//Q_GUI_EXPORT extern Atom wmProtocolsAtom; +//Q_GUI_EXPORT extern Atom wmDeleteWindowAtom; + +bool QTestLiteScreen::handleEvent(XEvent *xe) +{ + int quit = false; + QTestLiteWindow *xw = 0; + QWidget *widget = QWidget::find(xe->xany.window); + if (widget) { + xw = static_cast(widget->platformWindow()); + } + if (!xw) { +#ifdef MYX11_DEBUG + qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type; +#endif + return quit; + } + + switch (xe->type) { + + case ClientMessage: + if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom()) { + Atom a = xe->xclient.data.l[0]; + if (a == wmDeleteWindowAtom()) + xw->handleCloseEvent(); +#ifdef MYX11_DEBUG + qDebug() << "ClientMessage WM_PROTOCOLS" << a; +#endif + } +#ifdef MYX11_DEBUG + else + qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type; +#endif + break; + + case Expose: + if (xw) + if (xe->xexpose.count == 0) + xw->paintEvent(); + break; + case ConfigureNotify: + if (xw) + xw->resizeEvent(&xe->xconfigure); + break; + + case ButtonPress: + xw->mousePressEvent(&xe->xbutton); + break; + + case ButtonRelease: + xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); + break; + + case MotionNotify: + xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); + break; + + case XKeyPress: + xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); + break; + + case XKeyRelease: + xw->handleKeyEvent(QEvent::KeyRelease, &xe->xkey); + break; + + case EnterNotify: + xw->handleEnterEvent(); + break; + + case LeaveNotify: + xw->handleLeaveEvent(); + break; + + case XFocusIn: + xw->handleFocusInEvent(); + break; + + case XFocusOut: + xw->handleFocusOutEvent(); + break; + + default: +#ifdef MYX11_DEBUG + qDebug() << hex << xe->xany.window << "Other X event" << xe->type; +#endif + break; + } + return quit; +} + +void QTestLiteScreen::eventDispatcher() +{ + ulong marker = XNextRequest(mDisplay); + // int i = 0; + while (XPending(mDisplay)) { + XEvent event; + XNextEvent(mDisplay, &event); + /* done = */ + handleEvent(&event); + + if (event.xany.serial >= marker) { + #ifdef MYX11_DEBUG + qDebug() << "potential livelock averted"; + #endif + #if 0 + if (XEventsQueued(mDisplay, QueuedAfterFlush)) { + qDebug() << " with events queued"; + QTimer::singleShot(0, this, SLOT(eventDispatcher())); + } + #endif + break; + } + } +} + +QImage QTestLiteScreen::grabWindow(Window window, int x, int y, int w, int h) +{ + if (w == 0 || h ==0) + return QImage(); + + //WinId 0 means the desktop widget + if (!window) + window = rootWindow(); + + XWindowAttributes window_attr; + if (!XGetWindowAttributes(mDisplay, window, &window_attr)) + return QImage(); + + if (w < 0) + w = window_attr.width - x; + if (h < 0) + h = window_attr.height - y; + + // Ideally, we should also limit ourselves to the screen area, but the Qt docs say + // that it's "unsafe" to go outside the screen, so we can ignore that problem. + + //We're definitely not optimizing for speed... + XImage *xi = XGetImage(mDisplay, window, x, y, w, h, AllPlanes, ZPixmap); + + if (!xi) + return QImage(); + + //taking a copy to make sure we have ownership -- not fast + QImage result = QImage( (uchar*) xi->data, xi->width, xi->height, xi->bytes_per_line, QImage::Format_RGB32 ).copy(); + + XDestroyImage(xi); + + return result; +} + +QTestLiteScreen * QTestLiteScreen::testLiteScreenForWidget(QWidget *widget) +{ + QPlatformScreen *platformScreen = platformScreenForWidget(widget); + return static_cast(platformScreen); +} + +Display * QTestLiteScreen::display() const +{ + return mDisplay; +} + +int QTestLiteScreen::xScreenNumber() const +{ + return mScreen; +} + +Atom QTestLiteScreen::wmProtocolsAtom() const +{ + return mWmProtocolsAtom; +} + +Atom QTestLiteScreen::wmDeleteWindowAtom() const +{ + return mWmDeleteWindowAtom; +} + +void QTestLiteScreen::setWmDeleteWindowAtom(Atom newDeleteWindowAtom) +{ + mWmDeleteWindowAtom = newDeleteWindowAtom; +} + +Atom QTestLiteScreen::atomForMotifWmHints() const +{ + return mWmMotifHintAtom; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitescreen.h b/src/plugins/platforms/testlite/qtestlitescreen.h new file mode 100644 index 0000000..f8d9468 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitescreen.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITESCREEN_H +#define QTESTLITESCREEN_H + +#include +#include "qtestliteintegration.h" + +QT_BEGIN_NAMESPACE + +class QTestLiteCursor; + +class QTestLiteScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QTestLiteScreen(); + + ~QTestLiteScreen(); + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + + Window rootWindow() { return RootWindow(mDisplay, mScreen); } + unsigned long blackPixel() { return BlackPixel(mDisplay, mScreen); } + unsigned long whitePixel() { return WhitePixel(mDisplay, mScreen); } + + bool handleEvent(XEvent *xe); + QImage grabWindow(Window window, int x, int y, int w, int h); + + static QTestLiteScreen *testLiteScreenForWidget(QWidget *widget); + + Display *display() const; + int xScreenNumber() const; + + Atom wmProtocolsAtom() const; + Atom wmDeleteWindowAtom() const; + void setWmDeleteWindowAtom(Atom newDeleteWindowAtom); + + Atom atomForMotifWmHints() const; + + +public slots: + void eventDispatcher(); + +private: + QRect mGeometry; + QSize mPhysicalSize; + int mDepth; + QImage::Format mFormat; + QTestLiteCursor *mCursor; + + Display * mDisplay; + int mScreen; + Atom mWmProtocolsAtom; + Atom mWmDeleteWindowAtom; + Atom mWmMotifHintAtom; +}; + +QT_END_NAMESPACE + +#endif // QTESTLITESCREEN_H diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 5f9d387..f8f4a5f 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -39,169 +39,81 @@ ** ****************************************************************************/ -#include "qtestliteintegration.h" -#include -#include -#include - #include "qtestlitewindow.h" -#include -#include -#include -#include -#include -#include +#include "qtestliteintegration.h" +#include "qtestlitescreen.h" -#include -#include +#include +#include #include +#include + +#include +#include #ifndef QT_NO_OPENGL #include "qglxintegration.h" #endif -#include -#include - - -#include - -#include - - - -//### remove stuff we don't want from qt_x11_p.h -#undef ATOM -#undef X11 - //#define MYX11_DEBUG QT_BEGIN_NAMESPACE -static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); -static bool seen_badwindow; - - -static Atom wmProtocolsAtom; -static Atom wmDeleteWindowAtom; - -class MyX11CursorNode +QTestLiteWindow::QTestLiteWindow(QWidget *window) + : QPlatformWindow(window) + , mGLContext(0) + , mScreen(QTestLiteScreen::testLiteScreenForWidget(window)) { -public: - MyX11CursorNode(int id, Cursor c) { idValue = id; cursorValue = c; refCount = 1; } - QDateTime expiration() { return t; } - void setExpiration(QDateTime val) { t = val; } - MyX11CursorNode * ante() { return before; } - void setAnte(MyX11CursorNode *node) { before = node; } - MyX11CursorNode * post() { return after; } - void setPost(MyX11CursorNode *node) { after = node; } - Cursor cursor() { return cursorValue; } - int id() { return idValue; } - unsigned int refCount; - -private: - MyX11CursorNode *before; - MyX11CursorNode *after; - QDateTime t; - Cursor cursorValue; - int idValue; - - Display * display; -}; - - - - - -class MyX11Cursors : public QObject -{ - Q_OBJECT -public: - MyX11Cursors(Display * d); - ~MyX11Cursors() { timer.stop(); } - void incrementUseCount(int id); - void decrementUseCount(int id); - void createNode(int id, Cursor c); - bool exists(int id) { return lookupMap.contains(id); } - Cursor cursor(int id); -public slots: - void timeout(); - -private: - void removeNode(MyX11CursorNode *node); - void insertNode(MyX11CursorNode *node); - - // linked list of cursors currently not assigned to any window - MyX11CursorNode *firstExpired; - MyX11CursorNode *lastExpired; - - QHash lookupMap; - QTimer timer; - - Display *display; - - int removalDelay; -}; - - - - - -QTestLiteWindow::QTestLiteWindow(const QTestLiteIntegration *platformIntegration, - QTestLiteScreen */*screen*/, QWidget *window) - :QPlatformWindow(window), mGLContext(0) -{ - xd = platformIntegration->xd; - xd->windowList.append(this); - { - int x = window->x(); - int y = window->y(); - int w = window->width(); - int h = window->height(); + int x = window->x(); + int y = window->y(); + int w = window->width(); + int h = window->height(); if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL - && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { + && QApplicationPrivate + ::platformIntegration()->hasOpenGL() ) { #ifndef QT_NO_OPENGL - XVisualInfo *visualInfo = QGLXGLContext::findVisualInfo(xd,window->platformWindowFormat()); - Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); + Colormap cmap = XCreateColormap(mScreen->display(),mScreen->rootWindow(),visualInfo->visual,AllocNone); XSetWindowAttributes a; a.colormap = cmap; - x_window = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, + x_window = XCreateWindow(mScreen->display(), mScreen->rootWindow(),x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWColormap, &a); #endif //QT_NO_OPENGL } else { - x_window = XCreateSimpleWindow(xd->display, xd->rootWindow(), + x_window = XCreateSimpleWindow(mScreen->display(), mScreen->rootWindow(), x, y, w, h, 0 /*border_width*/, - xd->blackPixel(), xd->whitePixel()); + mScreen->blackPixel(), mScreen->whitePixel()); } #ifdef MYX11_DEBUG qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; #endif - } +// } - width = -1; - height = -1; - xpos = -1; - ypos = -1; +// width = -1; +// height = -1; +// xpos = -1; +// ypos = -1; - XSetWindowBackgroundPixmap(xd->display, x_window, XNone); + XSetWindowBackgroundPixmap(mScreen->display(), x_window, XNone); - XSelectInput(xd->display, x_window, ExposureMask | KeyPressMask | KeyReleaseMask | + XSelectInput(mScreen->display(), x_window, ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | StructureNotifyMask); gc = createGC(); - XChangeProperty (xd->display, x_window, - wmProtocolsAtom, - XA_ATOM, 32, PropModeAppend, - (unsigned char *) &wmDeleteWindowAtom, 1); - currentCursor = -1; + Atom wmDeleteWindowAtom = mScreen->wmDeleteWindowAtom(); + XChangeProperty (mScreen->display(), x_window, + mScreen->wmProtocolsAtom(), + XA_ATOM, 32, PropModeAppend, + (unsigned char *) &wmDeleteWindowAtom, 1); + mScreen->setWmDeleteWindowAtom(wmDeleteWindowAtom); } @@ -211,19 +123,12 @@ QTestLiteWindow::~QTestLiteWindow() qDebug() << "~QTestLiteWindow" << hex << x_window; #endif delete mGLContext; - XFreeGC(xd->display, gc); - XDestroyWindow(xd->display, x_window); - - xd->windowList.removeAll(this); + XFreeGC(mScreen->display(), gc); + XDestroyWindow(mScreen->display(), x_window); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Mouse event stuff - - - - static Qt::MouseButtons translateMouseButtons(int s) { Qt::MouseButtons ret = 0; @@ -236,13 +141,11 @@ static Qt::MouseButtons translateMouseButtons(int s) return ret; } - static Qt::KeyboardModifiers translateModifiers(int s) { const uchar qt_alt_mask = Mod1Mask; const uchar qt_meta_mask = Mod4Mask; - Qt::KeyboardModifiers ret = 0; if (s & ShiftMask) ret |= Qt::ShiftModifier; @@ -328,7 +231,6 @@ void QTestLiteWindow::handleFocusOutEvent() QWindowSystemInterface::handleWindowActivated(0); } - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Key event stuff -- not pretty either // @@ -570,7 +472,6 @@ static const unsigned int keyTbl[] = { 0, 0 }; - static int lookupCode(unsigned int xkeycode) { if (xkeycode >= XK_F1 && xkeycode <= XK_F35) @@ -586,7 +487,6 @@ static int lookupCode(unsigned int xkeycode) return 0; } - static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) { switch (qtcode) { @@ -640,7 +540,7 @@ void QTestLiteWindow::handleKeyEvent(QEvent::Type type, void *ev) void QTestLiteWindow::setGeometry(const QRect &rect) { - XMoveResizeWindow(xd->display, x_window, rect.x(), rect.y(), rect.width(), rect.height()); + XMoveResizeWindow(mScreen->display(), x_window, rect.x(), rect.y(), rect.width(), rect.height()); QPlatformWindow::setGeometry(rect); } @@ -658,17 +558,17 @@ WId QTestLiteWindow::winId() const void QTestLiteWindow::setParent(const QPlatformWindow *window) { QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); - XReparentWindow(xd->display,x_window,window->winId(),point.x(),point.y()); + XReparentWindow(mScreen->display(),x_window,window->winId(),point.x(),point.y()); } void QTestLiteWindow::raise() { - XRaiseWindow(xd->display, x_window); + XRaiseWindow(mScreen->display(), x_window); } void QTestLiteWindow::lower() { - XLowerWindow(xd->display, x_window); + XLowerWindow(mScreen->display(), x_window); } void QTestLiteWindow::setWindowTitle(const QString &title) @@ -680,14 +580,14 @@ void QTestLiteWindow::setWindowTitle(const QString &title) windowName.format = 8; windowName.nitems = ba.length(); - XSetWMName(xd->display, x_window, &windowName); + XSetWMName(mScreen->display(), x_window, &windowName); } GC QTestLiteWindow::createGC() { GC gc; - gc = XCreateGC(xd->display, x_window, 0, 0); + gc = XCreateGC(mScreen->display(), x_window, 0, 0); if (gc < 0) { qWarning("QTestLiteWindow::createGC() could not create GC"); } @@ -701,34 +601,32 @@ void QTestLiteWindow::paintEvent() #endif if (QWindowSurface *surface = widget()->windowSurface()) - surface->flush(widget(), QRect(xpos,ypos,width, height), QPoint()); + surface->flush(widget(), widget()->geometry(), QPoint()); } void QTestLiteWindow::requestActivateWindow() { - XSetInputFocus(xd->display, x_window, XRevertToParent, CurrentTime); + XSetInputFocus(mScreen->display(), x_window, XRevertToParent, CurrentTime); } void QTestLiteWindow::resizeEvent(XConfigureEvent *e) { - if ((e->width != width || e->height != height) && e->x == 0 && e->y == 0) { + int xpos = geometry().x(); + int ypos = geometry().y(); + if ((e->width != geometry().width() || e->height != geometry().height()) && e->x == 0 && e->y == 0) { //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window; } else { //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window; xpos = e->x; ypos = e->y; } - width = e->width; - height = e->height; - #ifdef MYX11_DEBUG qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height; #endif - QWindowSystemInterface::handleGeometryChange(widget(), QRect(xpos, ypos, width, height)); + QWindowSystemInterface::handleGeometryChange(widget(), QRect(xpos, ypos, e->width, e->height)); } - void QTestLiteWindow::mousePressEvent(XButtonEvent *e) { static long prevTime = 0; @@ -752,51 +650,7 @@ void QTestLiteWindow::mousePressEvent(XButtonEvent *e) handleMouseEvent(type, e); } - - -// WindowFlag stuff, lots of copied code from qwidget_x11.cpp... - -//We're hacking here... - - -// MWM support -struct QtMWMHints { - ulong flags, functions, decorations; - long input_mode; - ulong status; -}; - -enum { - MWM_HINTS_FUNCTIONS = (1L << 0), - - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - - MWM_HINTS_DECORATIONS = (1L << 1), - - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), - - MWM_HINTS_INPUT_MODE = (1L << 2), - - MWM_INPUT_MODELESS = 0L, - MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, - MWM_INPUT_FULL_APPLICATION_MODAL = 3L -}; - -static Atom mwm_hint_atom = XNone; - -#if 0 -static QtMWMHints GetMWMHints(Display *display, Window window) +QtMWMHints QTestLiteWindow::getMWMHints() const { QtMWMHints mwmhints; @@ -804,10 +658,10 @@ static QtMWMHints GetMWMHints(Display *display, Window window) int format; ulong nitems, bytesLeft; uchar *data = 0; - if ((XGetWindowProperty(display, window, mwm_hint_atom, 0, 5, false, - mwm_hint_atom, &type, &format, &nitems, &bytesLeft, + if ((XGetWindowProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints(), 0, 5, false, + mScreen->atomForMotifWmHints(), &type, &format, &nitems, &bytesLeft, &data) == Success) - && (type == mwm_hint_atom + && (type == mScreen->atomForMotifWmHints() && format == 32 && nitems >= 5)) { mwmhints = *(reinterpret_cast(data)); @@ -824,15 +678,15 @@ static QtMWMHints GetMWMHints(Display *display, Window window) return mwmhints; } -#endif -static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints) +void QTestLiteWindow::setMWMHints(const QtMWMHints &mwmhints) { if (mwmhints.flags != 0l) { - XChangeProperty(display, window, mwm_hint_atom, mwm_hint_atom, 32, + XChangeProperty(mScreen->display(), x_window, + mScreen->atomForMotifWmHints(), mScreen->atomForMotifWmHints(), 32, PropModeReplace, (unsigned char *) &mwmhints, 5); } else { - XDeleteProperty(display, window, mwm_hint_atom); + XDeleteProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints()); } } @@ -849,17 +703,11 @@ static inline bool isTransient(const QWidget *w) && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); } - - Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) { // Q_ASSERT(flags & Qt::Window); window_flags = flags; - if (mwm_hint_atom == XNone) { - mwm_hint_atom = XInternAtom(xd->display, "_MOTIF_WM_HINTS\0", False); - } - #ifdef MYX11_DEBUG qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags; #endif @@ -878,12 +726,10 @@ Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) bool tool = (type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer); - Q_UNUSED(topLevel); Q_UNUSED(dialog); Q_UNUSED(desktop); - bool tooltip = (type == Qt::ToolTip); XSetWindowAttributes wsa; @@ -964,7 +810,7 @@ Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) mwmhints.decorations = 0; } - SetMWMHints(xd->display, x_window, mwmhints); + setMWMHints(mwmhints); //##### only if initializeWindow??? @@ -977,7 +823,7 @@ Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) wsa.override_redirect = True; wsa.save_under = True; - XChangeWindowAttributes(xd->display, x_window, CWOverrideRedirect | CWSaveUnder, + XChangeWindowAttributes(mScreen->display(), x_window, CWOverrideRedirect | CWSaveUnder, &wsa); } else { #ifdef MYX11_DEBUG @@ -994,38 +840,15 @@ void QTestLiteWindow::setVisible(bool visible) qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window; #endif if (visible) - XMapWindow(xd->display, x_window); + XMapWindow(mScreen->display(), x_window); else - XUnmapWindow(xd->display, x_window); + XUnmapWindow(mScreen->display(), x_window); } - -void QTestLiteWindow::setCursor(QCursor * cursor) +void QTestLiteWindow::setCursor(const Cursor &cursor) { - int id = cursor->handle(); - if (id == currentCursor) - return; - Cursor c; - if (!xd->cursors->exists(id)) { - if (cursor->shape() == Qt::BitmapCursor) - c = createCursorBitmap(cursor); - else - c = createCursorShape(cursor->shape()); - if (!c) { - return; - } - xd->cursors->createNode(id, c); - } else { - xd->cursors->incrementUseCount(id); - c = xd->cursors->cursor(id); - } - - if (currentCursor != -1) - xd->cursors->decrementUseCount(currentCursor); - currentCursor = id; - - XDefineCursor(xd->display, x_window, c); - XFlush(xd->display); + XDefineCursor(mScreen->display(), x_window, cursor); + XFlush(mScreen->display()); } QPlatformGLContext *QTestLiteWindow::glContext() const @@ -1035,574 +858,20 @@ QPlatformGLContext *QTestLiteWindow::glContext() const if (!mGLContext) { QTestLiteWindow *that = const_cast(this); #ifndef QT_NO_OPENGL - that->mGLContext = new QGLXGLContext(x_window, xd,widget()->platformWindowFormat()); + that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat()); #endif } return mGLContext; } -Cursor QTestLiteWindow::createCursorBitmap(QCursor * cursor) -{ - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - QPoint spot = cursor->hotSpot(); - Window rootwin = x_window; - - QImage mapImage = cursor->bitmap()->toImage().convertToFormat(QImage::Format_MonoLSB); - QImage maskImage = cursor->mask()->toImage().convertToFormat(QImage::Format_MonoLSB); - - int width = cursor->bitmap()->width(); - int height = cursor->bitmap()->height(); - int bytesPerLine = mapImage.bytesPerLine(); - int destLineSize = width / 8; - if (width % 8) - destLineSize++; - - const uchar * map = mapImage.bits(); - const uchar * mask = maskImage.bits(); - - char * mapBits = new char[height * destLineSize]; - char * maskBits = new char[height * destLineSize]; - for (int i = 0; i < height; i++) { - memcpy(mapBits + (destLineSize * i),map + (bytesPerLine * i), destLineSize); - memcpy(maskBits + (destLineSize * i),mask + (bytesPerLine * i), destLineSize); - } - - Pixmap cp = XCreateBitmapFromData(xd->display, rootwin, mapBits, width, height); - Pixmap mp = XCreateBitmapFromData(xd->display, rootwin, maskBits, width, height); - Cursor c = XCreatePixmapCursor(xd->display, cp, mp, &fg, &bg, spot.x(), spot.y()); - XFreePixmap(xd->display, cp); - XFreePixmap(xd->display, mp); - delete[] mapBits; - delete[] maskBits; - - return c; -} - -Cursor QTestLiteWindow::createCursorShape(int cshape) -{ - Cursor cursor = 0; - - if (cshape < 0 || cshape > Qt::LastCursor) - return 0; - - switch (cshape) { - case Qt::ArrowCursor: - cursor = XCreateFontCursor(xd->display, XC_left_ptr); - break; - case Qt::UpArrowCursor: - cursor = XCreateFontCursor(xd->display, XC_center_ptr); - break; - case Qt::CrossCursor: - cursor = XCreateFontCursor(xd->display, XC_crosshair); - break; - case Qt::WaitCursor: - cursor = XCreateFontCursor(xd->display, XC_watch); - break; - case Qt::IBeamCursor: - cursor = XCreateFontCursor(xd->display, XC_xterm); - break; - case Qt::SizeAllCursor: - cursor = XCreateFontCursor(xd->display, XC_fleur); - break; - case Qt::PointingHandCursor: - cursor = XCreateFontCursor(xd->display, XC_hand2); - break; - case Qt::SizeBDiagCursor: - cursor = XCreateFontCursor(xd->display, XC_top_right_corner); - break; - case Qt::SizeFDiagCursor: - cursor = XCreateFontCursor(xd->display, XC_bottom_right_corner); - break; - case Qt::SizeVerCursor: - case Qt::SplitVCursor: - cursor = XCreateFontCursor(xd->display, XC_sb_v_double_arrow); - break; - case Qt::SizeHorCursor: - case Qt::SplitHCursor: - cursor = XCreateFontCursor(xd->display, XC_sb_h_double_arrow); - break; - case Qt::WhatsThisCursor: - cursor = XCreateFontCursor(xd->display, XC_question_arrow); - break; - case Qt::ForbiddenCursor: - cursor = XCreateFontCursor(xd->display, XC_circle); - break; - case Qt::BusyCursor: - cursor = XCreateFontCursor(xd->display, XC_watch); - break; - - default: //default cursor for all the rest - break; - } - return cursor; -} - - -MyX11Cursors::MyX11Cursors(Display * d) : firstExpired(0), lastExpired(0), display(d), removalDelay(3) -{ - connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); -} - -void MyX11Cursors::insertNode(MyX11CursorNode * node) +Window QTestLiteWindow::xWindow() const { - QDateTime now = QDateTime::currentDateTime(); - QDateTime timeout = now.addSecs(removalDelay); - node->setExpiration(timeout); - node->setPost(0); - if (lastExpired) { - lastExpired->setPost(node); - node->setAnte(lastExpired); - } - lastExpired = node; - if (!firstExpired) { - firstExpired = node; - node->setAnte(0); - int interval = removalDelay * 1000; - timer.setInterval(interval); - timer.start(); - } -} - -void MyX11Cursors::removeNode(MyX11CursorNode * node) -{ - MyX11CursorNode *pre = node->ante(); - MyX11CursorNode *post = node->post(); - if (pre) - pre->setPost(post); - if (post) - post->setAnte(pre); - if (node == lastExpired) - lastExpired = pre; - if (node == firstExpired) { - firstExpired = post; - if (!firstExpired) { - timer.stop(); - return; - } - int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; - timer.stop(); - timer.setInterval(interval); - timer.start(); - } -} - -void MyX11Cursors::incrementUseCount(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - if (!node->refCount) - removeNode(node); - node->refCount++; -} - -void MyX11Cursors::decrementUseCount(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - node->refCount--; - if (!node->refCount) - insertNode(node); -} - -void MyX11Cursors::createNode(int id, Cursor c) -{ - MyX11CursorNode * node = new MyX11CursorNode(id, c); - lookupMap.insert(id, node); -} - -void MyX11Cursors::timeout() -{ - MyX11CursorNode * node; - node = firstExpired; - QDateTime now = QDateTime::currentDateTime(); - while (node && now.secsTo(node->expiration()) < 1) { - Cursor c = node->cursor(); - int id = node->id(); - lookupMap.take(id); - MyX11CursorNode * tmp = node; - node = node->post(); - if (node) - node->setAnte(0); - delete tmp; - XFreeCursor(display, c); - } - firstExpired = node; - if (node == 0) { - timer.stop(); - lastExpired = 0; - } - else { - int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; - timer.setInterval(interval); - timer.start(); - } -} - -Cursor MyX11Cursors::cursor(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - return node->cursor(); -} - - - -/******************************************************************** - -MyDisplay class - perhaps better placed in qplatformintegration_testlite? - -*********************************************************************/ - -//### copied from qapplication_x11.cpp - -static int qt_x_errhandler(Display *dpy, XErrorEvent *err) -{ - -qDebug() << "qt_x_errhandler" << err->error_code; - - switch (err->error_code) { - case BadAtom: -#if 0 - if (err->request_code == 20 /* X_GetProperty */ - && (err->resourceid == XA_RESOURCE_MANAGER - || err->resourceid == XA_RGB_DEFAULT_MAP - || err->resourceid == ATOM(_NET_SUPPORTED) - || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) - || err->resourceid == ATOM(KDE_FULL_SESSION) - || err->resourceid == ATOM(KWIN_RUNNING) - || err->resourceid == ATOM(XdndProxy) - || err->resourceid == ATOM(XdndAware)) - - - ) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } -#endif - qDebug() << "BadAtom"; - break; - - case BadWindow: - if (err->request_code == 2 /* X_ChangeWindowAttributes */ - || err->request_code == 38 /* X_QueryPointer */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } - } - seen_badwindow = true; - if (err->request_code == 25 /* X_SendEvent */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } -#if 0 - if (X11->xdndHandleBadwindow()) { - qDebug("xdndHandleBadwindow returned true"); - return 0; - } -#endif - } -#if 0 - if (X11->ignore_badwindow) - return 0; -#endif - break; - - case BadMatch: - if (err->request_code == 42 /* X_SetInputFocus */) - return 0; - break; - - default: -#if 0 //!defined(QT_NO_XINPUT) - if (err->request_code == X11->xinput_major - && err->error_code == (X11->xinput_errorbase + XI_BadDevice) - && err->minor_code == 3 /* X_OpenDevice */) { - return 0; - } -#endif - break; - } - - char errstr[256]; - XGetErrorText( dpy, err->error_code, errstr, 256 ); - char buffer[256]; - char request_str[256]; - qsnprintf(buffer, 256, "%d", err->request_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); - if (err->request_code < 128) { - // X error for a normal protocol request - qWarning( "X Error: %s %d\n" - " Major opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - request_str, - err->resourceid ); - } else { - // X error for an extension request - const char *extensionName = 0; -#if 0 - if (err->request_code == X11->xrender_major) - extensionName = "RENDER"; - else if (err->request_code == X11->xrandr_major) - extensionName = "RANDR"; - else if (err->request_code == X11->xinput_major) - extensionName = "XInputExtension"; - else if (err->request_code == X11->mitshm_major) - extensionName = "MIT-SHM"; -#endif - char minor_str[256]; - if (extensionName) { - qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); - } else { - extensionName = "Uknown extension"; - qsnprintf(minor_str, 256, "Unknown request"); - } - qWarning( "X Error: %s %d\n" - " Extension: %d (%s)\n" - " Minor opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - extensionName, - err->minor_code, - minor_str, - err->resourceid ); - } - - // ### we really should distinguish between severe, non-severe and - // ### application specific errors - - return 0; -} - - -#ifdef KeyPress -#undef KeyPress -#endif -#ifdef KeyRelease -#undef KeyRelease -#endif - -bool MyDisplay::handleEvent(XEvent *xe) -{ - //qDebug() << "handleEvent" << xe->xany.type << xe->xany.window; - int quit = false; - QTestLiteWindow *xw = 0; - foreach (QTestLiteWindow *w, windowList) { - if (w->winId() == xe->xany.window) { - xw = w; - break; - } - } - if (!xw) { -#ifdef MYX11_DEBUG - qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type; -#endif - return quit; - } - - switch (xe->type) { - - case ClientMessage: - if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { - Atom a = xe->xclient.data.l[0]; - if (a == wmDeleteWindowAtom) - xw->handleCloseEvent(); -#ifdef MYX11_DEBUG - qDebug() << "ClientMessage WM_PROTOCOLS" << a; -#endif - } -#ifdef MYX11_DEBUG - else - qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type; -#endif - break; - - case Expose: - if (xw) - if (xe->xexpose.count == 0) - xw->paintEvent(); - break; - case ConfigureNotify: - if (xw) - xw->resizeEvent(&xe->xconfigure); - break; - - case ButtonPress: - xw->mousePressEvent(&xe->xbutton); - break; - - case ButtonRelease: - xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); - break; - - case MotionNotify: - xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); - break; - - case XKeyPress: - xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); - break; - - case XKeyRelease: - xw->handleKeyEvent(QEvent::KeyRelease, &xe->xkey); - break; - - case EnterNotify: - xw->handleEnterEvent(); - break; - - case LeaveNotify: - xw->handleLeaveEvent(); - break; - - case XFocusIn: - xw->handleFocusInEvent(); - break; - - case XFocusOut: - xw->handleFocusOutEvent(); - break; - - default: -#ifdef MYX11_DEBUG - qDebug() << hex << xe->xany.window << "Other X event" << xe->type; -#endif - break; - } - return quit; -}; - - - -MyDisplay::MyDisplay() -{ - char *display_name = getenv("DISPLAY"); - display = XOpenDisplay(display_name); - if (!display) { - fprintf(stderr, "Cannot connect to X server: %s\n", - display_name); - exit(1); - } - -#ifndef DONT_USE_MIT_SHM - Status MIT_SHM_extension_supported = XShmQueryExtension (display); - Q_ASSERT(MIT_SHM_extension_supported == True); -#endif - original_x_errhandler = XSetErrorHandler(qt_x_errhandler); - - if (qgetenv("DO_X_SYNCHRONIZE").toInt()) - XSynchronize(display, true); - - screen = DefaultScreen(display); - width = DisplayWidth(display, screen); - height = DisplayHeight(display, screen); - physicalWidth = DisplayWidthMM(display, screen); - physicalHeight = DisplayHeightMM(display, screen); - - int xSocketNumber = XConnectionNumber(display); -#ifdef MYX11_DEBUG - qDebug() << "X socket:"<< xSocketNumber; -#endif - QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); - connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); - - wmProtocolsAtom = XInternAtom (display, "WM_PROTOCOLS", False); - wmDeleteWindowAtom = XInternAtom (display, "WM_DELETE_WINDOW", False); - - cursors = new MyX11Cursors(display); -} - - -MyDisplay::~MyDisplay() -{ - XCloseDisplay(display); -} - - -void MyDisplay::eventDispatcher() -{ -// qDebug() << "eventDispatcher"; - - - ulong marker = XNextRequest(display); -// int i = 0; - while (XPending(display)) { - XEvent event; - XNextEvent(display, &event); - /* done = */ - handleEvent(&event); - - if (event.xany.serial >= marker) { -#ifdef MYX11_DEBUG - qDebug() << "potential livelock averted"; -#endif -#if 0 - if (XEventsQueued(display, QueuedAfterFlush)) { - qDebug() << " with events queued"; - QTimer::singleShot(0, this, SLOT(eventDispatcher())); - } -#endif - break; - } - } + return x_window; } - -QImage MyDisplay::grabWindow(Window window, int x, int y, int w, int h) +GC QTestLiteWindow::graphicsContext() const { - if (w == 0 || h ==0) - return QImage(); - - //WinId 0 means the desktop widget - if (!window) - window = rootWindow(); - - XWindowAttributes window_attr; - if (!XGetWindowAttributes(display, window, &window_attr)) - return QImage(); - - if (w < 0) - w = window_attr.width - x; - if (h < 0) - h = window_attr.height - y; - - // Ideally, we should also limit ourselves to the screen area, but the Qt docs say - // that it's "unsafe" to go outside the screen, so we can ignore that problem. - - //We're definitely not optimizing for speed... - XImage *xi = XGetImage(display, window, x, y, w, h, AllPlanes, ZPixmap); - - if (!xi) - return QImage(); - - //taking a copy to make sure we have ownership -- not fast - QImage result = QImage( (uchar*) xi->data, xi->width, xi->height, xi->bytes_per_line, QImage::Format_RGB32 ).copy(); - - XDestroyImage(xi); - - return result; + return gc; } - - - - - - QT_END_NAMESPACE -#include "qtestlitewindow.moc" diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index 69442f1..8e9f6fd 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -42,63 +42,51 @@ #ifndef QTESTLITEWINDOW_H #define QTESTLITEWINDOW_H +#include "qtestliteintegration.h" + #include -#include +#include #include #include -#include -#include - -#include - -#include -#include - - - -class QTestLiteIntegration; -class QTestLiteScreen; -class QTestLiteWindowSurface; -class MyX11Cursors; -class QTestLiteWindow; -class MyDisplay : public QObject -{ - Q_OBJECT; -public: - MyDisplay(); - ~MyDisplay(); +struct QtMWMHints { + ulong flags, functions, decorations; + long input_mode; + ulong status; +}; - Window rootWindow() { return RootWindow(display, screen); } - unsigned long blackPixel() { return BlackPixel(display, screen); } - unsigned long whitePixel() { return WhitePixel(display, screen); } +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), - bool handleEvent(XEvent *xe); - QImage grabWindow(Window window, int x, int y, int w, int h); + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), -public slots: - void eventDispatcher(); + MWM_HINTS_DECORATIONS = (1L << 1), -public: //### - Display * display; - int screen; - int width, height; - int physicalWidth; - int physicalHeight; + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), - QList windowList; + MWM_HINTS_INPUT_MODE = (1L << 2), - MyX11Cursors * cursors; + MWM_INPUT_MODELESS = 0L, + MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, + MWM_INPUT_FULL_APPLICATION_MODAL = 3L }; -struct MyShmImageInfo; - class QTestLiteWindow : public QPlatformWindow { public: - QTestLiteWindow(const QTestLiteIntegration *platformIntegration, - QTestLiteScreen *screen, QWidget *window); + QTestLiteWindow(QWidget *window); ~QTestLiteWindow(); @@ -128,33 +116,29 @@ public: void lower(); void setWindowTitle(const QString &title); - void setCursor(QCursor * cursor); + void setCursor(const Cursor &cursor); QPlatformGLContext *glContext() const; + Window xWindow() const; + GC graphicsContext() const; + +protected: + void setMWMHints(const QtMWMHints &mwmhints); + QtMWMHints getMWMHints() const; + private: - int xpos, ypos; - int width, height; Window x_window; GC gc; GC createGC(); - Cursor createCursorShape(int cshape); - Cursor createCursorBitmap(QCursor * cursor); - - int currentCursor; - - MyDisplay *xd; + QPlatformGLContext *mGLContext; QTestLiteScreen *mScreen; Qt::WindowFlags window_flags; - QPlatformGLContext *mGLContext; - - friend class QTestLiteWindowSurface; // x_window, gc and windowSurface -}; - - + Atom m_mwm_hint_atom; +}; #endif diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp index b3232c8..ced964a 100644 --- a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp @@ -46,6 +46,7 @@ #include #include "qtestlitewindow.h" +#include "qtestlitescreen.h" # include # include @@ -65,8 +66,6 @@ struct MyShmImageInfo { Display *display; }; -//void QTestLiteWindowSurface::flush() - #ifndef DONT_USE_MIT_SHM void MyShmImageInfo::destroy() @@ -80,20 +79,21 @@ void MyShmImageInfo::destroy() void QTestLiteWindowSurface::resizeShmImage(int width, int height) { - MyDisplay *xd = xw->xd; #ifdef DONT_USE_MIT_SHM shm_img = QImage(width, height, QImage::Format_RGB32); #else + + QTestLiteScreen *screen = QTestLiteScreen::testLiteScreenForWidget(window()); if (image_info) image_info->destroy(); else - image_info = new MyShmImageInfo(xd->display); + image_info = new MyShmImageInfo(screen->display()); - Visual *visual = DefaultVisual(xd->display, xd->screen); + Visual *visual = DefaultVisual(screen->display(), screen->xScreenNumber()); - XImage *image = XShmCreateImage (xd->display, visual, 24, ZPixmap, 0, + XImage *image = XShmCreateImage (screen->display(), visual, 24, ZPixmap, 0, &image_info->shminfo, width, height); @@ -105,7 +105,7 @@ void QTestLiteWindowSurface::resizeShmImage(int width, int height) image_info->image = image; - Status shm_attach_status = XShmAttach(xd->display, &image_info->shminfo); + Status shm_attach_status = XShmAttach(screen->display(), &image_info->shminfo); Q_ASSERT(shm_attach_status == True); @@ -126,7 +126,7 @@ QSize QTestLiteWindowSurface::bufferSize() const return shm_img.size(); } -QTestLiteWindowSurface::QTestLiteWindowSurface (QTestLiteScreen */*screen*/, QWidget *window) +QTestLiteWindowSurface::QTestLiteWindowSurface (QWidget *window) : QWindowSurface(window), painted(false), image_info(0) { @@ -151,29 +151,27 @@ void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const Q_UNUSED(region); Q_UNUSED(offset); - // qDebug() << "QTestLiteWindowSurface::flush:" << (long)this; - if (!painted) return; - MyDisplay *xd = xw->xd; - GC gc = xw->gc; - Window window = xw->x_window; + QTestLiteScreen *screen = QTestLiteScreen::testLiteScreenForWidget(widget); + GC gc = xw->graphicsContext(); + Window window = xw->xWindow(); #ifdef DONT_USE_MIT_SHM // just convert the image every time... if (!shm_img.isNull()) { - Visual *visual = DefaultVisual(xd->display, xd->screen); + Visual *visual = DefaultVisual(screen->display(), screen->xScreenNumber()); QImage image = shm_img; //img.convertToFormat( - XImage *xi = XCreateImage(xd->display, visual, 24, ZPixmap, + XImage *xi = XCreateImage(screen->display(), visual, 24, ZPixmap, 0, (char *) image.scanLine(0), image.width(), image.height(), 32, image.bytesPerLine()); int x = 0; int y = 0; - /*int r =*/ XPutImage(xd->display, window, gc, xi, 0, 0, x, y, image.width(), image.height()); + /*int r =*/ XPutImage(screen->display(), window, gc, xi, 0, 0, x, y, image.width(), image.height()); xi->data = 0; // QImage owns these bits XDestroyImage(xi); @@ -187,11 +185,11 @@ void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const // We could set send_event to true, and then use the ShmCompletion to synchronize, // but let's do like Qt/11 and just use XSync - XShmPutImage (xd->display, window, gc, image_info->image, 0, 0, + XShmPutImage (screen->display(), window, gc, image_info->image, 0, 0, x, y, image_info->image->width, image_info->image->height, /*send_event*/ False); - XSync(xd->display, False); + XSync(screen->display(), False); } #endif } diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.h b/src/plugins/platforms/testlite/qtestlitewindowsurface.h index 915e7fe..ca900e5 100644 --- a/src/plugins/platforms/testlite/qtestlitewindowsurface.h +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.h @@ -55,7 +55,7 @@ class MyShmImageInfo; class QTestLiteWindowSurface : public QWindowSurface { public: - QTestLiteWindowSurface (QTestLiteScreen *screen, QWidget *window); + QTestLiteWindowSurface (QWidget *window); ~QTestLiteWindowSurface(); QPaintDevice *paintDevice(); diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index 05bd384..ef977bf 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -7,13 +7,16 @@ SOURCES = \ main.cpp \ qtestliteintegration.cpp \ qtestlitewindowsurface.cpp \ - qtestlitewindow.cpp + qtestlitewindow.cpp \ + qtestlitecursor.cpp \ + qtestlitescreen.cpp HEADERS = \ qtestliteintegration.h \ qtestlitewindowsurface.h \ - qtestlitewindow.h - + qtestlitewindow.h \ + qtestlitecursor.h \ + qtestlitescreen.h LIBS += -lX11 -lXext -- cgit v0.12 From dd72b151b500838475f2ec40695449a37acd3922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Thu, 9 Dec 2010 09:00:02 +0100 Subject: Remove Lighthouse specific code in QGLWidget constructor truth to be told, I can't remember why I decided that it was a good idea to have the code there. But clearly now I don't think so anymore. Such initialisation should happen in qgl_qpa.cpp chooseContext. If we tear down the window and the context then that has to be solved elsewhere. --- src/opengl/opengl.pro.user.2.1pre1 | 83 ++++++++++++++++++++++++++++++++++++++ src/opengl/qgl.cpp | 34 ---------------- src/opengl/qgl_qpa.cpp | 5 --- 3 files changed, 83 insertions(+), 39 deletions(-) create mode 100644 src/opengl/opengl.pro.user.2.1pre1 diff --git a/src/opengl/opengl.pro.user.2.1pre1 b/src/opengl/opengl.pro.user.2.1pre1 new file mode 100644 index 0000000..0c38724 --- /dev/null +++ b/src/opengl/opengl.pro.user.2.1pre1 @@ -0,0 +1,83 @@ + + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + UTF-8 + + + + ProjectExplorer.Project.Target.0 + + Desktop + Qt4ProjectManager.Target.DesktopTarget + 0 + 0 + + + qmake + QtProjectManager.QMakeBuildStep + + QMAKE_ABSOLUTE_SOURCE_PATH=/home/jlind/dev/qt/lighthouse-master/src/opengl + + + + Make + Qt4ProjectManager.MakeStep + false + + -j9 + + + + 2 + + Make + Qt4ProjectManager.MakeStep + true + + clean + + + + 1 + false + + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + /home/jlind/builds/master-lighthouse/src/opengl + 23 + 0 + true + + 1 + + headers + Qt4ProjectManager.Qt4RunConfiguration + 2 + + ../../../../../builds/master-lighthouse/include/QtOpenGL/headers.pri + false + false + + false + false + + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 4 + + diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index e9e8880..dac00dc 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -3772,24 +3772,7 @@ QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFl setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility -#ifdef Q_WS_QPA - QPlatformWindowFormat platformFormat = QGLFormat::toPlatformWindowFormat(QGLFormat::defaultFormat()); - platformFormat.setUseDefaultSharedContext(false); - if (shareWidget && shareWidget->d_func()->glcx) { - QPlatformGLContext *sharedPlatformContext = shareWidget->d_func()->glcx->d_func()->platformContext; - platformFormat.setSharedContext(sharedPlatformContext); - } - setPlatformWindowFormat(platformFormat); - winId(); // create window; - QGLContext *glContext = 0; - if (platformWindow()) - glContext = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); - if (glContext){ - d->init(glContext,shareWidget); - } -#else d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget); -#endif } @@ -3829,24 +3812,7 @@ QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* setAttribute(Qt::WA_PaintOnScreen); setAttribute(Qt::WA_NoSystemBackground); setAutoFillBackground(true); // for compatibility -#ifdef Q_WS_QPA - QPlatformWindowFormat platformFormat = QGLFormat::toPlatformWindowFormat(format); - platformFormat.setUseDefaultSharedContext(false); - if (shareWidget && shareWidget->d_func()->glcx) { - QPlatformGLContext *sharedPlatformContext = shareWidget->d_func()->glcx->d_func()->platformContext; - platformFormat.setSharedContext(sharedPlatformContext); - } - setPlatformWindowFormat(platformFormat); - winId(); // create window; - QGLContext *glContext = 0; - if (platformWindow()) - glContext = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); - if (glContext){ - d->init(glContext,shareWidget); - } -#else d->init(new QGLContext(format, this), shareWidget); -#endif } /*! diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 415e915..52eb57f 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -325,11 +325,6 @@ void QGLWidget::setMouseTracking(bool enable) bool QGLWidget::event(QEvent *e) { Q_D(QGLWidget); - if (e->type() == QEvent::WinIdChange) { - if (platformWindow()) { - d->glcx = QGLContext::fromPlatformGLContext(platformWindow()->glContext()); - } - } return QWidget::event(e); } -- cgit v0.12 From 90de48493be283b9afb249f6a0fd8dbd8958517d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 10 Dec 2010 16:43:16 +0100 Subject: Handle the QWidgetPrivate::mapper structure Dont have widgets without a valid winId there --- src/gui/kernel/qwidget_qpa.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index 24ab8f7..560c9cd 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -768,6 +768,7 @@ void QWidgetPrivate::deleteTLSysExtra() context->deleteQGLContext(); } } + setWinId(0); delete extra->topextra->platformWindow; extra->topextra->platformWindow = 0; extra->topextra->backingStore.destroy(); -- cgit v0.12 From d0414bd582190e205aa698f5cb24f1c6909d8222 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 10 Dec 2010 16:44:44 +0100 Subject: Dont do backingStore.destroy in deleteTLSysExtra It is done by QWidgetPrivate::deleteExtra() --- src/gui/kernel/qwidget_qpa.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index 560c9cd..dce23a3 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -771,7 +771,6 @@ void QWidgetPrivate::deleteTLSysExtra() setWinId(0); delete extra->topextra->platformWindow; extra->topextra->platformWindow = 0; - extra->topextra->backingStore.destroy(); } } -- cgit v0.12 From e90cb6992e35ed4b9c2aae85edb8d787c24a8a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 14 Dec 2010 17:08:55 +0100 Subject: Fix gstreamer phonon build on X11 I added an x11{ } clause in the pro file for the plugin. But as it turnes out the x11 clause is defined in gui.pro so it is not available for use in any other pro or pri files. Also fixed a missing !qpa in qttest_p4.prf --- mkspecs/features/qttest_p4.prf | 2 +- src/plugins/phonon/gstreamer/gstreamer.pro | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qttest_p4.prf b/mkspecs/features/qttest_p4.prf index 2ee148b..26f4b35 100644 --- a/mkspecs/features/qttest_p4.prf +++ b/mkspecs/features/qttest_p4.prf @@ -2,7 +2,7 @@ isEmpty(TEMPLATE):TEMPLATE=app CONFIG += qt warn_on console depend_includepath testcase # x11 is not defined by configure (the following line is copied from gui.pro) -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!qpa:!mac:!symbian:CONFIG += x11 qtAddLibrary(QtTest) diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro index 02e0848..c0d2604 100644 --- a/src/plugins/phonon/gstreamer/gstreamer.pro +++ b/src/plugins/phonon/gstreamer/gstreamer.pro @@ -58,7 +58,7 @@ SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp -x11 { +!qpa:!embedded{ HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h SOURCES += $$PHONON_GSTREAMER_DIR/x11renderer.cpp } -- cgit v0.12 From a7fc0e8bad3bd020ece5fa70f0462bcaf59b3d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 14 Dec 2010 17:15:44 +0100 Subject: Fix nativechild widget position in Lighthouse --- src/gui/kernel/qwidget_qpa.cpp | 16 ++++++---------- src/plugins/platforms/testlite/qtestlitewindow.cpp | 11 ++++++----- src/plugins/platforms/testlite/qtestlitewindow.h | 3 --- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp index dce23a3..001810e 100644 --- a/src/gui/kernel/qwidget_qpa.cpp +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -162,7 +162,6 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) { Q_Q(QWidget); - // QWidget *oldParent = q->parentWidget(); Qt::WindowFlags oldFlags = data.window_flags; int targetScreen = -1; @@ -214,13 +213,6 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) data.window_flags = window->setWindowFlags(data.window_flags); } - // Reparenting child to toplevel - if ((f&Qt::Window) && !(oldFlags&Qt::Window)) { - //qDebug() << "setParent_sys() change to toplevel"; - q->create(); //### too early: this ought to happen at show() time - } - - if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden) q->setAttribute(Qt::WA_WState_Hidden); q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); @@ -396,7 +388,11 @@ void QWidgetPrivate::show_sys() QPlatformWindow *window = q->platformWindow(); if (window) { - const QRect geomRect = q->geometry(); + QRect geomRect = q->geometry(); + if (!q->isWindow()) { + QPoint topLeftOfWindow = q->mapTo(q->nativeParentWidget(),QPoint()); + geomRect.moveTopLeft(topLeftOfWindow); + } const QRect windowRect = window->geometry(); if (windowRect != geomRect) { window->setGeometry(geomRect); @@ -591,7 +587,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (q->isVisible()) { if (q->platformWindow()) { if (q->isWindow()) { - q->platformWindow()->setGeometry(q->frameGeometry()); + q->platformWindow()->setGeometry(q->geometry()); } else { QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint()); q->platformWindow()->setGeometry(QRect(posInNativeParent,r.size())); diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index f8f4a5f..5446615 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -71,8 +71,7 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) int h = window->height(); if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL - && QApplicationPrivate - ::platformIntegration()->hasOpenGL() ) { + && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { #ifndef QT_NO_OPENGL XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); Colormap cmap = XCreateColormap(mScreen->display(),mScreen->rootWindow(),visualInfo->visual,AllocNone); @@ -117,6 +116,7 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) } + QTestLiteWindow::~QTestLiteWindow() { #ifdef MYX11_DEBUG @@ -557,8 +557,8 @@ WId QTestLiteWindow::winId() const void QTestLiteWindow::setParent(const QPlatformWindow *window) { - QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); - XReparentWindow(mScreen->display(),x_window,window->winId(),point.x(),point.y()); + QPoint topLeft = geometry().topLeft(); + XReparentWindow(mScreen->display(),x_window,window->winId(),topLeft.x(),topLeft.y()); } void QTestLiteWindow::raise() @@ -624,7 +624,8 @@ void QTestLiteWindow::resizeEvent(XConfigureEvent *e) qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height; #endif - QWindowSystemInterface::handleGeometryChange(widget(), QRect(xpos, ypos, e->width, e->height)); + QRect newRect(xpos, ypos, e->width, e->height); + QWindowSystemInterface::handleGeometryChange(widget(), newRect); } void QTestLiteWindow::mousePressEvent(XButtonEvent *e) diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index 8e9f6fd..7e990ee 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -136,9 +136,6 @@ private: QPlatformGLContext *mGLContext; QTestLiteScreen *mScreen; Qt::WindowFlags window_flags; - - Atom m_mwm_hint_atom; - }; #endif -- cgit v0.12 From fc79d664af9fe3396badac8d1829623118e827fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 17 Dec 2010 07:58:43 +0100 Subject: Remove current cursor optimization It was broken since it didn't take care of the initial cursor. --- src/plugins/platforms/testlite/qtestlitecursor.cpp | 3 +-- src/plugins/platforms/testlite/qtestlitecursor.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestlitecursor.cpp b/src/plugins/platforms/testlite/qtestlitecursor.cpp index 4f3f0cb..e9e6eb7 100644 --- a/src/plugins/platforms/testlite/qtestlitecursor.cpp +++ b/src/plugins/platforms/testlite/qtestlitecursor.cpp @@ -71,8 +71,7 @@ void QTestLiteCursor::changeCursor(QCursor *cursor, QWidget *widget) return; int id = cursor->handle(); - if (id == currentCursor) - return; + Cursor c; if (!cursorMap.contains(id)) { if (cursor->shape() == Qt::BitmapCursor) diff --git a/src/plugins/platforms/testlite/qtestlitecursor.h b/src/plugins/platforms/testlite/qtestlitecursor.h index 15a5b2a..bb3549e 100644 --- a/src/plugins/platforms/testlite/qtestlitecursor.h +++ b/src/plugins/platforms/testlite/qtestlitecursor.h @@ -60,7 +60,6 @@ private: Cursor createCursorShape(int cshape); QTestLiteScreen *testLiteScreen() const; - int currentCursor; QMap cursorMap; }; -- cgit v0.12 From 683263e4010e3e1797221edb73d91471aea7b93a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 17 Dec 2010 08:02:04 +0100 Subject: Refactored the keyboard event handling in testlite --- .../platforms/testlite/qtestlitekeyboard.cpp | 943 +++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitekeyboard.h | 35 + src/plugins/platforms/testlite/qtestlitescreen.cpp | 11 +- src/plugins/platforms/testlite/qtestlitescreen.h | 3 + src/plugins/platforms/testlite/qtestlitewindow.cpp | 329 +------ src/plugins/platforms/testlite/qtestlitewindow.h | 1 - src/plugins/platforms/testlite/testlite.pro | 6 +- 7 files changed, 997 insertions(+), 331 deletions(-) create mode 100644 src/plugins/platforms/testlite/qtestlitekeyboard.cpp create mode 100644 src/plugins/platforms/testlite/qtestlitekeyboard.h diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp new file mode 100644 index 0000000..c18de59 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -0,0 +1,943 @@ +#include "qtestlitekeyboard.h" + +#include "qtestlitescreen.h" + +#include + +#include + +#ifndef XK_ISO_Left_Tab +#define XK_ISO_Left_Tab 0xFE20 +#endif + +#ifndef XK_dead_hook +#define XK_dead_hook 0xFE61 +#endif + +#ifndef XK_dead_horn +#define XK_dead_horn 0xFE62 +#endif + +#ifndef XK_Codeinput +#define XK_Codeinput 0xFF37 +#endif + +#ifndef XK_Kanji_Bangou +#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */ +#endif + +// Fix old X libraries +#ifndef XK_KP_Home +#define XK_KP_Home 0xFF95 +#endif +#ifndef XK_KP_Left +#define XK_KP_Left 0xFF96 +#endif +#ifndef XK_KP_Up +#define XK_KP_Up 0xFF97 +#endif +#ifndef XK_KP_Right +#define XK_KP_Right 0xFF98 +#endif +#ifndef XK_KP_Down +#define XK_KP_Down 0xFF99 +#endif +#ifndef XK_KP_Prior +#define XK_KP_Prior 0xFF9A +#endif +#ifndef XK_KP_Next +#define XK_KP_Next 0xFF9B +#endif +#ifndef XK_KP_End +#define XK_KP_End 0xFF9C +#endif +#ifndef XK_KP_Insert +#define XK_KP_Insert 0xFF9E +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif + +// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special +// multimedia keys. They are included here as not every system has them. +#define XF86XK_MonBrightnessUp 0x1008FF02 +#define XF86XK_MonBrightnessDown 0x1008FF03 +#define XF86XK_KbdLightOnOff 0x1008FF04 +#define XF86XK_KbdBrightnessUp 0x1008FF05 +#define XF86XK_KbdBrightnessDown 0x1008FF06 +#define XF86XK_Standby 0x1008FF10 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioPlay 0x1008FF14 +#define XF86XK_AudioStop 0x1008FF15 +#define XF86XK_AudioPrev 0x1008FF16 +#define XF86XK_AudioNext 0x1008FF17 +#define XF86XK_HomePage 0x1008FF18 +#define XF86XK_Mail 0x1008FF19 +#define XF86XK_Start 0x1008FF1A +#define XF86XK_Search 0x1008FF1B +#define XF86XK_AudioRecord 0x1008FF1C +#define XF86XK_Calculator 0x1008FF1D +#define XF86XK_Memo 0x1008FF1E +#define XF86XK_ToDoList 0x1008FF1F +#define XF86XK_Calendar 0x1008FF20 +#define XF86XK_PowerDown 0x1008FF21 +#define XF86XK_ContrastAdjust 0x1008FF22 +#define XF86XK_Back 0x1008FF26 +#define XF86XK_Forward 0x1008FF27 +#define XF86XK_Stop 0x1008FF28 +#define XF86XK_Refresh 0x1008FF29 +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_WakeUp 0x1008FF2B +#define XF86XK_Eject 0x1008FF2C +#define XF86XK_ScreenSaver 0x1008FF2D +#define XF86XK_WWW 0x1008FF2E +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Favorites 0x1008FF30 +#define XF86XK_AudioPause 0x1008FF31 +#define XF86XK_AudioMedia 0x1008FF32 +#define XF86XK_MyComputer 0x1008FF33 +#define XF86XK_LightBulb 0x1008FF35 +#define XF86XK_Shop 0x1008FF36 +#define XF86XK_History 0x1008FF37 +#define XF86XK_OpenURL 0x1008FF38 +#define XF86XK_AddFavorite 0x1008FF39 +#define XF86XK_HotLinks 0x1008FF3A +#define XF86XK_BrightnessAdjust 0x1008FF3B +#define XF86XK_Finance 0x1008FF3C +#define XF86XK_Community 0x1008FF3D +#define XF86XK_AudioRewind 0x1008FF3E +#define XF86XK_BackForward 0x1008FF3F +#define XF86XK_Launch0 0x1008FF40 +#define XF86XK_Launch1 0x1008FF41 +#define XF86XK_Launch2 0x1008FF42 +#define XF86XK_Launch3 0x1008FF43 +#define XF86XK_Launch4 0x1008FF44 +#define XF86XK_Launch5 0x1008FF45 +#define XF86XK_Launch6 0x1008FF46 +#define XF86XK_Launch7 0x1008FF47 +#define XF86XK_Launch8 0x1008FF48 +#define XF86XK_Launch9 0x1008FF49 +#define XF86XK_LaunchA 0x1008FF4A +#define XF86XK_LaunchB 0x1008FF4B +#define XF86XK_LaunchC 0x1008FF4C +#define XF86XK_LaunchD 0x1008FF4D +#define XF86XK_LaunchE 0x1008FF4E +#define XF86XK_LaunchF 0x1008FF4F +#define XF86XK_ApplicationLeft 0x1008FF50 +#define XF86XK_ApplicationRight 0x1008FF51 +#define XF86XK_Book 0x1008FF52 +#define XF86XK_CD 0x1008FF53 +#define XF86XK_Calculater 0x1008FF54 +#define XF86XK_Clear 0x1008FF55 +#define XF86XK_ClearGrab 0x1008FE21 +#define XF86XK_Close 0x1008FF56 +#define XF86XK_Copy 0x1008FF57 +#define XF86XK_Cut 0x1008FF58 +#define XF86XK_Display 0x1008FF59 +#define XF86XK_DOS 0x1008FF5A +#define XF86XK_Documents 0x1008FF5B +#define XF86XK_Excel 0x1008FF5C +#define XF86XK_Explorer 0x1008FF5D +#define XF86XK_Game 0x1008FF5E +#define XF86XK_Go 0x1008FF5F +#define XF86XK_iTouch 0x1008FF60 +#define XF86XK_LogOff 0x1008FF61 +#define XF86XK_Market 0x1008FF62 +#define XF86XK_Meeting 0x1008FF63 +#define XF86XK_MenuKB 0x1008FF65 +#define XF86XK_MenuPB 0x1008FF66 +#define XF86XK_MySites 0x1008FF67 +#define XF86XK_News 0x1008FF69 +#define XF86XK_OfficeHome 0x1008FF6A +#define XF86XK_Option 0x1008FF6C +#define XF86XK_Paste 0x1008FF6D +#define XF86XK_Phone 0x1008FF6E +#define XF86XK_Reply 0x1008FF72 +#define XF86XK_Reload 0x1008FF73 +#define XF86XK_RotateWindows 0x1008FF74 +#define XF86XK_RotationPB 0x1008FF75 +#define XF86XK_RotationKB 0x1008FF76 +#define XF86XK_Save 0x1008FF77 +#define XF86XK_Send 0x1008FF7B +#define XF86XK_Spell 0x1008FF7C +#define XF86XK_SplitScreen 0x1008FF7D +#define XF86XK_Support 0x1008FF7E +#define XF86XK_TaskPane 0x1008FF7F +#define XF86XK_Terminal 0x1008FF80 +#define XF86XK_Tools 0x1008FF81 +#define XF86XK_Travel 0x1008FF82 +#define XF86XK_Video 0x1008FF87 +#define XF86XK_Word 0x1008FF89 +#define XF86XK_Xfer 0x1008FF8A +#define XF86XK_ZoomIn 0x1008FF8B +#define XF86XK_ZoomOut 0x1008FF8C +#define XF86XK_Away 0x1008FF8D +#define XF86XK_Messenger 0x1008FF8E +#define XF86XK_WebCam 0x1008FF8F +#define XF86XK_MailForward 0x1008FF90 +#define XF86XK_Pictures 0x1008FF91 +#define XF86XK_Music 0x1008FF92 +#define XF86XK_Battery 0x1008FF93 +#define XF86XK_Bluetooth 0x1008FF94 +#define XF86XK_WLAN 0x1008FF95 +#define XF86XK_UWB 0x1008FF96 +#define XF86XK_AudioForward 0x1008FF97 +#define XF86XK_AudioRepeat 0x1008FF98 +#define XF86XK_AudioRandomPlay 0x1008FF99 +#define XF86XK_Subtitle 0x1008FF9A +#define XF86XK_AudioCycleTrack 0x1008FF9B +#define XF86XK_Time 0x1008FF9F +#define XF86XK_Select 0x1008FFA0 +#define XF86XK_View 0x1008FFA1 +#define XF86XK_TopMenu 0x1008FFA2 +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + + +// end of XF86keysyms.h + +// Special keys used by Qtopia, mapped into the X11 private keypad range. +#define QTOPIAXK_Select 0x11000601 +#define QTOPIAXK_Yes 0x11000602 +#define QTOPIAXK_No 0x11000603 +#define QTOPIAXK_Cancel 0x11000604 +#define QTOPIAXK_Printer 0x11000605 +#define QTOPIAXK_Execute 0x11000606 +#define QTOPIAXK_Sleep 0x11000607 +#define QTOPIAXK_Play 0x11000608 +#define QTOPIAXK_Zoom 0x11000609 +#define QTOPIAXK_Context1 0x1100060A +#define QTOPIAXK_Context2 0x1100060B +#define QTOPIAXK_Context3 0x1100060C +#define QTOPIAXK_Context4 0x1100060D +#define QTOPIAXK_Call 0x1100060E +#define QTOPIAXK_Hangup 0x1100060F +#define QTOPIAXK_Flip 0x11000610 + +// keyboard mapping table +static const unsigned int KeyTbl[] = { + + // misc keys + + XK_Escape, Qt::Key_Escape, + XK_Tab, Qt::Key_Tab, + XK_ISO_Left_Tab, Qt::Key_Backtab, + XK_BackSpace, Qt::Key_Backspace, + XK_Return, Qt::Key_Return, + XK_Insert, Qt::Key_Insert, + XK_Delete, Qt::Key_Delete, + XK_Clear, Qt::Key_Delete, + XK_Pause, Qt::Key_Pause, + XK_Print, Qt::Key_Print, + 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq + 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq + + // cursor movement + + XK_Home, Qt::Key_Home, + XK_End, Qt::Key_End, + XK_Left, Qt::Key_Left, + XK_Up, Qt::Key_Up, + XK_Right, Qt::Key_Right, + XK_Down, Qt::Key_Down, + XK_Prior, Qt::Key_PageUp, + XK_Next, Qt::Key_PageDown, + + // modifiers + + XK_Shift_L, Qt::Key_Shift, + XK_Shift_R, Qt::Key_Shift, + XK_Shift_Lock, Qt::Key_Shift, + XK_Control_L, Qt::Key_Control, + XK_Control_R, Qt::Key_Control, + XK_Meta_L, Qt::Key_Meta, + XK_Meta_R, Qt::Key_Meta, + XK_Alt_L, Qt::Key_Alt, + XK_Alt_R, Qt::Key_Alt, + XK_Caps_Lock, Qt::Key_CapsLock, + XK_Num_Lock, Qt::Key_NumLock, + XK_Scroll_Lock, Qt::Key_ScrollLock, + XK_Super_L, Qt::Key_Super_L, + XK_Super_R, Qt::Key_Super_R, + XK_Menu, Qt::Key_Menu, + XK_Hyper_L, Qt::Key_Hyper_L, + XK_Hyper_R, Qt::Key_Hyper_R, + XK_Help, Qt::Key_Help, + 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab + 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) + 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) + + // numeric and function keypad keys + + XK_KP_Space, Qt::Key_Space, + XK_KP_Tab, Qt::Key_Tab, + XK_KP_Enter, Qt::Key_Enter, + //XK_KP_F1, Qt::Key_F1, + //XK_KP_F2, Qt::Key_F2, + //XK_KP_F3, Qt::Key_F3, + //XK_KP_F4, Qt::Key_F4, + XK_KP_Home, Qt::Key_Home, + XK_KP_Left, Qt::Key_Left, + XK_KP_Up, Qt::Key_Up, + XK_KP_Right, Qt::Key_Right, + XK_KP_Down, Qt::Key_Down, + XK_KP_Prior, Qt::Key_PageUp, + XK_KP_Next, Qt::Key_PageDown, + XK_KP_End, Qt::Key_End, + XK_KP_Begin, Qt::Key_Clear, + XK_KP_Insert, Qt::Key_Insert, + XK_KP_Delete, Qt::Key_Delete, + XK_KP_Equal, Qt::Key_Equal, + XK_KP_Multiply, Qt::Key_Asterisk, + XK_KP_Add, Qt::Key_Plus, + XK_KP_Separator, Qt::Key_Comma, + XK_KP_Subtract, Qt::Key_Minus, + XK_KP_Decimal, Qt::Key_Period, + XK_KP_Divide, Qt::Key_Slash, + + // International input method support keys + + // International & multi-key character composition + XK_ISO_Level3_Shift, Qt::Key_AltGr, + XK_Multi_key, Qt::Key_Multi_key, + XK_Codeinput, Qt::Key_Codeinput, + XK_SingleCandidate, Qt::Key_SingleCandidate, + XK_MultipleCandidate, Qt::Key_MultipleCandidate, + XK_PreviousCandidate, Qt::Key_PreviousCandidate, + + // Misc Functions + XK_Mode_switch, Qt::Key_Mode_switch, + XK_script_switch, Qt::Key_Mode_switch, + + // Japanese keyboard support + XK_Kanji, Qt::Key_Kanji, + XK_Muhenkan, Qt::Key_Muhenkan, + //XK_Henkan_Mode, Qt::Key_Henkan_Mode, + XK_Henkan_Mode, Qt::Key_Henkan, + XK_Henkan, Qt::Key_Henkan, + XK_Romaji, Qt::Key_Romaji, + XK_Hiragana, Qt::Key_Hiragana, + XK_Katakana, Qt::Key_Katakana, + XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, + XK_Zenkaku, Qt::Key_Zenkaku, + XK_Hankaku, Qt::Key_Hankaku, + XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, + XK_Touroku, Qt::Key_Touroku, + XK_Massyo, Qt::Key_Massyo, + XK_Kana_Lock, Qt::Key_Kana_Lock, + XK_Kana_Shift, Qt::Key_Kana_Shift, + XK_Eisu_Shift, Qt::Key_Eisu_Shift, + XK_Eisu_toggle, Qt::Key_Eisu_toggle, + //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, + //XK_Zen_Koho, Qt::Key_Zen_Koho, + //XK_Mae_Koho, Qt::Key_Mae_Koho, + XK_Kanji_Bangou, Qt::Key_Codeinput, + XK_Zen_Koho, Qt::Key_MultipleCandidate, + XK_Mae_Koho, Qt::Key_PreviousCandidate, + +#ifdef XK_KOREAN + // Korean keyboard support + XK_Hangul, Qt::Key_Hangul, + XK_Hangul_Start, Qt::Key_Hangul_Start, + XK_Hangul_End, Qt::Key_Hangul_End, + XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, + XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, + XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, + //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, + XK_Hangul_Codeinput, Qt::Key_Codeinput, + XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, + XK_Hangul_Banja, Qt::Key_Hangul_Banja, + XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, + XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, + //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, + //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, + //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, + XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, + XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, + XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, + XK_Hangul_Special, Qt::Key_Hangul_Special, + //XK_Hangul_switch, Qt::Key_Hangul_switch, + XK_Hangul_switch, Qt::Key_Mode_switch, +#endif // XK_KOREAN + + // dead keys + XK_dead_grave, Qt::Key_Dead_Grave, + XK_dead_acute, Qt::Key_Dead_Acute, + XK_dead_circumflex, Qt::Key_Dead_Circumflex, + XK_dead_tilde, Qt::Key_Dead_Tilde, + XK_dead_macron, Qt::Key_Dead_Macron, + XK_dead_breve, Qt::Key_Dead_Breve, + XK_dead_abovedot, Qt::Key_Dead_Abovedot, + XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, + XK_dead_abovering, Qt::Key_Dead_Abovering, + XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, + XK_dead_caron, Qt::Key_Dead_Caron, + XK_dead_cedilla, Qt::Key_Dead_Cedilla, + XK_dead_ogonek, Qt::Key_Dead_Ogonek, + XK_dead_iota, Qt::Key_Dead_Iota, + XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, + XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, + XK_dead_belowdot, Qt::Key_Dead_Belowdot, + XK_dead_hook, Qt::Key_Dead_Hook, + XK_dead_horn, Qt::Key_Dead_Horn, + + // Special keys from X.org - This include multimedia keys, + // wireless/bluetooth/uwb keys, special launcher keys, etc. + XF86XK_Back, Qt::Key_Back, + XF86XK_Forward, Qt::Key_Forward, + XF86XK_Stop, Qt::Key_Stop, + XF86XK_Refresh, Qt::Key_Refresh, + XF86XK_Favorites, Qt::Key_Favorites, + XF86XK_AudioMedia, Qt::Key_LaunchMedia, + XF86XK_OpenURL, Qt::Key_OpenUrl, + XF86XK_HomePage, Qt::Key_HomePage, + XF86XK_Search, Qt::Key_Search, + XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, + XF86XK_AudioMute, Qt::Key_VolumeMute, + XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, + XF86XK_AudioPlay, Qt::Key_MediaPlay, + XF86XK_AudioStop, Qt::Key_MediaStop, + XF86XK_AudioPrev, Qt::Key_MediaPrevious, + XF86XK_AudioNext, Qt::Key_MediaNext, + XF86XK_AudioRecord, Qt::Key_MediaRecord, + XF86XK_Mail, Qt::Key_LaunchMail, + XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly + XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Memo, Qt::Key_Memo, + XF86XK_ToDoList, Qt::Key_ToDoList, + XF86XK_Calendar, Qt::Key_Calendar, + XF86XK_PowerDown, Qt::Key_PowerDown, + XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust, + XF86XK_Standby, Qt::Key_Standby, + XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp, + XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown, + XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff, + XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp, + XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown, + XF86XK_PowerOff, Qt::Key_PowerOff, + XF86XK_WakeUp, Qt::Key_WakeUp, + XF86XK_Eject, Qt::Key_Eject, + XF86XK_ScreenSaver, Qt::Key_ScreenSaver, + XF86XK_WWW, Qt::Key_WWW, + XF86XK_Sleep, Qt::Key_Sleep, + XF86XK_LightBulb, Qt::Key_LightBulb, + XF86XK_Shop, Qt::Key_Shop, + XF86XK_History, Qt::Key_History, + XF86XK_AddFavorite, Qt::Key_AddFavorite, + XF86XK_HotLinks, Qt::Key_HotLinks, + XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust, + XF86XK_Finance, Qt::Key_Finance, + XF86XK_Community, Qt::Key_Community, + XF86XK_AudioRewind, Qt::Key_AudioRewind, + XF86XK_BackForward, Qt::Key_BackForward, + XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft, + XF86XK_ApplicationRight, Qt::Key_ApplicationRight, + XF86XK_Book, Qt::Key_Book, + XF86XK_CD, Qt::Key_CD, + XF86XK_Calculater, Qt::Key_Calculator, + XF86XK_Clear, Qt::Key_Clear, + XF86XK_ClearGrab, Qt::Key_ClearGrab, + XF86XK_Close, Qt::Key_Close, + XF86XK_Copy, Qt::Key_Copy, + XF86XK_Cut, Qt::Key_Cut, + XF86XK_Display, Qt::Key_Display, + XF86XK_DOS, Qt::Key_DOS, + XF86XK_Documents, Qt::Key_Documents, + XF86XK_Excel, Qt::Key_Excel, + XF86XK_Explorer, Qt::Key_Explorer, + XF86XK_Game, Qt::Key_Game, + XF86XK_Go, Qt::Key_Go, + XF86XK_iTouch, Qt::Key_iTouch, + XF86XK_LogOff, Qt::Key_LogOff, + XF86XK_Market, Qt::Key_Market, + XF86XK_Meeting, Qt::Key_Meeting, + XF86XK_MenuKB, Qt::Key_MenuKB, + XF86XK_MenuPB, Qt::Key_MenuPB, + XF86XK_MySites, Qt::Key_MySites, + XF86XK_News, Qt::Key_News, + XF86XK_OfficeHome, Qt::Key_OfficeHome, + XF86XK_Option, Qt::Key_Option, + XF86XK_Paste, Qt::Key_Paste, + XF86XK_Phone, Qt::Key_Phone, + XF86XK_Reply, Qt::Key_Reply, + XF86XK_Reload, Qt::Key_Reload, + XF86XK_RotateWindows, Qt::Key_RotateWindows, + XF86XK_RotationPB, Qt::Key_RotationPB, + XF86XK_RotationKB, Qt::Key_RotationKB, + XF86XK_Save, Qt::Key_Save, + XF86XK_Send, Qt::Key_Send, + XF86XK_Spell, Qt::Key_Spell, + XF86XK_SplitScreen, Qt::Key_SplitScreen, + XF86XK_Support, Qt::Key_Support, + XF86XK_TaskPane, Qt::Key_TaskPane, + XF86XK_Terminal, Qt::Key_Terminal, + XF86XK_Tools, Qt::Key_Tools, + XF86XK_Travel, Qt::Key_Travel, + XF86XK_Video, Qt::Key_Video, + XF86XK_Word, Qt::Key_Word, + XF86XK_Xfer, Qt::Key_Xfer, + XF86XK_ZoomIn, Qt::Key_ZoomIn, + XF86XK_ZoomOut, Qt::Key_ZoomOut, + XF86XK_Away, Qt::Key_Away, + XF86XK_Messenger, Qt::Key_Messenger, + XF86XK_WebCam, Qt::Key_WebCam, + XF86XK_MailForward, Qt::Key_MailForward, + XF86XK_Pictures, Qt::Key_Pictures, + XF86XK_Music, Qt::Key_Music, + XF86XK_Battery, Qt::Key_Battery, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_WLAN, Qt::Key_WLAN, + XF86XK_UWB, Qt::Key_UWB, + XF86XK_AudioForward, Qt::Key_AudioForward, + XF86XK_AudioRepeat, Qt::Key_AudioRepeat, + XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay, + XF86XK_Subtitle, Qt::Key_Subtitle, + XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack, + XF86XK_Time, Qt::Key_Time, + XF86XK_Select, Qt::Key_Select, + XF86XK_View, Qt::Key_View, + XF86XK_TopMenu, Qt::Key_TopMenu, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_Suspend, Qt::Key_Suspend, + XF86XK_Hibernate, Qt::Key_Hibernate, + XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly + XF86XK_Launch1, Qt::Key_Launch3, + XF86XK_Launch2, Qt::Key_Launch4, + XF86XK_Launch3, Qt::Key_Launch5, + XF86XK_Launch4, Qt::Key_Launch6, + XF86XK_Launch5, Qt::Key_Launch7, + XF86XK_Launch6, Qt::Key_Launch8, + XF86XK_Launch7, Qt::Key_Launch9, + XF86XK_Launch8, Qt::Key_LaunchA, + XF86XK_Launch9, Qt::Key_LaunchB, + XF86XK_LaunchA, Qt::Key_LaunchC, + XF86XK_LaunchB, Qt::Key_LaunchD, + XF86XK_LaunchC, Qt::Key_LaunchE, + XF86XK_LaunchD, Qt::Key_LaunchF, + XF86XK_LaunchE, Qt::Key_LaunchG, + XF86XK_LaunchF, Qt::Key_LaunchH, + + // Qtopia keys + QTOPIAXK_Select, Qt::Key_Select, + QTOPIAXK_Yes, Qt::Key_Yes, + QTOPIAXK_No, Qt::Key_No, + QTOPIAXK_Cancel, Qt::Key_Cancel, + QTOPIAXK_Printer, Qt::Key_Printer, + QTOPIAXK_Execute, Qt::Key_Execute, + QTOPIAXK_Sleep, Qt::Key_Sleep, + QTOPIAXK_Play, Qt::Key_Play, + QTOPIAXK_Zoom, Qt::Key_Zoom, + QTOPIAXK_Context1, Qt::Key_Context1, + QTOPIAXK_Context2, Qt::Key_Context2, + QTOPIAXK_Context3, Qt::Key_Context3, + QTOPIAXK_Context4, Qt::Key_Context4, + QTOPIAXK_Call, Qt::Key_Call, + QTOPIAXK_Hangup, Qt::Key_Hangup, + QTOPIAXK_Flip, Qt::Key_Flip, + + 0, 0 +}; + +static const unsigned short katakanaKeysymsToUnicode[] = { + 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, + 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, + 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, + 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, + 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, + 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, + 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, + 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C +}; + +static const unsigned short cyrillicKeysymsToUnicode[] = { + 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, + 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static const unsigned short greekKeysymsToUnicode[] = { + 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, + 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, + 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, + 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short technicalKeysymsToUnicode[] = { + 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, + 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, + 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, + 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, + 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, + 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 +}; + +static const unsigned short specialKeysymsToUnicode[] = { + 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, + 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, + 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, + 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short publishingKeysymsToUnicode[] = { + 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, + 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, + 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, + 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, + 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, + 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, + 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, + 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, + 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, + 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, + 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, + 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 +}; + +static const unsigned short aplKeysymsToUnicode[] = { + 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, + 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, + 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, + 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, + 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short koreanKeysymsToUnicode[] = { + 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, + 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, + 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, + 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, + 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, + 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, + 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, + 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, + 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, + 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, + 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 +}; + +static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) +{ + switch (byte3) { + case 0x04: + // katakana + if (byte4 > 0xa0 && byte4 < 0xe0) + return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]); + else if (byte4 == 0x7e) + return QChar(0x203e); // Overline + break; + case 0x06: + // russian, use lookup table + if (byte4 > 0xa0) + return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x07: + // greek + if (byte4 > 0xa0) + return QChar(greekKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x08: + // technical + if (byte4 > 0xa0) + return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x09: + // special + if (byte4 >= 0xe0) + return QChar(specialKeysymsToUnicode[byte4 - 0xe0]); + break; + case 0x0a: + // publishing + if (byte4 > 0xa0) + return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0b: + // APL + if (byte4 > 0xa0) + return QChar(aplKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0e: + // Korean + if (byte4 > 0xa0) + return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]); + break; + default: + break; + } + return QChar(0x0); +} + +Qt::KeyboardModifiers QTestLiteKeyboard::translateModifiers(int s) +{ + Qt::KeyboardModifiers ret = 0; + if (s & ShiftMask) + ret |= Qt::ShiftModifier; + if (s & ControlMask) + ret |= Qt::ControlModifier; + if (s & m_alt_mask) + ret |= Qt::AltModifier; + if (s & m_meta_mask) + ret |= Qt::MetaModifier; + if (s & m_mode_switch_mask) + ret |= Qt::GroupSwitchModifier; + return ret; +} + +void QTestLiteKeyboard::setMask(KeySym sym, uint mask) +{ + if (m_alt_mask == 0 + && m_meta_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && (sym == XK_Alt_L || sym == XK_Alt_R)) { + m_alt_mask = mask; + } + if (m_meta_mask == 0 + && m_alt_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && (sym == XK_Meta_L || sym == XK_Meta_R)) { + m_meta_mask = mask; + } + if (m_super_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_hyper_mask != mask + && (sym == XK_Super_L || sym == XK_Super_R)) { + m_super_mask = mask; + } + if (m_hyper_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_super_mask != mask + && (sym == XK_Hyper_L || sym == XK_Hyper_R)) { + m_hyper_mask = mask; + } + if (m_mode_switch_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && sym == XK_Mode_switch) { + m_mode_switch_mask = mask; + } + if (m_num_lock_mask == 0 + && sym == XK_Num_Lock) { + m_num_lock_mask = mask; + } +} + +int QTestLiteKeyboard::translateKeySym(uint key) const +{ + int code = -1; + int i = 0; // any other keys + while (KeyTbl[i]) { + if (key == KeyTbl[i]) { + code = (int)KeyTbl[i+1]; + break; + } + i += 2; + } + if (m_meta_mask) { + // translate Super/Hyper keys to Meta if we're using them as the MetaModifier + if (m_meta_mask == m_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { + code = Qt::Key_Meta; + } else if (m_meta_mask == m_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { + code = Qt::Key_Meta; + } + } + return code; +} + +QString QTestLiteKeyboard::translateKeySym(KeySym keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count) +{ + // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars + + QTextCodec *mapper = QTextCodec::codecForLocale(); + QChar converted; + + if (/*count == 0 &&*/ keysym < 0xff00) { + unsigned char byte3 = (unsigned char)(keysym >> 8); + int mib = -1; + switch(byte3) { + case 0: // Latin 1 + case 1: // Latin 2 + case 2: //latin 3 + case 3: // latin4 + mib = byte3 + 4; break; + case 5: // arabic + mib = 82; break; + case 12: // Hebrew + mib = 85; break; + case 13: // Thai + mib = 2259; break; + case 4: // kana + case 6: // cyrillic + case 7: // greek + case 8: // technical, no mapping here at the moment + case 9: // Special + case 10: // Publishing + case 11: // APL + case 14: // Korean, no mapping + mib = -1; // manual conversion + mapper= 0; +#if !defined(QT_NO_XIM) + converted = keysymToUnicode(byte3, keysym & 0xff); +#endif + case 0x20: + // currency symbols + if (keysym >= 0x20a0 && keysym <= 0x20ac) { + mib = -1; // manual conversion + mapper = 0; + converted = (uint)keysym; + } + break; + default: + break; + } + if (mib != -1) { + mapper = QTextCodec::codecForMib(mib); + if (chars.isEmpty()) + chars.resize(1); + chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later + count++; + } + } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) { + converted = (ushort) (keysym - 0x1000000); + mapper = 0; + } + if (count < (int)chars.size()-1) + chars[count] = '\0'; + + QString text; + if (!mapper && converted.unicode() != 0x0) { + text = converted; + } else if (!chars.isEmpty()) { + // convert chars (8bit) to text (unicode). + if (mapper) + text = mapper->toUnicode(chars.data(), count, 0); + if (text.isEmpty()) { + // no mapper, or codec couldn't convert to unicode (this + // can happen when running in the C locale or with no LANG + // set). try converting from latin-1 + text = QString::fromLatin1(chars); + } + } + + modifiers = translateModifiers(xmodifiers); + + // Commentary in X11/keysymdef says that X codes match ASCII, so it + // is safe to use the locale functions to process X codes in ISO8859-1. + // + // This is mainly for compatibility - applications should not use the + // Qt keycodes between 128 and 255, but should rather use the + // QKeyEvent::text(). + // + if (keysym < 128 || (keysym < 256 && (!mapper || mapper->mibEnum()==4))) { + // upper-case key, if known + code = isprint((int)keysym) ? toupper((int)keysym) : 0; + } else if (keysym >= XK_F1 && keysym <= XK_F35) { + // function keys + code = Qt::Key_F1 + ((int)keysym - XK_F1); + } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) { + if (keysym >= XK_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XK_KP_0); + } else { + code = translateKeySym(keysym); + } + modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = translateKeySym(keysym); + + if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) { + // map shift+tab to shift+backtab, QShortcutMap knows about it + // and will handle it. + code = Qt::Key_Backtab; + text = QString(); + } + } + + return text; +} + +QTestLiteKeyboard::QTestLiteKeyboard(QTestLiteScreen *screen) + : m_screen(screen) + , m_alt_mask(0) + , m_super_mask(0) + , m_hyper_mask(0) + , m_meta_mask(0) +{ + changeLayout(); +} + +void QTestLiteKeyboard::changeLayout() +{ + XkbDescPtr xkbDesc = XkbGetMap(m_screen->display(), XkbAllClientInfoMask, XkbUseCoreKbd); + for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) { + const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0; + if (mask == 0) { + // key is not bound to a modifier + continue; + } + + for (int j = 0; j < XkbKeyGroupsWidth(xkbDesc, i); ++j) { + KeySym keySym = XkbKeySym(xkbDesc, i, j); + if (keySym == NoSymbol) + continue; + setMask(keySym, mask); + } + } + XkbFreeKeyboard(xkbDesc, XkbAllComponentsMask, true); + +} + +void QTestLiteKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev) +{ + int qtcode = 0; + Qt::KeyboardModifiers modifiers; + QByteArray chars; + chars.resize(513); + int count = 1; + KeySym keySym; + count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); + QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); + QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text); +} diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.h b/src/plugins/platforms/testlite/qtestlitekeyboard.h new file mode 100644 index 0000000..65ead16 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.h @@ -0,0 +1,35 @@ +#ifndef QTESTLITEKEYBOARD_H +#define QTESTLITEKEYBOARD_H + +#include "qtestliteintegration.h" + +class QTestLiteKeyboard +{ +public: + QTestLiteKeyboard(QTestLiteScreen *screen); + + void changeLayout(); + + void handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev); + + Qt::KeyboardModifiers translateModifiers(int s); + +private: + + void setMask(KeySym sym, uint mask); + int translateKeySym(uint key) const; + QString translateKeySym(KeySym keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count); + + QTestLiteScreen *m_screen; + + uint m_alt_mask; + uint m_super_mask; + uint m_hyper_mask; + uint m_meta_mask; + uint m_mode_switch_mask; + uint m_num_lock_mask; +}; + +#endif // QTESTLITEKEYBOARD_H diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp index 919506e..c0f696d 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.cpp +++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp @@ -43,6 +43,7 @@ #include "qtestlitecursor.h" #include "qtestlitewindow.h" +#include "qtestlitekeyboard.h" #include #include @@ -226,6 +227,7 @@ QTestLiteScreen::QTestLiteScreen() mWmMotifHintAtom = XInternAtom(mDisplay, "_MOTIF_WM_HINTS\0", False); mCursor = new QTestLiteCursor(this); + mKeyboard = new QTestLiteKeyboard(this); } QTestLiteScreen::~QTestLiteScreen() @@ -299,11 +301,11 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) break; case XKeyPress: - xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); + mKeyboard->handleKeyEvent(widget,QEvent::KeyPress, &xe->xkey); break; case XKeyRelease: - xw->handleKeyEvent(QEvent::KeyRelease, &xe->xkey); + mKeyboard->handleKeyEvent(widget,QEvent::KeyRelease, &xe->xkey); break; case EnterNotify: @@ -427,4 +429,9 @@ Atom QTestLiteScreen::atomForMotifWmHints() const return mWmMotifHintAtom; } +QTestLiteKeyboard * QTestLiteScreen::keyboard() const +{ + return mKeyboard; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitescreen.h b/src/plugins/platforms/testlite/qtestlitescreen.h index f8d9468..9a1a510 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.h +++ b/src/plugins/platforms/testlite/qtestlitescreen.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE class QTestLiteCursor; +class QTestLiteKeyboard; class QTestLiteScreen : public QPlatformScreen { @@ -80,6 +81,7 @@ public: Atom atomForMotifWmHints() const; + QTestLiteKeyboard *keyboard() const; public slots: void eventDispatcher(); @@ -90,6 +92,7 @@ private: int mDepth; QImage::Format mFormat; QTestLiteCursor *mCursor; + QTestLiteKeyboard *mKeyboard; Display * mDisplay; int mScreen; diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 5446615..42f2302 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -43,6 +43,7 @@ #include "qtestliteintegration.h" #include "qtestlitescreen.h" +#include "qtestlitekeyboard.h" #include #include @@ -141,26 +142,7 @@ static Qt::MouseButtons translateMouseButtons(int s) return ret; } -static Qt::KeyboardModifiers translateModifiers(int s) -{ - const uchar qt_alt_mask = Mod1Mask; - const uchar qt_meta_mask = Mod4Mask; - - Qt::KeyboardModifiers ret = 0; - if (s & ShiftMask) - ret |= Qt::ShiftModifier; - if (s & ControlMask) - ret |= Qt::ControlModifier; - if (s & qt_alt_mask) - ret |= Qt::AltModifier; - if (s & qt_meta_mask) - ret |= Qt::MetaModifier; -#if 0 - if (s & qt_mode_switch_mask) - ret |= Qt::GroupSwitchModifier; -#endif - return ret; -} + void QTestLiteWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e) { @@ -168,7 +150,7 @@ void QTestLiteWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e) Qt::MouseButton button = Qt::NoButton; Qt::MouseButtons buttons = translateMouseButtons(e->state); - Qt::KeyboardModifiers modifiers = translateModifiers(e->state); + Qt::KeyboardModifiers modifiers = mScreen->keyboard()->translateModifiers(e->state); if (type != QEvent::MouseMove) { switch (e->button) { case Button1: button = Qt::LeftButton; break; @@ -231,312 +213,7 @@ void QTestLiteWindow::handleFocusOutEvent() QWindowSystemInterface::handleWindowActivated(0); } -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Key event stuff -- not pretty either -// -// What we want to do is to port Robert's keytable code properly - -// keyboard mapping table -static const unsigned int keyTbl[] = { - - // misc keys - - XK_Escape, Qt::Key_Escape, - XK_Tab, Qt::Key_Tab, - XK_ISO_Left_Tab, Qt::Key_Backtab, - XK_BackSpace, Qt::Key_Backspace, - XK_Return, Qt::Key_Return, - XK_Insert, Qt::Key_Insert, - XK_Delete, Qt::Key_Delete, - XK_Clear, Qt::Key_Delete, - XK_Pause, Qt::Key_Pause, - XK_Print, Qt::Key_Print, - 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq - 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq - - // cursor movement - - XK_Home, Qt::Key_Home, - XK_End, Qt::Key_End, - XK_Left, Qt::Key_Left, - XK_Up, Qt::Key_Up, - XK_Right, Qt::Key_Right, - XK_Down, Qt::Key_Down, - XK_Prior, Qt::Key_PageUp, - XK_Next, Qt::Key_PageDown, - - // modifiers - - XK_Shift_L, Qt::Key_Shift, - XK_Shift_R, Qt::Key_Shift, - XK_Shift_Lock, Qt::Key_Shift, - XK_Control_L, Qt::Key_Control, - XK_Control_R, Qt::Key_Control, - XK_Meta_L, Qt::Key_Meta, - XK_Meta_R, Qt::Key_Meta, - XK_Alt_L, Qt::Key_Alt, - XK_Alt_R, Qt::Key_Alt, - XK_Caps_Lock, Qt::Key_CapsLock, - XK_Num_Lock, Qt::Key_NumLock, - XK_Scroll_Lock, Qt::Key_ScrollLock, - XK_Super_L, Qt::Key_Super_L, - XK_Super_R, Qt::Key_Super_R, - XK_Menu, Qt::Key_Menu, - XK_Hyper_L, Qt::Key_Hyper_L, - XK_Hyper_R, Qt::Key_Hyper_R, - XK_Help, Qt::Key_Help, - 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab - 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) - 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) - - // numeric and function keypad keys - - XK_KP_Space, Qt::Key_Space, - XK_KP_Tab, Qt::Key_Tab, - XK_KP_Enter, Qt::Key_Enter, - //XK_KP_F1, Qt::Key_F1, - //XK_KP_F2, Qt::Key_F2, - //XK_KP_F3, Qt::Key_F3, - //XK_KP_F4, Qt::Key_F4, - XK_KP_Home, Qt::Key_Home, - XK_KP_Left, Qt::Key_Left, - XK_KP_Up, Qt::Key_Up, - XK_KP_Right, Qt::Key_Right, - XK_KP_Down, Qt::Key_Down, - XK_KP_Prior, Qt::Key_PageUp, - XK_KP_Next, Qt::Key_PageDown, - XK_KP_End, Qt::Key_End, - XK_KP_Begin, Qt::Key_Clear, - XK_KP_Insert, Qt::Key_Insert, - XK_KP_Delete, Qt::Key_Delete, - XK_KP_Equal, Qt::Key_Equal, - XK_KP_Multiply, Qt::Key_Asterisk, - XK_KP_Add, Qt::Key_Plus, - XK_KP_Separator, Qt::Key_Comma, - XK_KP_Subtract, Qt::Key_Minus, - XK_KP_Decimal, Qt::Key_Period, - XK_KP_Divide, Qt::Key_Slash, - - // International input method support keys - - // International & multi-key character composition - XK_ISO_Level3_Shift, Qt::Key_AltGr, - XK_Multi_key, Qt::Key_Multi_key, - XK_Codeinput, Qt::Key_Codeinput, - XK_SingleCandidate, Qt::Key_SingleCandidate, - XK_MultipleCandidate, Qt::Key_MultipleCandidate, - XK_PreviousCandidate, Qt::Key_PreviousCandidate, - - // Misc Functions - XK_Mode_switch, Qt::Key_Mode_switch, - XK_script_switch, Qt::Key_Mode_switch, - - // Japanese keyboard support - XK_Kanji, Qt::Key_Kanji, - XK_Muhenkan, Qt::Key_Muhenkan, - //XK_Henkan_Mode, Qt::Key_Henkan_Mode, - XK_Henkan_Mode, Qt::Key_Henkan, - XK_Henkan, Qt::Key_Henkan, - XK_Romaji, Qt::Key_Romaji, - XK_Hiragana, Qt::Key_Hiragana, - XK_Katakana, Qt::Key_Katakana, - XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, - XK_Zenkaku, Qt::Key_Zenkaku, - XK_Hankaku, Qt::Key_Hankaku, - XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, - XK_Touroku, Qt::Key_Touroku, - XK_Massyo, Qt::Key_Massyo, - XK_Kana_Lock, Qt::Key_Kana_Lock, - XK_Kana_Shift, Qt::Key_Kana_Shift, - XK_Eisu_Shift, Qt::Key_Eisu_Shift, - XK_Eisu_toggle, Qt::Key_Eisu_toggle, - //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, - //XK_Zen_Koho, Qt::Key_Zen_Koho, - //XK_Mae_Koho, Qt::Key_Mae_Koho, - XK_Kanji_Bangou, Qt::Key_Codeinput, - XK_Zen_Koho, Qt::Key_MultipleCandidate, - XK_Mae_Koho, Qt::Key_PreviousCandidate, - -#ifdef XK_KOREAN - // Korean keyboard support - XK_Hangul, Qt::Key_Hangul, - XK_Hangul_Start, Qt::Key_Hangul_Start, - XK_Hangul_End, Qt::Key_Hangul_End, - XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, - XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, - XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, - //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, - XK_Hangul_Codeinput, Qt::Key_Codeinput, - XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, - XK_Hangul_Banja, Qt::Key_Hangul_Banja, - XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, - XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, - //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, - //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, - //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, - XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, - XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, - XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, - XK_Hangul_Special, Qt::Key_Hangul_Special, - //XK_Hangul_switch, Qt::Key_Hangul_switch, - XK_Hangul_switch, Qt::Key_Mode_switch, -#endif // XK_KOREAN - - // dead keys - XK_dead_grave, Qt::Key_Dead_Grave, - XK_dead_acute, Qt::Key_Dead_Acute, - XK_dead_circumflex, Qt::Key_Dead_Circumflex, - XK_dead_tilde, Qt::Key_Dead_Tilde, - XK_dead_macron, Qt::Key_Dead_Macron, - XK_dead_breve, Qt::Key_Dead_Breve, - XK_dead_abovedot, Qt::Key_Dead_Abovedot, - XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, - XK_dead_abovering, Qt::Key_Dead_Abovering, - XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, - XK_dead_caron, Qt::Key_Dead_Caron, - XK_dead_cedilla, Qt::Key_Dead_Cedilla, - XK_dead_ogonek, Qt::Key_Dead_Ogonek, - XK_dead_iota, Qt::Key_Dead_Iota, - XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, - XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, - XK_dead_belowdot, Qt::Key_Dead_Belowdot, - XK_dead_hook, Qt::Key_Dead_Hook, - XK_dead_horn, Qt::Key_Dead_Horn, - -#if 0 - // Special multimedia keys - // currently only tested with MS internet keyboard - - // browsing keys - XF86XK_Back, Qt::Key_Back, - XF86XK_Forward, Qt::Key_Forward, - XF86XK_Stop, Qt::Key_Stop, - XF86XK_Refresh, Qt::Key_Refresh, - XF86XK_Favorites, Qt::Key_Favorites, - XF86XK_AudioMedia, Qt::Key_LaunchMedia, - XF86XK_OpenURL, Qt::Key_OpenUrl, - XF86XK_HomePage, Qt::Key_HomePage, - XF86XK_Search, Qt::Key_Search, - - // media keys - XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, - XF86XK_AudioMute, Qt::Key_VolumeMute, - XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, - XF86XK_AudioPlay, Qt::Key_MediaPlay, - XF86XK_AudioStop, Qt::Key_MediaStop, - XF86XK_AudioPrev, Qt::Key_MediaPrevious, - XF86XK_AudioNext, Qt::Key_MediaNext, - XF86XK_AudioRecord, Qt::Key_MediaRecord, - - // launch keys - XF86XK_Mail, Qt::Key_LaunchMail, - XF86XK_MyComputer, Qt::Key_Launch0, - XF86XK_Calculator, Qt::Key_Launch1, - XF86XK_Standby, Qt::Key_Standby, - - XF86XK_Launch0, Qt::Key_Launch2, - XF86XK_Launch1, Qt::Key_Launch3, - XF86XK_Launch2, Qt::Key_Launch4, - XF86XK_Launch3, Qt::Key_Launch5, - XF86XK_Launch4, Qt::Key_Launch6, - XF86XK_Launch5, Qt::Key_Launch7, - XF86XK_Launch6, Qt::Key_Launch8, - XF86XK_Launch7, Qt::Key_Launch9, - XF86XK_Launch8, Qt::Key_LaunchA, - XF86XK_Launch9, Qt::Key_LaunchB, - XF86XK_LaunchA, Qt::Key_LaunchC, - XF86XK_LaunchB, Qt::Key_LaunchD, - XF86XK_LaunchC, Qt::Key_LaunchE, - XF86XK_LaunchD, Qt::Key_LaunchF, -#endif - -#if 0 - // Qtopia keys - QTOPIAXK_Select, Qt::Key_Select, - QTOPIAXK_Yes, Qt::Key_Yes, - QTOPIAXK_No, Qt::Key_No, - QTOPIAXK_Cancel, Qt::Key_Cancel, - QTOPIAXK_Printer, Qt::Key_Printer, - QTOPIAXK_Execute, Qt::Key_Execute, - QTOPIAXK_Sleep, Qt::Key_Sleep, - QTOPIAXK_Play, Qt::Key_Play, - QTOPIAXK_Zoom, Qt::Key_Zoom, - QTOPIAXK_Context1, Qt::Key_Context1, - QTOPIAXK_Context2, Qt::Key_Context2, - QTOPIAXK_Context3, Qt::Key_Context3, - QTOPIAXK_Context4, Qt::Key_Context4, - QTOPIAXK_Call, Qt::Key_Call, - QTOPIAXK_Hangup, Qt::Key_Hangup, - QTOPIAXK_Flip, Qt::Key_Flip, -#endif - 0, 0 -}; - -static int lookupCode(unsigned int xkeycode) -{ - if (xkeycode >= XK_F1 && xkeycode <= XK_F35) - return Qt::Key_F1 + (int(xkeycode) - XK_F1); - - const unsigned int *p = keyTbl; - while (*p) { - if (*p == xkeycode) - return *++p; - p += 2; - } - - return 0; -} - -static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) -{ - switch (qtcode) { - case Qt::Key_Control: - return Qt::ControlModifier; - case Qt::Key_Alt: - return Qt::AltModifier; - case Qt::Key_Shift: - return Qt::ShiftModifier; - case Qt::Key_Meta: - return Qt::MetaModifier; - default: - return Qt::NoModifier; - } -} - -void QTestLiteWindow::handleKeyEvent(QEvent::Type type, void *ev) -{ - XKeyEvent *e = static_cast(ev); - - KeySym keySym; - QByteArray chars; - chars.resize(513); - int count = XLookupString(e, chars.data(), chars.size(), &keySym, 0); - Q_UNUSED(count); -// qDebug() << "QTLWS::handleKeyEvent" << count << hex << "XKeysym:" << keySym; -// if (count) -// qDebug() << hex << int(chars[0]) << "String:" << chars; - - Qt::KeyboardModifiers modifiers = translateModifiers(e->state); - - int qtcode = lookupCode(keySym); -// qDebug() << "lookup: " << hex << keySym << qtcode << "mod" << modifiers; - - //X11 specifies state *before*, Qt expects state *after* the event - - modifiers ^= modifierFromKeyCode(qtcode); - - if (qtcode) { - QWindowSystemInterface::handleKeyEvent(widget(), e->time, type, qtcode, modifiers); - } else if (chars[0]) { - int qtcode = chars.toUpper()[0]; //Not exactly right... - if (modifiers & Qt::ControlModifier && qtcode < ' ') - qtcode = chars[0] + '@'; - QWindowSystemInterface::handleKeyEvent(0, e->time, type, qtcode, modifiers, QString::fromLatin1(chars)); - } else { - qWarning() << "unknown X keycode" << hex << e->keycode << keySym; - } -} void QTestLiteWindow::setGeometry(const QRect &rect) { diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index 7e990ee..35ba677 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -93,7 +93,6 @@ public: void mousePressEvent(XButtonEvent*); void handleMouseEvent(QEvent::Type, XButtonEvent *ev); - void handleKeyEvent(QEvent::Type, void *); void handleCloseEvent(); void handleEnterEvent(); void handleLeaveEvent(); diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index ef977bf..d2f2562 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -9,14 +9,16 @@ SOURCES = \ qtestlitewindowsurface.cpp \ qtestlitewindow.cpp \ qtestlitecursor.cpp \ - qtestlitescreen.cpp + qtestlitescreen.cpp \ + qtestlitekeyboard.cpp HEADERS = \ qtestliteintegration.h \ qtestlitewindowsurface.h \ qtestlitewindow.h \ qtestlitecursor.h \ - qtestlitescreen.h + qtestlitescreen.h \ + qtestlitekeyboard.h LIBS += -lX11 -lXext -- cgit v0.12 From 91a438cad2139ae33f8a18c8ca8f81a41795ebe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 17 Dec 2010 08:51:53 +0100 Subject: Add basic mouse context menues to lighthouse --- src/gui/kernel/qapplication_qpa.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index a587e8e..a164c2d 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -735,7 +735,15 @@ void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mouse cursor.data()->pointerEvent(ev); } + int oldOpenPopupCount = openPopupCount; QApplication::sendSpontaneousEvent(mouseWidget, &ev); + +#ifndef QT_NO_CONTEXTMENU + if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { + QContextMenuEvent e(QContextMenuEvent::Mouse, localPoint, globalPoint, modifiers); + QApplication::sendSpontaneousEvent(mouseWidget, &e); + } +#endif // QT_NO_CONTEXTMENU } -- cgit v0.12 From d79b18d59cc39396f4993a294f24cfb804be728f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Mon, 20 Dec 2010 10:24:48 +0100 Subject: Make TestLite show windows in correct position --- src/plugins/platforms/testlite/qtestlitewindow.cpp | 28 +++++++++++++++++++--- src/plugins/platforms/testlite/qtestlitewindow.h | 2 ++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 42f2302..6f9ad58 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -517,10 +517,13 @@ void QTestLiteWindow::setVisible(bool visible) #ifdef MYX11_DEBUG qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window; #endif - if (visible) - XMapWindow(mScreen->display(), x_window); - else + if (visible) { + //ensure that the window is viewed in correct position. + doSizeHints(); + XMapWindow(mScreen->display(), x_window); + } else { XUnmapWindow(mScreen->display(), x_window); + } } void QTestLiteWindow::setCursor(const Cursor &cursor) @@ -552,4 +555,23 @@ GC QTestLiteWindow::graphicsContext() const return gc; } +void QTestLiteWindow::doSizeHints() +{ + Q_ASSERT(widget()->testAttribute(Qt::WA_WState_Created)); + XSizeHints s; + s.flags = 0; + QRect g = geometry(); + s.x = g.x(); + s.y = g.y(); + s.width = g.width(); + s.height = g.height(); + s.flags |= USPosition; + s.flags |= PPosition; + s.flags |= USSize; + s.flags |= PSize; + s.flags |= PWinGravity; + s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; + XSetWMNormalHints(mScreen->display(), x_window, &s); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index 35ba677..4b952dc 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -126,6 +126,8 @@ protected: void setMWMHints(const QtMWMHints &mwmhints); QtMWMHints getMWMHints() const; + void doSizeHints(); + private: Window x_window; GC gc; -- cgit v0.12 From a7fbc64969168fef3285901e383a044692bebfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Mon, 20 Dec 2010 10:36:00 +0100 Subject: Lighthouse: fix keyboard problem in testlite --- src/plugins/platforms/testlite/qtestlitekeyboard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp index c18de59..be7a686 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -834,7 +834,7 @@ QString QTestLiteKeyboard::translateKeySym(KeySym keysym, uint xmodifiers, if (chars.isEmpty()) chars.resize(1); chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later - count++; + count = 1; } } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) { converted = (ushort) (keysym - 0x1000000); @@ -935,9 +935,9 @@ void QTestLiteKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyE Qt::KeyboardModifiers modifiers; QByteArray chars; chars.resize(513); - int count = 1; + int count = 0; KeySym keySym; count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); - QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text); + QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text.left(count)); } -- cgit v0.12 From f03d9c91d7576974d1a156749c1e159468f2451a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 28 Dec 2010 15:26:19 +0100 Subject: Initial support for WS specific clipboard support in Lighthouse default implementation in QPlatformIntegration still supports in process copy/paste --- src/gui/kernel/kernel.pri | 6 +- src/gui/kernel/qclipboard_qpa.cpp | 82 ++++------------------ src/gui/kernel/qdnd_p.h | 2 +- src/gui/kernel/qplatformclipboard_qpa.cpp | 101 ++++++++++++++++++++++++++++ src/gui/kernel/qplatformclipboard_qpa.h | 70 +++++++++++++++++++ src/gui/kernel/qplatformintegration_qpa.cpp | 18 +++++ src/gui/kernel/qplatformintegration_qpa.h | 4 +- 7 files changed, 209 insertions(+), 74 deletions(-) create mode 100644 src/gui/kernel/qplatformclipboard_qpa.cpp create mode 100644 src/gui/kernel/qplatformclipboard_qpa.h diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 4261e93..0ff3d88 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -222,7 +222,8 @@ qpa { kernel/qplatformglcontext_qpa.h \ kernel/qdesktopwidget_qpa_p.h \ kernel/qplatformeventloopintegration_qpa.h \ - kernel/qplatformcursor_qpa.h + kernel/qplatformcursor_qpa.h \ + kernel/qplatformclipboard_qpa.h SOURCES += \ kernel/qapplication_qpa.cpp \ @@ -244,7 +245,8 @@ qpa { kernel/qplatformwindowformat_qpa.cpp \ kernel/qplatformeventloopintegration_qpa.cpp \ kernel/qplatformglcontext_qpa.cpp \ - kernel/qplatformcursor_qpa.cpp + kernel/qplatformcursor_qpa.cpp \ + kernel/qplatformclipboard_qpa.cpp contains(QT_CONFIG, glib) { SOURCES += \ diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qclipboard_qpa.cpp index 92b9e83..b8ce60e 100644 --- a/src/gui/kernel/qclipboard_qpa.cpp +++ b/src/gui/kernel/qclipboard_qpa.cpp @@ -44,73 +44,16 @@ #ifndef QT_NO_CLIPBOARD #include "qmimedata.h" -#include "qapplication.h" +#include "private/qapplication_p.h" +#include "qplatformclipboard_qpa.h" QT_BEGIN_NAMESPACE QT_USE_NAMESPACE - -class QClipboardData -{ -public: - QClipboardData(); - ~QClipboardData(); - - void setSource(QMimeData* s) - { - if (s == src) - return; - delete src; - src = s; - } - QMimeData* source() - { return src; } - - void clear(); - -private: - QMimeData* src; -}; - -QClipboardData::QClipboardData() -{ - src = 0; -} - -QClipboardData::~QClipboardData() -{ - delete src; -} - -void QClipboardData::clear() -{ - delete src; - src = 0; -} - - -static QClipboardData *internalCbData = 0; - -static void cleanupClipboardData() -{ - delete internalCbData; - internalCbData = 0; -} - -static QClipboardData *clipboardData() -{ - if (internalCbData == 0) { - internalCbData = new QClipboardData; - qAddPostRoutine(cleanupClipboardData); - } - return internalCbData; -} - - void QClipboard::clear(Mode mode) { - setText(QString(), mode); + setMimeData(0,mode); } @@ -121,26 +64,25 @@ bool QClipboard::event(QEvent *e) const QMimeData* QClipboard::mimeData(Mode mode) const { - if (mode != Clipboard) return 0; - - QClipboardData *d = clipboardData(); - return d->source(); + QPlatformClipboard *clipboard = QApplicationPrivate::platformIntegration()->clipboard(); + if (!clipboard->supportsMode(mode)) return 0; + return clipboard->mimeData(mode); } void QClipboard::setMimeData(QMimeData* src, Mode mode) { - if (mode != Clipboard) return; - - QClipboardData *d = clipboardData(); + QPlatformClipboard *clipboard = QApplicationPrivate::platformIntegration()->clipboard(); + if (!clipboard->supportsMode(mode)) return; - d->setSource(src); + clipboard->setMimeData(src,mode); - emitChanged(QClipboard::Clipboard); + emitChanged(mode); } bool QClipboard::supportsMode(Mode mode) const { - return (mode == Clipboard); + QPlatformClipboard *clipboard = QApplicationPrivate::platformIntegration()->clipboard(); + return clipboard->supportsMode(mode); } bool QClipboard::ownsMode(Mode mode) const diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 598a9de..7b23630 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -76,7 +76,7 @@ class QEventLoop; #if !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD)) -class QInternalMimeData : public QMimeData +class Q_GUI_EXPORT QInternalMimeData : public QMimeData { Q_OBJECT public: diff --git a/src/gui/kernel/qplatformclipboard_qpa.cpp b/src/gui/kernel/qplatformclipboard_qpa.cpp new file mode 100644 index 0000000..fff4e19 --- /dev/null +++ b/src/gui/kernel/qplatformclipboard_qpa.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qplatformclipboard_qpa.h" + +QT_BEGIN_NAMESPACE + +class QClipboardData +{ +public: + QClipboardData(); + ~QClipboardData(); + + void setSource(QMimeData* s) + { + if (s == src) + return; + delete src; + src = s; + } + QMimeData* source() + { return src; } + +private: + QMimeData* src; +}; + +QClipboardData::QClipboardData() +{ + src = 0; +} + +QClipboardData::~QClipboardData() +{ + delete src; +} + +Q_GLOBAL_STATIC(QClipboardData,q_clipboardData); + +QPlatformClipboard::~QPlatformClipboard() +{ + +} + +const QMimeData *QPlatformClipboard::mimeData(QClipboard::Mode mode) const +{ + //we know its clipboard + Q_UNUSED(mode); + return q_clipboardData()->source(); +} + +void QPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + //we know its clipboard + Q_UNUSED(mode); + q_clipboardData()->setSource(data); +} + +bool QPlatformClipboard::supportsMode(QClipboard::Mode mode) const +{ + return mode == QClipboard::Clipboard; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformclipboard_qpa.h b/src/gui/kernel/qplatformclipboard_qpa.h new file mode 100644 index 0000000..3f7bfbb --- /dev/null +++ b/src/gui/kernel/qplatformclipboard_qpa.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMCLIPBOARD_QPA_H +#define QPLATFORMCLIPBOARD_QPA_H + +#include + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QPlatformClipboard +{ +public: + virtual ~QPlatformClipboard(); + + virtual const QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard ) const; + virtual void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard); + virtual bool supportsMode(QClipboard::Mode mode) const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif //QPLATFORMCLIPBOARD_QPA_H diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp index 9b6e590..0cac57d 100644 --- a/src/gui/kernel/qplatformintegration_qpa.cpp +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -42,6 +42,7 @@ #include "qplatformintegration_qpa.h" #include +#include QT_BEGIN_NAMESPACE @@ -94,6 +95,23 @@ QPlatformFontDatabase *QPlatformIntegration::fontDatabase() const } /*! + Accessor for the platform integrations clipboard. + + Default implementation returns a default QPlatformClipboard. + + \sa QPlatformClipboard + +*/ +QPlatformClipboard *QPlatformIntegration::clipboard() const +{ + static QPlatformClipboard *clipboard = 0; + if (!clipboard) { + clipboard = new QPlatformClipboard; + } + return clipboard; +} + +/*! \class QPlatformIntegration \since 4.8 \internal diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h index f01b4f4..7050245 100644 --- a/src/gui/kernel/qplatformintegration_qpa.h +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -59,6 +59,7 @@ class QBlittable; class QWidget; class QPlatformEventLoopIntegration; class QPlatformFontDatabase; +class QPlatformClipboard; class Q_GUI_EXPORT QPlatformIntegration { @@ -76,8 +77,9 @@ public: virtual bool isVirtualDesktop() { return false; } virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const; -//Fontdatabase integration. +//Deeper window system integrations virtual QPlatformFontDatabase *fontDatabase() const; + virtual QPlatformClipboard *clipboard() const; // Experimental in mainthread eventloop integration // This should only be used if it is only possible to do window system event processing in -- cgit v0.12 From 1097310a4ff0bda0f3c5a0204c42ed40035e6dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 28 Dec 2010 15:27:52 +0100 Subject: Fix keyboard when using modifiers for testlite --- src/plugins/platforms/testlite/qtestlitekeyboard.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp index be7a686..93d21b3 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -929,15 +929,32 @@ void QTestLiteKeyboard::changeLayout() } +static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) +{ + switch (qtcode) { + case Qt::Key_Control: + return Qt::ControlModifier; + case Qt::Key_Alt: + return Qt::AltModifier; + case Qt::Key_Shift: + return Qt::ShiftModifier; + case Qt::Key_Meta: + return Qt::MetaModifier; + default: + return Qt::NoModifier; + } +} + void QTestLiteKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev) { int qtcode = 0; - Qt::KeyboardModifiers modifiers; + Qt::KeyboardModifiers modifiers = translateModifiers(ev->state); QByteArray chars; chars.resize(513); int count = 0; KeySym keySym; count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); + modifiers ^= modifierFromKeyCode(qtcode); QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text.left(count)); } -- cgit v0.12 From c33402ff531c1667305907963c221b88dd168691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Tue, 28 Dec 2010 15:44:47 +0100 Subject: Copy/Paste in testlite and also added QTestLiteStaticInfo which is a class to resolve atoms etc. --- .../platforms/testlite/qtestliteclipboard.cpp | 519 +++++++++++++++++++++ .../platforms/testlite/qtestliteclipboard.h | 52 +++ .../platforms/testlite/qtestliteintegration.cpp | 13 + .../platforms/testlite/qtestliteintegration.h | 4 +- src/plugins/platforms/testlite/qtestlitemime.cpp | 362 ++++++++++++++ src/plugins/platforms/testlite/qtestlitemime.h | 42 ++ src/plugins/platforms/testlite/qtestlitescreen.cpp | 133 ++++-- src/plugins/platforms/testlite/qtestlitescreen.h | 16 +- .../platforms/testlite/qtestlitestaticinfo.cpp | 417 +++++++++++++++++ .../platforms/testlite/qtestlitestaticinfo.h | 371 +++++++++++++++ src/plugins/platforms/testlite/qtestlitewindow.cpp | 36 +- src/plugins/platforms/testlite/testlite.pro | 10 +- 12 files changed, 1899 insertions(+), 76 deletions(-) create mode 100644 src/plugins/platforms/testlite/qtestliteclipboard.cpp create mode 100644 src/plugins/platforms/testlite/qtestliteclipboard.h create mode 100644 src/plugins/platforms/testlite/qtestlitemime.cpp create mode 100644 src/plugins/platforms/testlite/qtestlitemime.h create mode 100644 src/plugins/platforms/testlite/qtestlitestaticinfo.cpp create mode 100644 src/plugins/platforms/testlite/qtestlitestaticinfo.h diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp new file mode 100644 index 0000000..fdd6d30 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp @@ -0,0 +1,519 @@ +#include "qtestliteclipboard.h" + +#include "qtestlitescreen.h" +#include "qtestlitemime.h" + +#include + +#include + +const int QTestLiteClipboard::clipboard_timeout = 5000; + +QTestLiteClipboard::QTestLiteClipboard(QTestLiteScreen *screen) + : QPlatformClipboard() + , m_screen(screen) + , m_xClipboard(0) + , m_clientClipboard(0) + , m_xSelection(0) + , m_clientSelection(0) + , m_requestor(XNone) + , m_owner(XNone) +{ +} + +const QMimeData * QTestLiteClipboard::mimeData(QClipboard::Mode mode) const +{ + if (mode == QClipboard::Clipboard) { + if (!m_xClipboard) { + QTestLiteClipboard *that = const_cast(this); + that->m_xClipboard = new QTestLiteMime(mode,that); + } + Window clipboardOwner = XGetSelectionOwner(screen()->display(),QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD)); + if (clipboardOwner == owner()) { + return m_clientClipboard; + } else { + return m_xClipboard; + } + } + return 0; +} + +void QTestLiteClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + Atom modeAtom; + QMimeData **d; + switch (mode) { + case QClipboard::Selection: + modeAtom = XA_PRIMARY; + d = &m_clientSelection; + break; + + case QClipboard::Clipboard: + modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); + d = &m_clientClipboard; + break; + + default: + qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode); + return; + } + + Window newOwner; + + if (! data) { // no data, clear clipboard contents + newOwner = XNone; + } else { + newOwner = owner(); + + *d = data; + } + + XSetSelectionOwner(m_screen->display(), modeAtom, newOwner, CurrentTime); + + if (XGetSelectionOwner(m_screen->display(), modeAtom) != newOwner) { +// qWarning("QClipboard::setData: Cannot set X11 selection owner for %s", +// xdndAtomToString(atom).data()); + *d = 0; + return; + } + +} + +QTestLiteScreen * QTestLiteClipboard::screen() const +{ + return m_screen; +} + +Window QTestLiteClipboard::requestor() const +{ + if (!m_requestor) { + int x = 0, y = 0, w = 3, h = 3; + QTestLiteClipboard *that = const_cast(this); + Window window = XCreateSimpleWindow(m_screen->display(), m_screen->rootWindow(), + x, y, w, h, 0 /*border_width*/, + m_screen->blackPixel(), m_screen->whitePixel()); + that->setRequestor(window); + } + return m_requestor; +} + +void QTestLiteClipboard::setRequestor(Window window) +{ + if (m_requestor != XNone) { + XDestroyWindow(m_screen->display(),m_requestor); + } + m_requestor = window; +} + +Window QTestLiteClipboard::owner() const +{ + if (!m_owner) { + int x = 0, y = 0, w = 3, h = 3; + QTestLiteClipboard *that = const_cast(this); + Window window = XCreateSimpleWindow(m_screen->display(), m_screen->rootWindow(), + x, y, w, h, 0 /*border_width*/, + m_screen->blackPixel(), m_screen->whitePixel()); + that->setOwner(window); + } + return m_owner; +} + +void QTestLiteClipboard::setOwner(Window window) +{ + if (m_owner != XNone){ + XDestroyWindow(m_screen->display(),m_owner); + } + m_owner = window; +} + +Atom QTestLiteClipboard::sendTargetsSelection(QMimeData *d, Window window, Atom property) +{ + QVector types; + QStringList formats = QInternalMimeData::formatsHelper(d); + for (int i = 0; i < formats.size(); ++i) { + QList atoms = QTestLiteMime::xdndMimeAtomsForFormat(screen()->display(),formats.at(i)); + for (int j = 0; j < atoms.size(); ++j) { + if (!types.contains(atoms.at(j))) + types.append(atoms.at(j)); + } + } + types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS)); + types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE)); + types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP)); + types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::SAVE_TARGETS)); + + XChangeProperty(screen()->display(), window, property, XA_ATOM, 32, + PropModeReplace, (uchar *) types.data(), types.size()); + return property; +} + +Atom QTestLiteClipboard::sendSelection(QMimeData *d, Atom target, Window window, Atom property) +{ + Atom atomFormat = target; + int dataFormat = 0; + QByteArray data; + + QString fmt = QTestLiteMime::xdndMimeAtomToString(screen()->display(), target); + if (fmt.isEmpty()) { // Not a MIME type we have + qDebug() << "QClipboard: send_selection(): converting to type '%s' is not supported" << fmt.data(); + return XNone; + } + qDebug() << "QClipboard: send_selection(): converting to type '%s'" << fmt.data(); + + if (QTestLiteMime::xdndMimeDataForAtom(screen()->display(),target, d, &data, &atomFormat, &dataFormat)) { + + // don't allow INCR transfers when using MULTIPLE or to + // Motif clients (since Motif doesn't support INCR) + static Atom motif_clip_temporary = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIP_TEMPORARY); + bool allow_incr = property != motif_clip_temporary; + + // X_ChangeProperty protocol request is 24 bytes + const int increment = (XMaxRequestSize(screen()->display()) * 4) - 24; + if (data.size() > increment && allow_incr) { + long bytes = data.size(); + XChangeProperty(screen()->display(), window, property, + QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR), 32, PropModeReplace, (uchar *) &bytes, 1); + +// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); + qDebug() << "not implemented INCRT just YET!"; + return property; + } + + // make sure we can perform the XChangeProperty in a single request + if (data.size() > increment) + return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend? + int dataSize = data.size() / (dataFormat / 8); + // use a single request to transfer data + XChangeProperty(screen()->display(), window, property, atomFormat, + dataFormat, PropModeReplace, (uchar *) data.data(), + dataSize); + } + return property; +} + +void QTestLiteClipboard::handleSelectionRequest(XEvent *xevent) +{ + XSelectionRequestEvent *req = &xevent->xselectionrequest; + + if (requestor() && req->requestor == requestor()) { + qDebug() << "This should be caught before"; + return; + } + + XEvent event; + event.xselection.type = SelectionNotify; + event.xselection.display = req->display; + event.xselection.requestor = req->requestor; + event.xselection.selection = req->selection; + event.xselection.target = req->target; + event.xselection.property = XNone; + event.xselection.time = req->time; + + QMimeData *d; + if (req->selection == XA_PRIMARY) { + d = m_clientSelection; + } else if (req->selection == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD)) { + d = m_clientClipboard; + } else { + qWarning("QClipboard: Unknown selection '%lx'", req->selection); + XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event); + return; + } + + if (!d) { + qWarning("QClipboard: Cannot transfer data, no data available"); + XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event); + return; + } + + Atom xa_targets = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS); + Atom xa_multiple = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE); + Atom xa_timestamp = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP); + + struct AtomPair { Atom target; Atom property; } *multi = 0; + Atom multi_type = XNone; + int multi_format = 0; + int nmulti = 0; + int imulti = -1; + bool multi_writeback = false; + + if (req->target == xa_multiple) { + QByteArray multi_data; + if (req->property == XNone + || !clipboardReadProperty(req->requestor, req->property, false, &multi_data, + 0, &multi_type, &multi_format) + || multi_format != 32) { + // MULTIPLE property not formatted correctly + XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event); + return; + } + nmulti = multi_data.size()/sizeof(*multi); + multi = new AtomPair[nmulti]; + memcpy(multi,multi_data.data(),multi_data.size()); + imulti = 0; + } + + for (; imulti < nmulti; ++imulti) { + Atom target; + Atom property; + + if (multi) { + target = multi[imulti].target; + property = multi[imulti].property; + } else { + target = req->target; + property = req->property; + if (property == XNone) // obsolete client + property = target; + } + + Atom ret = XNone; + if (target == XNone || property == XNone) { + ; + } else if (target == xa_timestamp) { +// if (d->timestamp != CurrentTime) { + XChangeProperty(screen()->display(), req->requestor, property, XA_INTEGER, 32, + PropModeReplace, CurrentTime, 1); + ret = property; +// } else { +// qWarning("QClipboard: Invalid data timestamp"); +// } + } else if (target == xa_targets) { + ret = sendTargetsSelection(d, req->requestor, property); + } else { + ret = sendSelection(d, target, req->requestor, property); + } + + if (nmulti > 0) { + if (ret == XNone) { + multi[imulti].property = XNone; + multi_writeback = true; + } + } else { + event.xselection.property = ret; + break; + } + } + + if (nmulti > 0) { + if (multi_writeback) { + // according to ICCCM 2.6.2 says to put None back + // into the original property on the requestor window + XChangeProperty(screen()->display(), req->requestor, req->property, multi_type, 32, + PropModeReplace, (uchar *) multi, nmulti * 2); + } + + delete [] multi; + event.xselection.property = req->property; + } + + // send selection notify to requestor + XSendEvent(screen()->display(), req->requestor, False, NoEventMask, &event); +} + +static inline int maxSelectionIncr(Display *dpy) +{ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; } + +bool QTestLiteClipboard::clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const +{ + int maxsize = maxSelectionIncr(screen()->display()); + ulong bytes_left; // bytes_after + ulong length; // nitems + uchar *data; + Atom dummy_type; + int dummy_format; + int r; + + if (!type) // allow null args + type = &dummy_type; + if (!format) + format = &dummy_format; + + // Don't read anything, just get the size of the property data + r = XGetWindowProperty(screen()->display(), win, property, 0, 0, False, + AnyPropertyType, type, format, + &length, &bytes_left, &data); + if (r != Success || (type && *type == XNone)) { + buffer->resize(0); + return false; + } + XFree((char*)data); + + int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left; + + switch (*format) { + case 8: + default: + format_inc = sizeof(char) / 1; + break; + + case 16: + format_inc = sizeof(short) / 2; + proplen *= sizeof(short) / 2; + break; + + case 32: + format_inc = sizeof(long) / 4; + proplen *= sizeof(long) / 4; + break; + } + + int newSize = proplen; + buffer->resize(newSize); + + bool ok = (buffer->size() == newSize); + + if (ok && newSize) { + // could allocate buffer + + while (bytes_left) { + // more to read... + + r = XGetWindowProperty(screen()->display(), win, property, offset, maxsize/4, + False, AnyPropertyType, type, format, + &length, &bytes_left, &data); + if (r != Success || (type && *type == XNone)) + break; + + offset += length / (32 / *format); + length *= format_inc * (*format) / 8; + + // Here we check if we get a buffer overflow and tries to + // recover -- this shouldn't normally happen, but it doesn't + // hurt to be defensive + if ((int)(buffer_offset + length) > buffer->size()) { + length = buffer->size() - buffer_offset; + + // escape loop + bytes_left = 0; + } + + memcpy(buffer->data() + buffer_offset, data, length); + buffer_offset += length; + + XFree((char*)data); + } + + if (*format == 8 && *type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) { + // convert COMPOUND_TEXT to a multibyte string + XTextProperty textprop; + textprop.encoding = *type; + textprop.format = *format; + textprop.nitems = buffer_offset; + textprop.value = (unsigned char *) buffer->data(); + + char **list_ret = 0; + int count; + if (XmbTextPropertyToTextList(screen()->display(), &textprop, &list_ret, + &count) == Success && count && list_ret) { + offset = buffer_offset = strlen(list_ret[0]); + buffer->resize(offset); + memcpy(buffer->data(), list_ret[0], offset); + } + if (list_ret) XFreeStringList(list_ret); + } + } + + // correct size, not 0-term. + if (size) + *size = buffer_offset; + + if (deleteProperty) + XDeleteProperty(screen()->display(), win, property); + + XFlush(screen()->display()); + + return ok; +} + +QByteArray QTestLiteClipboard::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm) +{ + XEvent event; + + QByteArray buf; + QByteArray tmp_buf; + bool alloc_error = false; + int length; + int offset = 0; + + if (nbytes > 0) { + // Reserve buffer + zero-terminator (for text data) + // We want to complete the INCR transfer even if we cannot + // allocate more memory + buf.resize(nbytes+1); + alloc_error = buf.size() != nbytes+1; + } + + for (;;) { + XFlush(screen()->display()); + if (!screen()->waitForClipboardEvent(win,PropertyNotify,&event,clipboard_timeout)) + break; + if (event.xproperty.atom != property || + event.xproperty.state != PropertyNewValue) + continue; + if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) { + if (length == 0) { // no more data, we're done + if (nullterm) { + buf.resize(offset+1); + buf[offset] = '\0'; + } else { + buf.resize(offset); + } + return buf; + } else if (!alloc_error) { + if (offset+length > (int)buf.size()) { + buf.resize(offset+length+65535); + if (buf.size() != offset+length+65535) { + alloc_error = true; + length = buf.size() - offset; + } + } + memcpy(buf.data()+offset, tmp_buf.constData(), length); + tmp_buf.resize(0); + offset += length; + } + } else { + break; + } + } + + // timed out ... create a new requestor window, otherwise the requestor + // could consider next request to be still part of this timed out request + setRequestor(0); + + return QByteArray(); +} + +QByteArray QTestLiteClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom) +{ + QByteArray buf; + + Window win = requestor(); + + XSelectInput(screen()->display(), win, NoEventMask); // don't listen for any events + + XDeleteProperty(screen()->display(), win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION)); + XConvertSelection(screen()->display(), modeAtom, fmtatom, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), win, CurrentTime); + XSync(screen()->display(), false); + + XEvent xevent; + if (!screen()->waitForClipboardEvent(win,SelectionNotify,&xevent,clipboard_timeout) || + xevent.xselection.property == XNone) { + return buf; + } + + Atom type; + XSelectInput(screen()->display(), win, PropertyChangeMask); + + if (clipboardReadProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), true, &buf, 0, &type, 0)) { + if (type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR)) { + int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0; + buf = clipboardReadIncrementalProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), nbytes, false); + } + } + + XSelectInput(screen()->display(), win, NoEventMask); + + + return buf; +} diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.h b/src/plugins/platforms/testlite/qtestliteclipboard.h new file mode 100644 index 0000000..31e42b7 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteclipboard.h @@ -0,0 +1,52 @@ +#ifndef QTESTLITECLIPBOARD_H +#define QTESTLITECLIPBOARD_H + +#include +#include "qtestlitestaticinfo.h" + +class QTestLiteScreen; +class QTestLiteMime; +class QTestLiteClipboard : public QPlatformClipboard +{ +public: + QTestLiteClipboard(QTestLiteScreen *screen); + + const QMimeData *mimeData(QClipboard::Mode mode) const; + void setMimeData(QMimeData *data, QClipboard::Mode mode); + + QTestLiteScreen *screen() const; + + Window requestor() const; + void setRequestor(Window window); + + Window owner() const; + + void handleSelectionRequest(XEvent *event); + + bool clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const; + QByteArray clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm); + + QByteArray getDataInFormat(Atom modeAtom, Atom fmtatom); + +private: + void setOwner(Window window); + + Atom sendTargetsSelection(QMimeData *d, Window window, Atom property); + Atom sendSelection(QMimeData *d, Atom target, Window window, Atom property); + + QTestLiteScreen *m_screen; + + QTestLiteMime *m_xClipboard; + QMimeData *m_clientClipboard; + + QTestLiteMime *m_xSelection; + QMimeData *m_clientSelection; + + Window m_requestor; + Window m_owner; + + static const int clipboard_timeout; + +}; + +#endif // QTESTLITECLIPBOARD_H diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp index fc2a89c..537e22a 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -47,6 +47,7 @@ #include "qtestlitewindow.h" #include "qgenericunixfontdatabase.h" #include "qtestlitescreen.h" +#include "qtestliteclipboard.h" #ifndef QT_NO_OPENGL #include @@ -60,6 +61,7 @@ QT_BEGIN_NAMESPACE QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) : mUseOpenGL(useOpenGL) , mFontDb(new QGenericUnixFontDatabase()) + , mClipboard(0) { mPrimaryScreen = new QTestLiteScreen(); mScreens.append(mPrimaryScreen); @@ -114,6 +116,16 @@ QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const return mFontDb; } +QPlatformClipboard * QTestLiteIntegration::clipboard() const +{ + //Use lazy init since clipboard needs QTestliteScreen + if (!mClipboard) { + QTestLiteIntegration *that = const_cast(this); + that->mClipboard = new QTestLiteClipboard(mPrimaryScreen); + } + return mClipboard; +} + bool QTestLiteIntegration::hasOpenGL() const { #ifndef QT_NO_OPENGL @@ -123,4 +135,5 @@ bool QTestLiteIntegration::hasOpenGL() const return false; } + QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h index 37d09f5..320cf00 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.h +++ b/src/plugins/platforms/testlite/qtestliteintegration.h @@ -48,7 +48,7 @@ #include #include -#include +#include "qtestlitestaticinfo.h" QT_BEGIN_NAMESPACE @@ -68,6 +68,7 @@ public: QList screens() const { return mScreens; } QPlatformFontDatabase *fontDatabase() const; + QPlatformClipboard *clipboard() const; bool hasOpenGL() const; @@ -76,6 +77,7 @@ private: QTestLiteScreen *mPrimaryScreen; QList mScreens; QPlatformFontDatabase *mFontDb; + QPlatformClipboard *mClipboard; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitemime.cpp b/src/plugins/platforms/testlite/qtestlitemime.cpp new file mode 100644 index 0000000..6261383 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitemime.cpp @@ -0,0 +1,362 @@ +#include "qtestlitemime.h" + +#include "qtestlitestaticinfo.h" +#include "qtestlitescreen.h" + +#include + +QTestLiteMime::QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard) + : QInternalMimeData(), m_clipboard(clipboard) +{ + switch (mode) { + case QClipboard::Selection: + modeAtom = XA_PRIMARY; + break; + + case QClipboard::Clipboard: + modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); + break; + + default: + qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode"); + break; + } +} + +QTestLiteMime::~QTestLiteMime() +{ +} + +bool QTestLiteMime::empty() const +{ + Window win = XGetSelectionOwner(m_clipboard->screen()->display(), modeAtom); + + return win == XNone; +} + +QStringList QTestLiteMime::formats_sys() const +{ + if (empty()) + return QStringList(); + + if (!formatList.count()) { + // get the list of targets from the current clipboard owner - we do this + // once so that multiple calls to this function don't require multiple + // server round trips... + + format_atoms = m_clipboard->getDataInFormat(modeAtom,QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS)); + + if (format_atoms.size() > 0) { + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + + for (int i = 0; i < size; ++i) { + if (targets[i] == 0) + continue; + + QStringList formatsForAtom = xdndMimeFormatsForAtom(m_clipboard->screen()->display(),targets[i]); + for (int j = 0; j < formatsForAtom.size(); ++j) { + if (!formatList.contains(formatsForAtom.at(j))) + formatList.append(formatsForAtom.at(j)); + } + } + } + } + + return formatList; +} + +bool QTestLiteMime::hasFormat_sys(const QString &format) const +{ + QStringList list = formats(); + return list.contains(format); +} + +QVariant QTestLiteMime::retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const +{ + if (fmt.isEmpty() || empty()) + return QByteArray(); + + (void)formats(); // trigger update of format list + + QList atoms; + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + for (int i = 0; i < size; ++i) + atoms.append(targets[i]); + + QByteArray encoding; + Atom fmtatom = xdndMimeAtomForFormat(m_clipboard->screen()->display(),fmt, requestedType, atoms, &encoding); + + if (fmtatom == 0) + return QVariant(); + + return xdndMimeConvertToFormat(m_clipboard->screen()->display(),fmtatom, m_clipboard->getDataInFormat(modeAtom,fmtatom), fmt, requestedType, encoding); +} + + +QString QTestLiteMime::xdndMimeAtomToString(Display *display, Atom a) +{ + if (!a) return 0; + + if (a == XA_STRING || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)) { + return "text/plain"; // some Xdnd clients are dumb + } + char *atom = XGetAtomName(display, a); + QString result = QString::fromLatin1(atom); + XFree(atom); + return result; +} + +Atom QTestLiteMime::xdndMimeStringToAtom(Display *display, const QString &mimeType) +{ + if (mimeType.isEmpty()) + return 0; + return XInternAtom(display, mimeType.toLatin1().constData(), False); +} + +QStringList QTestLiteMime::xdndMimeFormatsForAtom(Display *display, Atom a) +{ + QStringList formats; + if (a) { + QString atomName = xdndMimeAtomToString(display, a); + formats.append(atomName); + + // special cases for string type + if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING) + || a == XA_STRING + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + formats.append(QLatin1String("text/plain")); + + // special cases for uris + if (atomName == QLatin1String("text/x-moz-url")) + formats.append(QLatin1String("text/uri-list")); + + // special case for images + if (a == XA_PIXMAP) + formats.append(QLatin1String("image/ppm")); + } + return formats; +} + +bool QTestLiteMime::xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat) +{ + bool ret = false; + *atomFormat = a; + *dataFormat = 8; + QString atomName = xdndMimeAtomToString(display, a); + if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) { + *data = QInternalMimeData::renderDataHelper(atomName, mimeData); + if (atomName == QLatin1String("application/x-color")) + *dataFormat = 16; + ret = true; + } else { + if ((a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING) + || a == XA_STRING + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) { + if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)){ + *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData); + ret = true; + } else if (a == XA_STRING) { + *data = QString::fromUtf8(QInternalMimeData::renderDataHelper( + QLatin1String("text/plain"), mimeData)).toLocal8Bit(); + ret = true; + } else if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) { + // the ICCCM states that TEXT and COMPOUND_TEXT are in the + // encoding of choice, so we choose the encoding of the locale + QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper( + QLatin1String("text/plain"), mimeData)).toLocal8Bit(); + char *list[] = { strData.data(), NULL }; + + XICCEncodingStyle style = (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + ? XCompoundTextStyle : XStdICCTextStyle; + XTextProperty textprop; + if (list[0] != NULL + && XmbTextListToTextProperty(display, list, 1, style, + &textprop) == Success) { + *atomFormat = textprop.encoding; + *dataFormat = textprop.format; + *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8); + ret = true; + + XFree(textprop.value); + } + } + } else if (atomName == QLatin1String("text/x-moz-url") && + QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) { + QByteArray uri = QInternalMimeData::renderDataHelper( + QLatin1String("text/uri-list"), mimeData).split('\n').first(); + QString mozUri = QString::fromLatin1(uri, uri.size()); + mozUri += QLatin1Char('\n'); + *data = QByteArray(reinterpret_cast(mozUri.utf16()), mozUri.length() * 2); + ret = true; + } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) { + QPixmap pm = qvariant_cast(mimeData->imageData()); + if (a == XA_BITMAP && pm.depth() != 1) { + QImage img = pm.toImage(); + img = img.convertToFormat(QImage::Format_MonoLSB); + pm = QPixmap::fromImage(img); + } +// QDragManager *dm = QDragManager::self(); +// if (dm) { +// Pixmap handle = pm.handle(); +// *data = QByteArray((const char *) &handle, sizeof(Pixmap)); +// dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm; +// dm->xdndMimeTransferedPixmapIndex = +// (dm->xdndMimeTransferedPixmapIndex + 1) % 2; +// ret = true; +// } + } + } + return ret && data != 0; +} + +QList QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QString &format) +{ + QList atoms; + atoms.append(xdndMimeStringToAtom(display, format)); + + // special cases for strings + if (format == QLatin1String("text/plain")) { + atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)); + atoms.append(XA_STRING); + atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)); + atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)); + } + + // special cases for uris + if (format == QLatin1String("text/uri-list")) { + atoms.append(xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url"))); + } + + //special cases for images + if (format == QLatin1String("image/ppm")) + atoms.append(XA_PIXMAP); + if (format == QLatin1String("image/pbm")) + atoms.append(XA_BITMAP); + + return atoms; +} + +QVariant QTestLiteMime::xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding) +{ + QString atomName = xdndMimeAtomToString(display,a); + if (atomName == format) + return data; + + if (!encoding.isEmpty() + && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) { + + if (requestedType == QVariant::String) { + QTextCodec *codec = QTextCodec::codecForName(encoding); + if (codec) + return codec->toUnicode(data); + } + + return data; + } + + // special cases for string types + if (format == QLatin1String("text/plain")) { + if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)) + return QString::fromUtf8(data); + if (a == XA_STRING) + return QString::fromLatin1(data); + if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) + || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + // #### might be wrong for COMPUND_TEXT + return QString::fromLocal8Bit(data, data.size()); + } + + // special case for uri types + if (format == QLatin1String("text/uri-list")) { + if (atomName == QLatin1String("text/x-moz-url")) { + // we expect this as utf16 + // the first part is a url that should only contain ascci char + // so it should be safe to check that the second char is 0 + // to verify that it is utf16 + if (data.size() > 1 && data.at(1) == 0) + return QString::fromRawData((const QChar *)data.constData(), + data.size() / 2).split(QLatin1Char('\n')).first().toLatin1(); + } + } + + // special cas for images + if (format == QLatin1String("image/ppm")) { + if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { +// Pixmap xpm = *((Pixmap*)data.data()); +// if (!xpm) +// return QByteArray(); +// QPixmap qpm = QPixmap::fromX11Pixmap(xpm); +// QImageWriter imageWriter; +// imageWriter.setFormat("PPMRAW"); +// QImage imageToWrite = qpm.toImage(); +// QBuffer buf; +// buf.open(QIODevice::WriteOnly); +// imageWriter.setDevice(&buf); +// imageWriter.write(imageToWrite); +// return buf.buffer(); + return QVariant(); + } + } + return QVariant(); +} + +Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding) +{ + requestedEncoding->clear(); + + // find matches for string types + if (format == QLatin1String("text/plain")) { + if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING))) + return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING); + if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))) + return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT); + if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT))) + return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT); + if (atoms.contains(XA_STRING)) + return XA_STRING; + } + + // find matches for uri types + if (format == QLatin1String("text/uri-list")) { + Atom a = xdndMimeStringToAtom(display,format); + if (a && atoms.contains(a)) + return a; + a = xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url")); + if (a && atoms.contains(a)) + return a; + } + + // find match for image + if (format == QLatin1String("image/ppm")) { + if (atoms.contains(XA_PIXMAP)) + return XA_PIXMAP; + } + + // for string/text requests try to use a format with a well-defined charset + // first to avoid encoding problems + if (requestedType == QVariant::String + && format.startsWith(QLatin1String("text/")) + && !format.contains(QLatin1String("charset="))) { + + QString formatWithCharset = format; + formatWithCharset.append(QLatin1String(";charset=utf-8")); + + Atom a = xdndMimeStringToAtom(display,formatWithCharset); + if (a && atoms.contains(a)) { + *requestedEncoding = "utf-8"; + return a; + } + } + + Atom a = xdndMimeStringToAtom(display,format); + if (a && atoms.contains(a)) + return a; + + return 0; +} diff --git a/src/plugins/platforms/testlite/qtestlitemime.h b/src/plugins/platforms/testlite/qtestlitemime.h new file mode 100644 index 0000000..e5ed7b0 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitemime.h @@ -0,0 +1,42 @@ +#ifndef QTESTLITEMIME_H +#define QTESTLITEMIME_H + +#include <private/qdnd_p.h> + +#include <QtGui/QClipboard> + +#include "qtestliteintegration.h" +#include "qtestliteclipboard.h" + +class QTestLiteMime : public QInternalMimeData { + Q_OBJECT +public: + QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard); + ~QTestLiteMime(); + bool empty() const; + + static QList<Atom> xdndMimeAtomsForFormat(Display *display, const QString &format); + static QString xdndMimeAtomToString(Display *display, Atom a); + static bool xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat); + static QStringList xdndMimeFormatsForAtom(Display *display, Atom a); + static Atom xdndMimeStringToAtom(Display *display, const QString &mimeType); + + static QVariant xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding); + static Atom xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding); + + +protected: + virtual bool hasFormat_sys(const QString &mimetype) const; + virtual QStringList formats_sys() const; + + QVariant retrieveData_sys(const QString &mimetype, QVariant::Type type) const; + + +private: + QTestLiteClipboard *m_clipboard; + Atom modeAtom; + mutable QStringList formatList; + mutable QByteArray format_atoms; +}; + +#endif // QTESTLITEMIME_H diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp index c0f696d..2ae7028 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.cpp +++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp @@ -44,9 +44,16 @@ #include "qtestlitecursor.h" #include "qtestlitewindow.h" #include "qtestlitekeyboard.h" +#include "qtestlitestaticinfo.h" +#include "qtestliteclipboard.h" #include <QtCore/QDebug> #include <QtCore/QSocketNotifier> +#include <QtCore/QElapsedTimer> + +#include <private/qapplication_p.h> + +#include <X11/extensions/Xfixes.h> QT_BEGIN_NAMESPACE @@ -183,11 +190,10 @@ qDebug() << "qt_x_errhandler" << err->error_code; QTestLiteScreen::QTestLiteScreen() : mFormat(QImage::Format_RGB32) - , mWmProtocolsAtom(0) - , mWmDeleteWindowAtom(0) { char *display_name = getenv("DISPLAY"); mDisplay = XOpenDisplay(display_name); + mDisplayName = QString::fromLocal8Bit(display_name); if (!mDisplay) { fprintf(stderr, "Cannot connect to X server: %s\n", display_name); @@ -204,6 +210,7 @@ QTestLiteScreen::QTestLiteScreen() XSynchronize(mDisplay, true); mScreen = DefaultScreen(mDisplay); + XSelectInput(mDisplay,rootWindow(), KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); int width = DisplayWidth(mDisplay, mScreen); int height = DisplayHeight(mDisplay, mScreen); mGeometry = QRect(0,0,width,height); @@ -221,11 +228,6 @@ QTestLiteScreen::QTestLiteScreen() QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); - mWmProtocolsAtom = XInternAtom (mDisplay, "WM_PROTOCOLS", False); - mWmDeleteWindowAtom = XInternAtom (mDisplay, "WM_DELETE_WINDOW", False); - - mWmMotifHintAtom = XInternAtom(mDisplay, "_MOTIF_WM_HINTS\0", False); - mCursor = new QTestLiteCursor(this); mKeyboard = new QTestLiteKeyboard(this); } @@ -243,9 +245,6 @@ QTestLiteScreen::~QTestLiteScreen() #undef KeyRelease #endif -//Q_GUI_EXPORT extern Atom wmProtocolsAtom; -//Q_GUI_EXPORT extern Atom wmDeleteWindowAtom; - bool QTestLiteScreen::handleEvent(XEvent *xe) { int quit = false; @@ -254,28 +253,17 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) if (widget) { xw = static_cast<QTestLiteWindow *>(widget->platformWindow()); } - if (!xw) { -#ifdef MYX11_DEBUG - qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type; -#endif - return quit; - } + Atom wmProtocolsAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_PROTOCOLS); + Atom wmDeleteWindowAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW); switch (xe->type) { case ClientMessage: - if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom()) { + if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { Atom a = xe->xclient.data.l[0]; - if (a == wmDeleteWindowAtom()) + if (a == wmDeleteWindowAtom) xw->handleCloseEvent(); -#ifdef MYX11_DEBUG - qDebug() << "ClientMessage WM_PROTOCOLS" << a; -#endif } -#ifdef MYX11_DEBUG - else - qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type; -#endif break; case Expose: @@ -289,15 +277,18 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) break; case ButtonPress: - xw->mousePressEvent(&xe->xbutton); + if (xw) + xw->mousePressEvent(&xe->xbutton); break; case ButtonRelease: - xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); + if (xw) + xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); break; case MotionNotify: - xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); + if (xw) + xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); break; case XKeyPress: @@ -309,20 +300,39 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) break; case EnterNotify: - xw->handleEnterEvent(); + if (xw) + xw->handleEnterEvent(); break; case LeaveNotify: - xw->handleLeaveEvent(); + if (xw) + xw->handleLeaveEvent(); break; case XFocusIn: - xw->handleFocusInEvent(); + if (xw) + xw->handleFocusInEvent(); break; case XFocusOut: - xw->handleFocusOutEvent(); + if (xw) + xw->handleFocusOutEvent(); + break; + + case PropertyNotify: + break; + + case SelectionClear: + qDebug() << "Selection Clear!!!"; + break; + case SelectionRequest: + handleSelectionRequest(xe); break; + case SelectionNotify: + qDebug() << "Selection Notify!!!!"; + + break; + default: #ifdef MYX11_DEBUG @@ -330,9 +340,43 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) #endif break; } + return quit; } +static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer) +{ + Atom clipboard = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); + return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY + || e->xselectionrequest.selection == clipboard)) + || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY + || e->xselectionclear.selection == clipboard))); +} + +bool QTestLiteScreen::waitForClipboardEvent(Window win, int type, XEvent *event, int timeout) +{ + QElapsedTimer timer; + timer.start(); + do { + if (XCheckTypedWindowEvent(mDisplay,win,type,event)) + return true; + + // process other clipboard events, since someone is probably requesting data from us + XEvent e; + if (XCheckIfEvent(mDisplay, &e, checkForClipboardEvents, 0)) + handleEvent(&e); + + XFlush(mDisplay); + + // sleep 50 ms, so we don't use up CPU cycles all the time. + struct timeval usleep_tv; + usleep_tv.tv_sec = 0; + usleep_tv.tv_usec = 50000; + select(0, 0, 0, 0, &usleep_tv); + } while (timer.elapsed() < timeout); + return false; +} + void QTestLiteScreen::eventDispatcher() { ulong marker = XNextRequest(mDisplay); @@ -409,29 +453,16 @@ int QTestLiteScreen::xScreenNumber() const return mScreen; } -Atom QTestLiteScreen::wmProtocolsAtom() const -{ - return mWmProtocolsAtom; -} - -Atom QTestLiteScreen::wmDeleteWindowAtom() const -{ - return mWmDeleteWindowAtom; -} - -void QTestLiteScreen::setWmDeleteWindowAtom(Atom newDeleteWindowAtom) -{ - mWmDeleteWindowAtom = newDeleteWindowAtom; -} - -Atom QTestLiteScreen::atomForMotifWmHints() const +QTestLiteKeyboard * QTestLiteScreen::keyboard() const { - return mWmMotifHintAtom; + return mKeyboard; } -QTestLiteKeyboard * QTestLiteScreen::keyboard() const +void QTestLiteScreen::handleSelectionRequest(XEvent *event) { - return mKeyboard; + QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + QTestLiteClipboard *clipboard = static_cast<QTestLiteClipboard *>(integration->clipboard()); + clipboard->handleSelectionRequest(event); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitescreen.h b/src/plugins/platforms/testlite/qtestlitescreen.h index 9a1a510..860a67c 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.h +++ b/src/plugins/platforms/testlite/qtestlitescreen.h @@ -58,6 +58,8 @@ public: ~QTestLiteScreen(); + QString displayName() const { return mDisplayName; } + QRect geometry() const { return mGeometry; } int depth() const { return mDepth; } QImage::Format format() const { return mFormat; } @@ -68,6 +70,8 @@ public: unsigned long whitePixel() { return WhitePixel(mDisplay, mScreen); } bool handleEvent(XEvent *xe); + bool waitForClipboardEvent(Window win, int type, XEvent *event, int timeout); + QImage grabWindow(Window window, int x, int y, int w, int h); static QTestLiteScreen *testLiteScreenForWidget(QWidget *widget); @@ -75,18 +79,15 @@ public: Display *display() const; int xScreenNumber() const; - Atom wmProtocolsAtom() const; - Atom wmDeleteWindowAtom() const; - void setWmDeleteWindowAtom(Atom newDeleteWindowAtom); - - Atom atomForMotifWmHints() const; - QTestLiteKeyboard *keyboard() const; public slots: void eventDispatcher(); private: + + void handleSelectionRequest(XEvent *event); + QString mDisplayName; QRect mGeometry; QSize mPhysicalSize; int mDepth; @@ -96,9 +97,6 @@ private: Display * mDisplay; int mScreen; - Atom mWmProtocolsAtom; - Atom mWmDeleteWindowAtom; - Atom mWmMotifHintAtom; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp new file mode 100644 index 0000000..20d73a2 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp @@ -0,0 +1,417 @@ +#include "qtestlitestaticinfo.h" +#include "qtestlitescreen.h" + +#include <qplatformdefs.h> + +#include <QtGui/private/qapplication_p.h> +#include <QtCore/QBuffer> +#include <QtCore/QLibrary> + +#include <QDebug> + +#ifndef QT_NO_XFIXES +#include <X11/extensions/Xfixes.h> +#endif // QT_NO_XFIXES + +static const char * x11_atomnames = { + // window-manager <-> client protocols + "WM_PROTOCOLS\0" + "WM_DELETE_WINDOW\0" + "WM_TAKE_FOCUS\0" + "_NET_WM_PING\0" + "_NET_WM_CONTEXT_HELP\0" + "_NET_WM_SYNC_REQUEST\0" + "_NET_WM_SYNC_REQUEST_COUNTER\0" + + // ICCCM window state + "WM_STATE\0" + "WM_CHANGE_STATE\0" + + // Session management + "WM_CLIENT_LEADER\0" + "WM_WINDOW_ROLE\0" + "SM_CLIENT_ID\0" + + // Clipboard + "CLIPBOARD\0" + "INCR\0" + "TARGETS\0" + "MULTIPLE\0" + "TIMESTAMP\0" + "SAVE_TARGETS\0" + "CLIP_TEMPORARY\0" + "_QT_SELECTION\0" + "_QT_CLIPBOARD_SENTINEL\0" + "_QT_SELECTION_SENTINEL\0" + "CLIPBOARD_MANAGER\0" + + "RESOURCE_MANAGER\0" + + "_XSETROOT_ID\0" + + "_QT_SCROLL_DONE\0" + "_QT_INPUT_ENCODING\0" + + "_MOTIF_WM_HINTS\0" + + "DTWM_IS_RUNNING\0" + "ENLIGHTENMENT_DESKTOP\0" + "_DT_SAVE_MODE\0" + "_SGI_DESKS_MANAGER\0" + + // EWMH (aka NETWM) + "_NET_SUPPORTED\0" + "_NET_VIRTUAL_ROOTS\0" + "_NET_WORKAREA\0" + + "_NET_MOVERESIZE_WINDOW\0" + "_NET_WM_MOVERESIZE\0" + + "_NET_WM_NAME\0" + "_NET_WM_ICON_NAME\0" + "_NET_WM_ICON\0" + + "_NET_WM_PID\0" + + "_NET_WM_WINDOW_OPACITY\0" + + "_NET_WM_STATE\0" + "_NET_WM_STATE_ABOVE\0" + "_NET_WM_STATE_BELOW\0" + "_NET_WM_STATE_FULLSCREEN\0" + "_NET_WM_STATE_MAXIMIZED_HORZ\0" + "_NET_WM_STATE_MAXIMIZED_VERT\0" + "_NET_WM_STATE_MODAL\0" + "_NET_WM_STATE_STAYS_ON_TOP\0" + "_NET_WM_STATE_DEMANDS_ATTENTION\0" + + "_NET_WM_USER_TIME\0" + "_NET_WM_USER_TIME_WINDOW\0" + "_NET_WM_FULL_PLACEMENT\0" + + "_NET_WM_WINDOW_TYPE\0" + "_NET_WM_WINDOW_TYPE_DESKTOP\0" + "_NET_WM_WINDOW_TYPE_DOCK\0" + "_NET_WM_WINDOW_TYPE_TOOLBAR\0" + "_NET_WM_WINDOW_TYPE_MENU\0" + "_NET_WM_WINDOW_TYPE_UTILITY\0" + "_NET_WM_WINDOW_TYPE_SPLASH\0" + "_NET_WM_WINDOW_TYPE_DIALOG\0" + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0" + "_NET_WM_WINDOW_TYPE_POPUP_MENU\0" + "_NET_WM_WINDOW_TYPE_TOOLTIP\0" + "_NET_WM_WINDOW_TYPE_NOTIFICATION\0" + "_NET_WM_WINDOW_TYPE_COMBO\0" + "_NET_WM_WINDOW_TYPE_DND\0" + "_NET_WM_WINDOW_TYPE_NORMAL\0" + "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0" + + "_KDE_NET_WM_FRAME_STRUT\0" + + "_NET_STARTUP_INFO\0" + "_NET_STARTUP_INFO_BEGIN\0" + + "_NET_SUPPORTING_WM_CHECK\0" + + "_NET_WM_CM_S0\0" + + "_NET_SYSTEM_TRAY_VISUAL\0" + + "_NET_ACTIVE_WINDOW\0" + + // Property formats + "COMPOUND_TEXT\0" + "TEXT\0" + "UTF8_STRING\0" + + // xdnd + "XdndEnter\0" + "XdndPosition\0" + "XdndStatus\0" + "XdndLeave\0" + "XdndDrop\0" + "XdndFinished\0" + "XdndTypeList\0" + "XdndActionList\0" + + "XdndSelection\0" + + "XdndAware\0" + "XdndProxy\0" + + "XdndActionCopy\0" + "XdndActionLink\0" + "XdndActionMove\0" + "XdndActionPrivate\0" + + // Motif DND + "_MOTIF_DRAG_AND_DROP_MESSAGE\0" + "_MOTIF_DRAG_INITIATOR_INFO\0" + "_MOTIF_DRAG_RECEIVER_INFO\0" + "_MOTIF_DRAG_WINDOW\0" + "_MOTIF_DRAG_TARGETS\0" + + "XmTRANSFER_SUCCESS\0" + "XmTRANSFER_FAILURE\0" + + // Xkb + "_XKB_RULES_NAMES\0" + + // XEMBED + "_XEMBED\0" + "_XEMBED_INFO\0" + + // Wacom old. (before version 0.10) + "Wacom Stylus\0" + "Wacom Cursor\0" + "Wacom Eraser\0" + + // Tablet + "STYLUS\0" + "ERASER\0" +}; + +/*! + \internal + Try to resolve a \a symbol from \a library with the version specified + by \a vernum. + + Note that, in the case of the Xfixes library, \a vernum is not the same as + \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes + version. +*/ +static void* qt_load_library_runtime(const char *library, int vernum, + int highestVernum, const char *symbol) +{ + QList<int> versions; + // we try to load in the following order: + // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) ) + if (vernum != -1) + versions << vernum; + versions << -1; + if (vernum != -1) { + for(int i = highestVernum; i > vernum; --i) + versions << i; + } + Q_FOREACH(int version, versions) { + QLatin1String libName(library); + QLibrary xfixesLib(libName, version); + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; + } + return 0; +} + +# define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \ + (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol); +# define XFIXES_LOAD_V1(symbol) \ + XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol) +# define XFIXES_LOAD_V2(symbol) \ + XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol) + + +class QTestLiteStaticInfoPrivate +{ +public: + QTestLiteStaticInfoPrivate() + : use_xfixes(false) + , xfixes_major(0) + , xfixes_eventbase(0) + , xfixes_errorbase(0) + { + QTestLiteScreen *screen = qobject_cast<QTestLiteScreen *> (QApplicationPrivate::platformIntegration()->screens().at(0)); + Q_ASSERT(screen); + + initializeAllAtoms(screen); + initializeSupportedAtoms(screen); + + resolveXFixes(screen); + } + + bool isSupportedByWM(Atom atom) + { + if (!m_supportedAtoms) + return false; + + bool supported = false; + int i = 0; + while (m_supportedAtoms[i] != 0) { + if (m_supportedAtoms[i++] == atom) { + supported = true; + break; + } + } + + return supported; + } + + Atom atom(QTestLiteStaticInfo::X11Atom atom) + { + return m_allAtoms[atom]; + } + + bool useXFixes() const { return use_xfixes; } + + int xFixesEventBase() const {return xfixes_eventbase; } + + PtrXFixesSelectSelectionInput xFixesSelectSelectionInput() const + { + return ptrXFixesSelectSelectionInput; + } + +private: + + void initializeAllAtoms(QTestLiteScreen *screen) { + const char *names[QTestLiteStaticInfo::NAtoms]; + const char *ptr = x11_atomnames; + + int i = 0; + while (*ptr) { + names[i++] = ptr; + while (*ptr) + ++ptr; + ++ptr; + } + + Q_ASSERT(i == QTestLiteStaticInfo::NPredefinedAtoms); + + QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); + settings_atom_name += XDisplayName(qPrintable(screen->displayName())); + names[i++] = settings_atom_name; + + Q_ASSERT(i == QTestLiteStaticInfo::NAtoms); + #if 0//defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6) + XInternAtoms(screen->display(), (char **)names, i, False, m_allAtoms); + #else + for (i = 0; i < QTestLiteStaticInfo::NAtoms; ++i) + m_allAtoms[i] = XInternAtom(screen->display(), (char *)names[i], False); + #endif + } + + void initializeSupportedAtoms(QTestLiteScreen *screen) + { + Atom type; + int format; + long offset = 0; + unsigned long nitems, after; + unsigned char *data = 0; + + int e = XGetWindowProperty(screen->display(), screen->rootWindow(), + this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), 0, 0, + False, XA_ATOM, &type, &format, &nitems, &after, &data); + if (data) + XFree(data); + + if (e == Success && type == XA_ATOM && format == 32) { + QBuffer ts; + ts.open(QIODevice::WriteOnly); + + while (after > 0) { + XGetWindowProperty(screen->display(), screen->rootWindow(), + this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), offset, 1024, + False, XA_ATOM, &type, &format, &nitems, &after, &data); + + if (type == XA_ATOM && format == 32) { + ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long)); + offset += nitems; + } else + after = 0; + if (data) + XFree(data); + } + + // compute nitems + QByteArray buffer(ts.buffer()); + nitems = buffer.size() / sizeof(Atom); + m_supportedAtoms = new Atom[nitems + 1]; + Atom *a = (Atom *) buffer.data(); + uint i; + for (i = 0; i < nitems; i++) + m_supportedAtoms[i] = a[i]; + m_supportedAtoms[nitems] = 0; + + } + } + + void resolveXFixes(QTestLiteScreen *screen) + { +#ifndef QT_NO_XFIXES + // See if Xfixes is supported on the connected display + if (XQueryExtension(screen->display(), "XFIXES", &xfixes_major, + &xfixes_eventbase, &xfixes_errorbase)) { + ptrXFixesQueryExtension = XFIXES_LOAD_V1(XFixesQueryExtension); + ptrXFixesQueryVersion = XFIXES_LOAD_V1(XFixesQueryVersion); + ptrXFixesSetCursorName = XFIXES_LOAD_V2(XFixesSetCursorName); + ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput); + + if(ptrXFixesQueryExtension && ptrXFixesQueryVersion + && ptrXFixesQueryExtension(screen->display(), &xfixes_eventbase, + &xfixes_errorbase)) { + // Xfixes is supported. + // Note: the XFixes protocol version is negotiated using QueryVersion. + // We supply the highest version we support, the X server replies with + // the highest version it supports, but no higher than the version we + // asked for. The version sent back is the protocol version the X server + // will use to talk us. If this call is removed, the behavior of the + // X server when it receives an XFixes request is undefined. + int major = 3; + int minor = 0; + ptrXFixesQueryVersion(screen->display(), &major, &minor); + use_xfixes = (major >= 1); + xfixes_major = major; + } + } +#endif // QT_NO_XFIXES + + } + + Atom *m_supportedAtoms; + Atom m_allAtoms[QTestLiteStaticInfo::NAtoms]; + +#ifndef QT_NO_XFIXES + PtrXFixesQueryExtension ptrXFixesQueryExtension; + PtrXFixesQueryVersion ptrXFixesQueryVersion; + PtrXFixesSetCursorName ptrXFixesSetCursorName; + PtrXFixesSelectSelectionInput ptrXFixesSelectSelectionInput; +#endif + + bool use_xfixes; + int xfixes_major; + int xfixes_eventbase; + int xfixes_errorbase; + +}; +Q_GLOBAL_STATIC(QTestLiteStaticInfoPrivate, qTestLiteStaticInfoPrivate); + + +Atom QTestLiteStaticInfo::atom(QTestLiteStaticInfo::X11Atom atom) +{ + return qTestLiteStaticInfoPrivate()->atom(atom); +} + +bool QTestLiteStaticInfo::isSupportedByWM(Atom atom) +{ + return qTestLiteStaticInfoPrivate()->isSupportedByWM(atom); +} + +bool QTestLiteStaticInfo::useXFixes() +{ + return qTestLiteStaticInfoPrivate()->useXFixes(); +} + +int QTestLiteStaticInfo::xFixesEventBase() +{ + return qTestLiteStaticInfoPrivate()->xFixesEventBase(); +} + +#ifndef QT_NO_XFIXES +PtrXFixesSelectSelectionInput QTestLiteStaticInfo::xFixesSelectSelectionInput() +{ + qDebug() << qTestLiteStaticInfoPrivate()->useXFixes(); + if (!qTestLiteStaticInfoPrivate()->useXFixes()) + return 0; + + return qTestLiteStaticInfoPrivate()->xFixesSelectSelectionInput(); +} +#endif //QT_NO_XFIXES diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.h b/src/plugins/platforms/testlite/qtestlitestaticinfo.h new file mode 100644 index 0000000..ed0f7bd --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.h @@ -0,0 +1,371 @@ +#ifndef QTESTLITESTATICINFO_H +#define QTESTLITESTATICINFO_H + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> + +#if defined(_XLIB_H_) // crude hack, but... +#error "cannot include <X11/Xlib.h> before this file" +#endif +#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback +#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback +#define XSetIMValues qt_XSetIMValues +#include <X11/Xlib.h> +#undef XRegisterIMInstantiateCallback +#undef XUnregisterIMInstantiateCallback +#undef XSetIMValues + +#include <X11/Xutil.h> +#include <X11/Xos.h> +#ifdef index +# undef index +#endif +#ifdef rindex +# undef rindex +#endif +#ifdef Q_OS_VXWORS +# ifdef open +# undef open +# endif +# ifdef getpid +# undef getpid +# endif +#endif // Q_OS_VXWORKS +#include <X11/Xatom.h> + +//#define QT_NO_SHAPE +#ifdef QT_NO_SHAPE +# define XShapeCombineRegion(a,b,c,d,e,f,g) +# define XShapeCombineMask(a,b,c,d,e,f,g) +#else +# include <X11/extensions/shape.h> +#endif // QT_NO_SHAPE + + +#if !defined (QT_NO_TABLET) +# include <X11/extensions/XInput.h> +#if defined (Q_OS_IRIX) +# include <X11/extensions/SGIMisc.h> +# include <wacom.h> +#endif +#endif // QT_NO_TABLET + + +// #define QT_NO_XINERAMA +#ifndef QT_NO_XINERAMA +// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3). +extern "C" { +# include <X11/extensions/Xinerama.h> +} +#endif // QT_NO_XINERAMA + +// #define QT_NO_XRANDR +#ifndef QT_NO_XRANDR +# include <X11/extensions/Xrandr.h> +#endif // QT_NO_XRANDR + +// #define QT_NO_XRENDER +#ifndef QT_NO_XRENDER +# include <X11/extensions/Xrender.h> +#endif // QT_NO_XRENDER + +#ifndef QT_NO_XSYNC +extern "C" { +# include "X11/extensions/sync.h" +} +#endif + +// #define QT_NO_XKB +#ifndef QT_NO_XKB +# include <X11/XKBlib.h> +#endif // QT_NO_XKB + + +#if !defined(XlibSpecificationRelease) +# define X11R4 +typedef char *XPointer; +#else +# undef X11R4 +#endif + +#ifndef QT_NO_XFIXES +typedef Bool (*PtrXFixesQueryExtension)(Display *, int *, int *); +typedef Status (*PtrXFixesQueryVersion)(Display *, int *, int *); +typedef void (*PtrXFixesSetCursorName)(Display *dpy, Cursor cursor, const char *name); +typedef void (*PtrXFixesSelectSelectionInput)(Display *dpy, Window win, Atom selection, unsigned long eventMask); +#endif // QT_NO_XFIXES + +#ifndef QT_NO_XCURSOR +#include <X11/Xcursor/Xcursor.h> +typedef Cursor (*PtrXcursorLibraryLoadCursor)(Display *, const char *); +#endif // QT_NO_XCURSOR + +#ifndef QT_NO_XINERAMA +typedef Bool (*PtrXineramaQueryExtension)(Display *dpy, int *event_base, int *error_base); +typedef Bool (*PtrXineramaIsActive)(Display *dpy); +typedef XineramaScreenInfo *(*PtrXineramaQueryScreens)(Display *dpy, int *number); +#endif // QT_NO_XINERAMA + +#ifndef QT_NO_XRANDR +typedef void (*PtrXRRSelectInput)(Display *, Window, int); +typedef int (*PtrXRRUpdateConfiguration)(XEvent *); +typedef int (*PtrXRRRootToScreen)(Display *, Window); +typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *); +#endif // QT_NO_XRANDR + +#ifndef QT_NO_XINPUT +typedef int (*PtrXCloseDevice)(Display *, XDevice *); +typedef XDeviceInfo* (*PtrXListInputDevices)(Display *, int *); +typedef XDevice* (*PtrXOpenDevice)(Display *, XID); +typedef void (*PtrXFreeDeviceList)(XDeviceInfo *); +typedef int (*PtrXSelectExtensionEvent)(Display *, Window, XEventClass *, int); +#endif // QT_NO_XINPUT + +/* + * Solaris patch 108652-47 and higher fixes crases in + * XRegisterIMInstantiateCallback, but the function doesn't seem to + * work. + * + * Instead, we disabled R6 input, and open the input method + * immediately at application start. + */ + +//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback +//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2. +//######### Many old X11R6 header files lack XSetIMValues. +//######### Therefore, we have to declare these functions ourselves. + +extern "C" Bool XRegisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +extern "C" Bool XUnregisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +#ifndef X11R4 +# include <X11/Xlocale.h> +#endif // X11R4 + + +#ifndef QT_NO_MITSHM +# include <X11/extensions/XShm.h> +#endif // QT_NO_MITSHM + +// rename a couple of X defines to get rid of name clashes +// resolve the conflict between X11's FocusIn and QEvent::FocusIn +enum { + XFocusOut = FocusOut, + XFocusIn = FocusIn, + XKeyPress = KeyPress, + XKeyRelease = KeyRelease, + XNone = None, + XRevertToParent = RevertToParent, + XGrayScale = GrayScale, + XCursorShape = CursorShape +}; +#undef FocusOut +#undef FocusIn +#undef KeyPress +#undef KeyRelease +#undef None +#undef RevertToParent +#undef GrayScale +#undef CursorShape + +#ifdef FontChange +#undef FontChange +#endif + + +class QTestLiteStaticInfo +{ +public: + enum X11Atom { + // window-manager <-> client protocols + WM_PROTOCOLS, + WM_DELETE_WINDOW, + WM_TAKE_FOCUS, + _NET_WM_PING, + _NET_WM_CONTEXT_HELP, + _NET_WM_SYNC_REQUEST, + _NET_WM_SYNC_REQUEST_COUNTER, + + // ICCCM window state + WM_STATE, + WM_CHANGE_STATE, + + // Session management + WM_CLIENT_LEADER, + WM_WINDOW_ROLE, + SM_CLIENT_ID, + + // Clipboard + CLIPBOARD, + INCR, + TARGETS, + MULTIPLE, + TIMESTAMP, + SAVE_TARGETS, + CLIP_TEMPORARY, + _QT_SELECTION, + _QT_CLIPBOARD_SENTINEL, + _QT_SELECTION_SENTINEL, + CLIPBOARD_MANAGER, + + RESOURCE_MANAGER, + + _XSETROOT_ID, + + _QT_SCROLL_DONE, + _QT_INPUT_ENCODING, + + _MOTIF_WM_HINTS, + + DTWM_IS_RUNNING, + ENLIGHTENMENT_DESKTOP, + _DT_SAVE_MODE, + _SGI_DESKS_MANAGER, + + // EWMH (aka NETWM) + _NET_SUPPORTED, + _NET_VIRTUAL_ROOTS, + _NET_WORKAREA, + + _NET_MOVERESIZE_WINDOW, + _NET_WM_MOVERESIZE, + + _NET_WM_NAME, + _NET_WM_ICON_NAME, + _NET_WM_ICON, + + _NET_WM_PID, + + _NET_WM_WINDOW_OPACITY, + + _NET_WM_STATE, + _NET_WM_STATE_ABOVE, + _NET_WM_STATE_BELOW, + _NET_WM_STATE_FULLSCREEN, + _NET_WM_STATE_MAXIMIZED_HORZ, + _NET_WM_STATE_MAXIMIZED_VERT, + _NET_WM_STATE_MODAL, + _NET_WM_STATE_STAYS_ON_TOP, + _NET_WM_STATE_DEMANDS_ATTENTION, + + _NET_WM_USER_TIME, + _NET_WM_USER_TIME_WINDOW, + _NET_WM_FULL_PLACEMENT, + + _NET_WM_WINDOW_TYPE, + _NET_WM_WINDOW_TYPE_DESKTOP, + _NET_WM_WINDOW_TYPE_DOCK, + _NET_WM_WINDOW_TYPE_TOOLBAR, + _NET_WM_WINDOW_TYPE_MENU, + _NET_WM_WINDOW_TYPE_UTILITY, + _NET_WM_WINDOW_TYPE_SPLASH, + _NET_WM_WINDOW_TYPE_DIALOG, + _NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + _NET_WM_WINDOW_TYPE_POPUP_MENU, + _NET_WM_WINDOW_TYPE_TOOLTIP, + _NET_WM_WINDOW_TYPE_NOTIFICATION, + _NET_WM_WINDOW_TYPE_COMBO, + _NET_WM_WINDOW_TYPE_DND, + _NET_WM_WINDOW_TYPE_NORMAL, + _KDE_NET_WM_WINDOW_TYPE_OVERRIDE, + + _KDE_NET_WM_FRAME_STRUT, + + _NET_STARTUP_INFO, + _NET_STARTUP_INFO_BEGIN, + + _NET_SUPPORTING_WM_CHECK, + + _NET_WM_CM_S0, + + _NET_SYSTEM_TRAY_VISUAL, + + _NET_ACTIVE_WINDOW, + + // Property formats + COMPOUND_TEXT, + TEXT, + UTF8_STRING, + + // Xdnd + XdndEnter, + XdndPosition, + XdndStatus, + XdndLeave, + XdndDrop, + XdndFinished, + XdndTypelist, + XdndActionList, + + XdndSelection, + + XdndAware, + XdndProxy, + + XdndActionCopy, + XdndActionLink, + XdndActionMove, + XdndActionPrivate, + + // Motif DND + _MOTIF_DRAG_AND_DROP_MESSAGE, + _MOTIF_DRAG_INITIATOR_INFO, + _MOTIF_DRAG_RECEIVER_INFO, + _MOTIF_DRAG_WINDOW, + _MOTIF_DRAG_TARGETS, + + XmTRANSFER_SUCCESS, + XmTRANSFER_FAILURE, + + // Xkb + _XKB_RULES_NAMES, + + // XEMBED + _XEMBED, + _XEMBED_INFO, + + XWacomStylus, + XWacomCursor, + XWacomEraser, + + XTabletStylus, + XTabletEraser, + + NPredefinedAtoms, + + _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, + NAtoms + }; + + static Atom atom(X11Atom atom); + static bool isSupportedByWM(Atom atom); + + static bool useXFixes(); + static int xFixesEventBase(); + + #ifndef QT_NO_XFIXES + static PtrXFixesSelectSelectionInput xFixesSelectSelectionInput(); + #endif //QT_NO_XFIXES + + + +}; + +#endif // QTESTLITESTATICINFO_H diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 6f9ad58..71232ac 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -44,6 +44,7 @@ #include "qtestliteintegration.h" #include "qtestlitescreen.h" #include "qtestlitekeyboard.h" +#include "qtestlitestaticinfo.h" #include <QtGui/QWindowSystemInterface> #include <QSocketNotifier> @@ -101,19 +102,26 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) XSetWindowBackgroundPixmap(mScreen->display(), x_window, XNone); - XSelectInput(mScreen->display(), x_window, ExposureMask | KeyPressMask | KeyReleaseMask | + XSelectInput(mScreen->display(), x_window, + ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | - PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | + PointerMotionMask | ButtonPressMask | ButtonReleaseMask | + ButtonMotionMask | PropertyChangeMask | StructureNotifyMask); gc = createGC(); - Atom wmDeleteWindowAtom = mScreen->wmDeleteWindowAtom(); - XChangeProperty (mScreen->display(), x_window, - mScreen->wmProtocolsAtom(), - XA_ATOM, 32, PropModeAppend, - (unsigned char *) &wmDeleteWindowAtom, 1); - mScreen->setWmDeleteWindowAtom(wmDeleteWindowAtom); + Atom protocols[5]; + int n = 0; + protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW); // support del window protocol + protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_TAKE_FOCUS); // support take focus window protocol + protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_PING); // support _NET_WM_PING protocol +#ifndef QT_NO_XSYNC + protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol +#endif // QT_NO_XSYNC + if (window->windowFlags() & Qt::WindowContextHelpButtonHint) + protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_CONTEXT_HELP); + XSetWMProtocols(mScreen->display(), x_window, protocols, n); } @@ -336,10 +344,11 @@ QtMWMHints QTestLiteWindow::getMWMHints() const int format; ulong nitems, bytesLeft; uchar *data = 0; - if ((XGetWindowProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints(), 0, 5, false, - mScreen->atomForMotifWmHints(), &type, &format, &nitems, &bytesLeft, + Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS); + if ((XGetWindowProperty(mScreen->display(), x_window, atomForMotifWmHints, 0, 5, false, + atomForMotifWmHints, &type, &format, &nitems, &bytesLeft, &data) == Success) - && (type == mScreen->atomForMotifWmHints() + && (type == atomForMotifWmHints && format == 32 && nitems >= 5)) { mwmhints = *(reinterpret_cast<QtMWMHints *>(data)); @@ -359,12 +368,13 @@ QtMWMHints QTestLiteWindow::getMWMHints() const void QTestLiteWindow::setMWMHints(const QtMWMHints &mwmhints) { + Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS); if (mwmhints.flags != 0l) { XChangeProperty(mScreen->display(), x_window, - mScreen->atomForMotifWmHints(), mScreen->atomForMotifWmHints(), 32, + atomForMotifWmHints, atomForMotifWmHints, 32, PropModeReplace, (unsigned char *) &mwmhints, 5); } else { - XDeleteProperty(mScreen->display(), x_window, mScreen->atomForMotifWmHints()); + XDeleteProperty(mScreen->display(), x_window, atomForMotifWmHints); } } diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index d2f2562..9f8075c 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -10,7 +10,10 @@ SOURCES = \ qtestlitewindow.cpp \ qtestlitecursor.cpp \ qtestlitescreen.cpp \ - qtestlitekeyboard.cpp + qtestlitekeyboard.cpp \ + qtestliteclipboard.cpp \ + qtestlitemime.cpp \ + qtestlitestaticinfo.cpp HEADERS = \ qtestliteintegration.h \ @@ -18,7 +21,10 @@ HEADERS = \ qtestlitewindow.h \ qtestlitecursor.h \ qtestlitescreen.h \ - qtestlitekeyboard.h + qtestlitekeyboard.h \ + qtestliteclipboard.h \ + qtestlitemime.h \ + qtestlitestaticinfo.h LIBS += -lX11 -lXext -- cgit v0.12 From afc9371b68d7db91c0874b3923a376224656e4c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 3 Jan 2011 16:28:29 +0100 Subject: Renamed QTestLiteStaticInfo to QTestLiteStatic --- .../platforms/testlite/qtestliteclipboard.cpp | 38 +++++------ src/plugins/platforms/testlite/qtestlitemime.cpp | 46 ++++++------- src/plugins/platforms/testlite/qtestlitescreen.cpp | 8 +-- .../platforms/testlite/qtestlitestaticinfo.cpp | 79 ++++++++++++++++++---- .../platforms/testlite/qtestlitestaticinfo.h | 3 +- src/plugins/platforms/testlite/qtestlitewindow.cpp | 14 ++-- 6 files changed, 121 insertions(+), 67 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp index fdd6d30..9e1b387 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.cpp +++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp @@ -28,7 +28,7 @@ const QMimeData * QTestLiteClipboard::mimeData(QClipboard::Mode mode) const QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this); that->m_xClipboard = new QTestLiteMime(mode,that); } - Window clipboardOwner = XGetSelectionOwner(screen()->display(),QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD)); + Window clipboardOwner = XGetSelectionOwner(screen()->display(),QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD)); if (clipboardOwner == owner()) { return m_clientClipboard; } else { @@ -49,7 +49,7 @@ void QTestLiteClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) break; case QClipboard::Clipboard: - modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); + modeAtom = QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD); d = &m_clientClipboard; break; @@ -131,16 +131,16 @@ Atom QTestLiteClipboard::sendTargetsSelection(QMimeData *d, Window window, Atom QVector<Atom> types; QStringList formats = QInternalMimeData::formatsHelper(d); for (int i = 0; i < formats.size(); ++i) { - QList<Atom> atoms = QTestLiteMime::xdndMimeAtomsForFormat(screen()->display(),formats.at(i)); + QList<Atom> atoms = QTestLiteMime::mimeAtomsForFormat(screen()->display(),formats.at(i)); for (int j = 0; j < atoms.size(); ++j) { if (!types.contains(atoms.at(j))) types.append(atoms.at(j)); } } - types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS)); - types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE)); - types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP)); - types.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::SAVE_TARGETS)); + types.append(QTestLiteStatic::atom(QTestLiteStatic::TARGETS)); + types.append(QTestLiteStatic::atom(QTestLiteStatic::MULTIPLE)); + types.append(QTestLiteStatic::atom(QTestLiteStatic::TIMESTAMP)); + types.append(QTestLiteStatic::atom(QTestLiteStatic::SAVE_TARGETS)); XChangeProperty(screen()->display(), window, property, XA_ATOM, 32, PropModeReplace, (uchar *) types.data(), types.size()); @@ -164,7 +164,7 @@ Atom QTestLiteClipboard::sendSelection(QMimeData *d, Atom target, Window window, // don't allow INCR transfers when using MULTIPLE or to // Motif clients (since Motif doesn't support INCR) - static Atom motif_clip_temporary = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIP_TEMPORARY); + static Atom motif_clip_temporary = QTestLiteStatic::atom(QTestLiteStatic::CLIP_TEMPORARY); bool allow_incr = property != motif_clip_temporary; // X_ChangeProperty protocol request is 24 bytes @@ -172,7 +172,7 @@ Atom QTestLiteClipboard::sendSelection(QMimeData *d, Atom target, Window window, if (data.size() > increment && allow_incr) { long bytes = data.size(); XChangeProperty(screen()->display(), window, property, - QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR), 32, PropModeReplace, (uchar *) &bytes, 1); + QTestLiteStatic::atom(QTestLiteStatic::INCR), 32, PropModeReplace, (uchar *) &bytes, 1); // (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); qDebug() << "not implemented INCRT just YET!"; @@ -212,7 +212,7 @@ void QTestLiteClipboard::handleSelectionRequest(XEvent *xevent) QMimeData *d; if (req->selection == XA_PRIMARY) { d = m_clientSelection; - } else if (req->selection == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD)) { + } else if (req->selection == QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD)) { d = m_clientClipboard; } else { qWarning("QClipboard: Unknown selection '%lx'", req->selection); @@ -226,9 +226,9 @@ void QTestLiteClipboard::handleSelectionRequest(XEvent *xevent) return; } - Atom xa_targets = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS); - Atom xa_multiple = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::MULTIPLE); - Atom xa_timestamp = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TIMESTAMP); + Atom xa_targets = QTestLiteStatic::atom(QTestLiteStatic::TARGETS); + Atom xa_multiple = QTestLiteStatic::atom(QTestLiteStatic::MULTIPLE); + Atom xa_timestamp = QTestLiteStatic::atom(QTestLiteStatic::TIMESTAMP); struct AtomPair { Atom target; Atom property; } *multi = 0; Atom multi_type = XNone; @@ -394,7 +394,7 @@ bool QTestLiteClipboard::clipboardReadProperty(Window win, Atom property, bool d XFree((char*)data); } - if (*format == 8 && *type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) { + if (*format == 8 && *type == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) { // convert COMPOUND_TEXT to a multibyte string XTextProperty textprop; textprop.encoding = *type; @@ -492,8 +492,8 @@ QByteArray QTestLiteClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom) XSelectInput(screen()->display(), win, NoEventMask); // don't listen for any events - XDeleteProperty(screen()->display(), win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION)); - XConvertSelection(screen()->display(), modeAtom, fmtatom, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), win, CurrentTime); + XDeleteProperty(screen()->display(), win, QTestLiteStatic::atom(QTestLiteStatic::_QT_SELECTION)); + XConvertSelection(screen()->display(), modeAtom, fmtatom, QTestLiteStatic::atom(QTestLiteStatic::_QT_SELECTION), win, CurrentTime); XSync(screen()->display(), false); XEvent xevent; @@ -505,10 +505,10 @@ QByteArray QTestLiteClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom) Atom type; XSelectInput(screen()->display(), win, PropertyChangeMask); - if (clipboardReadProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), true, &buf, 0, &type, 0)) { - if (type == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::INCR)) { + if (clipboardReadProperty(win, QTestLiteStatic::atom(QTestLiteStatic::_QT_SELECTION), true, &buf, 0, &type, 0)) { + if (type == QTestLiteStatic::atom(QTestLiteStatic::INCR)) { int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0; - buf = clipboardReadIncrementalProperty(win, QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_QT_SELECTION), nbytes, false); + buf = clipboardReadIncrementalProperty(win, QTestLiteStatic::atom(QTestLiteStatic::_QT_SELECTION), nbytes, false); } } diff --git a/src/plugins/platforms/testlite/qtestlitemime.cpp b/src/plugins/platforms/testlite/qtestlitemime.cpp index 6261383..6a08b8c 100644 --- a/src/plugins/platforms/testlite/qtestlitemime.cpp +++ b/src/plugins/platforms/testlite/qtestlitemime.cpp @@ -99,7 +99,7 @@ QString QTestLiteMime::xdndMimeAtomToString(Display *display, Atom a) { if (!a) return 0; - if (a == XA_STRING || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)) { + if (a == XA_STRING || a == QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING)) { return "text/plain"; // some Xdnd clients are dumb } char *atom = XGetAtomName(display, a); @@ -123,10 +123,10 @@ QStringList QTestLiteMime::xdndMimeFormatsForAtom(Display *display, Atom a) formats.append(atomName); // special cases for string type - if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING) + if (a == QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING) || a == XA_STRING - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + || a == QTestLiteStatic::atom(QTestLiteStatic::TEXT) + || a == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) formats.append(QLatin1String("text/plain")); // special cases for uris @@ -152,27 +152,27 @@ bool QTestLiteMime::xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mim *dataFormat = 16; ret = true; } else { - if ((a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING) + if ((a == QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING) || a == XA_STRING - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + || a == QTestLiteStatic::atom(QTestLiteStatic::TEXT) + || a == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) { - if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)){ + if (a == QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING)){ *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData); ret = true; } else if (a == XA_STRING) { *data = QString::fromUtf8(QInternalMimeData::renderDataHelper( QLatin1String("text/plain"), mimeData)).toLocal8Bit(); ret = true; - } else if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) { + } else if (a == QTestLiteStatic::atom(QTestLiteStatic::TEXT) + || a == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) { // the ICCCM states that TEXT and COMPOUND_TEXT are in the // encoding of choice, so we choose the encoding of the locale QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper( QLatin1String("text/plain"), mimeData)).toLocal8Bit(); char *list[] = { strData.data(), NULL }; - XICCEncodingStyle style = (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + XICCEncodingStyle style = (a == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) ? XCompoundTextStyle : XStdICCTextStyle; XTextProperty textprop; if (list[0] != NULL @@ -222,10 +222,10 @@ QList<Atom> QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QStrin // special cases for strings if (format == QLatin1String("text/plain")) { - atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)); + atoms.append(QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING)); atoms.append(XA_STRING); - atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT)); - atoms.append(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)); + atoms.append(QTestLiteStatic::atom(QTestLiteStatic::TEXT)); + atoms.append(QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)); } // special cases for uris @@ -262,12 +262,12 @@ QVariant QTestLiteMime::xdndMimeConvertToFormat(Display *display, Atom a, const // special cases for string types if (format == QLatin1String("text/plain")) { - if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING)) + if (a == QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING)) return QString::fromUtf8(data); if (a == XA_STRING) return QString::fromLatin1(data); - if (a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT) - || a == QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT)) + if (a == QTestLiteStatic::atom(QTestLiteStatic::TEXT) + || a == QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT)) // #### might be wrong for COMPUND_TEXT return QString::fromLocal8Bit(data, data.size()); } @@ -312,12 +312,12 @@ Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &forma // find matches for string types if (format == QLatin1String("text/plain")) { - if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING))) - return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::UTF8_STRING); - if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT))) - return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::COMPOUND_TEXT); - if (atoms.contains(QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT))) - return QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TEXT); + if (atoms.contains(QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING))) + return QTestLiteStatic::atom(QTestLiteStatic::UTF8_STRING); + if (atoms.contains(QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT))) + return QTestLiteStatic::atom(QTestLiteStatic::COMPOUND_TEXT); + if (atoms.contains(QTestLiteStatic::atom(QTestLiteStatic::TEXT))) + return QTestLiteStatic::atom(QTestLiteStatic::TEXT); if (atoms.contains(XA_STRING)) return XA_STRING; } diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp index 2ae7028..82dab9a 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.cpp +++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp @@ -248,14 +248,14 @@ QTestLiteScreen::~QTestLiteScreen() bool QTestLiteScreen::handleEvent(XEvent *xe) { int quit = false; - QTestLiteWindow *xw = 0; + QTestLiteWindow *platformWindow = 0; QWidget *widget = QWidget::find(xe->xany.window); if (widget) { xw = static_cast<QTestLiteWindow *>(widget->platformWindow()); } - Atom wmProtocolsAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_PROTOCOLS); - Atom wmDeleteWindowAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW); + Atom wmProtocolsAtom = QTestLiteStatic::atom(QTestLiteStatic::WM_PROTOCOLS); + Atom wmDeleteWindowAtom = QTestLiteStatic::atom(QTestLiteStatic::WM_DELETE_WINDOW); switch (xe->type) { case ClientMessage: @@ -346,7 +346,7 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer) { - Atom clipboard = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); + Atom clipboard = QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD); return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY || e->xselectionrequest.selection == clipboard)) || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp index 20d73a2..875ac9e 100644 --- a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp @@ -246,7 +246,7 @@ public: return supported; } - Atom atom(QTestLiteStaticInfo::X11Atom atom) + Atom atom(QTestLiteStatic::X11Atom atom) { return m_allAtoms[atom]; } @@ -260,10 +260,58 @@ public: return ptrXFixesSelectSelectionInput; } + QImage qimageFromXImage(XImage *xi) + { + QImage::Format format = QImage::Format_ARGB32_Premultiplied; + if (xi->depth == 24) + format = QImage::Format_RGB32; + else if (xi->depth == 16) + format = QImage::Format_RGB16; + + QImage image = QImage((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format).copy(); + + // we may have to swap the byte order + if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) + || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) + { + for (int i=0; i < image.height(); i++) { + if (xi->depth == 16) { + ushort *p = (ushort*)image.scanLine(i); + ushort *end = p + image.width(); + while (p < end) { + *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); + p++; + } + } else { + uint *p = (uint*)image.scanLine(i); + uint *end = p + image.width(); + while (p < end) { + *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) + | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); + p++; + } + } + } + } + + // fix-up alpha channel + if (format == QImage::Format_RGB32) { + QRgb *p = (QRgb *)image.bits(); + for (int y = 0; y < xi->height; ++y) { + for (int x = 0; x < xi->width; ++x) + p[x] |= 0xff000000; + p += xi->bytes_per_line / 4; + } + } + + return image; + } + + private: void initializeAllAtoms(QTestLiteScreen *screen) { - const char *names[QTestLiteStaticInfo::NAtoms]; + const char *names[QTestLiteStatic::NAtoms]; const char *ptr = x11_atomnames; int i = 0; @@ -274,17 +322,17 @@ private: ++ptr; } - Q_ASSERT(i == QTestLiteStaticInfo::NPredefinedAtoms); + Q_ASSERT(i == QTestLiteStatic::NPredefinedAtoms); QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); settings_atom_name += XDisplayName(qPrintable(screen->displayName())); names[i++] = settings_atom_name; - Q_ASSERT(i == QTestLiteStaticInfo::NAtoms); + Q_ASSERT(i == QTestLiteStatic::NAtoms); #if 0//defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6) XInternAtoms(screen->display(), (char **)names, i, False, m_allAtoms); #else - for (i = 0; i < QTestLiteStaticInfo::NAtoms; ++i) + for (i = 0; i < QTestLiteStatic::NAtoms; ++i) m_allAtoms[i] = XInternAtom(screen->display(), (char *)names[i], False); #endif } @@ -298,7 +346,7 @@ private: unsigned char *data = 0; int e = XGetWindowProperty(screen->display(), screen->rootWindow(), - this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), 0, 0, + this->atom(QTestLiteStatic::_NET_SUPPORTED), 0, 0, False, XA_ATOM, &type, &format, &nitems, &after, &data); if (data) XFree(data); @@ -309,7 +357,7 @@ private: while (after > 0) { XGetWindowProperty(screen->display(), screen->rootWindow(), - this->atom(QTestLiteStaticInfo::_NET_SUPPORTED), offset, 1024, + this->atom(QTestLiteStatic::_NET_SUPPORTED), offset, 1024, False, XA_ATOM, &type, &format, &nitems, &after, &data); if (type == XA_ATOM && format == 32) { @@ -367,7 +415,7 @@ private: } Atom *m_supportedAtoms; - Atom m_allAtoms[QTestLiteStaticInfo::NAtoms]; + Atom m_allAtoms[QTestLiteStatic::NAtoms]; #ifndef QT_NO_XFIXES PtrXFixesQueryExtension ptrXFixesQueryExtension; @@ -385,28 +433,28 @@ private: Q_GLOBAL_STATIC(QTestLiteStaticInfoPrivate, qTestLiteStaticInfoPrivate); -Atom QTestLiteStaticInfo::atom(QTestLiteStaticInfo::X11Atom atom) +Atom QTestLiteStatic::atom(QTestLiteStatic::X11Atom atom) { return qTestLiteStaticInfoPrivate()->atom(atom); } -bool QTestLiteStaticInfo::isSupportedByWM(Atom atom) +bool QTestLiteStatic::isSupportedByWM(Atom atom) { return qTestLiteStaticInfoPrivate()->isSupportedByWM(atom); } -bool QTestLiteStaticInfo::useXFixes() +bool QTestLiteStatic::useXFixes() { return qTestLiteStaticInfoPrivate()->useXFixes(); } -int QTestLiteStaticInfo::xFixesEventBase() +int QTestLiteStatic::xFixesEventBase() { return qTestLiteStaticInfoPrivate()->xFixesEventBase(); } #ifndef QT_NO_XFIXES -PtrXFixesSelectSelectionInput QTestLiteStaticInfo::xFixesSelectSelectionInput() +PtrXFixesSelectSelectionInput QTestLiteStatic::xFixesSelectSelectionInput() { qDebug() << qTestLiteStaticInfoPrivate()->useXFixes(); if (!qTestLiteStaticInfoPrivate()->useXFixes()) @@ -414,4 +462,9 @@ PtrXFixesSelectSelectionInput QTestLiteStaticInfo::xFixesSelectSelectionInput() return qTestLiteStaticInfoPrivate()->xFixesSelectSelectionInput(); } + +QImage QTestLiteStatic::qimageFromXImage(XImage *xi) +{ + return qTestLiteStaticInfoPrivate()->qimageFromXImage(xi); +} #endif //QT_NO_XFIXES diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.h b/src/plugins/platforms/testlite/qtestlitestaticinfo.h index ed0f7bd..328de60 100644 --- a/src/plugins/platforms/testlite/qtestlitestaticinfo.h +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.h @@ -190,7 +190,7 @@ enum { #endif -class QTestLiteStaticInfo +class QTestLiteStatic { public: enum X11Atom { @@ -364,6 +364,7 @@ public: static PtrXFixesSelectSelectionInput xFixesSelectSelectionInput(); #endif //QT_NO_XFIXES + static QImage qimageFromXImage(XImage *xi); }; diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 71232ac..e8d40d7 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -113,14 +113,14 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) Atom protocols[5]; int n = 0; - protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_DELETE_WINDOW); // support del window protocol - protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::WM_TAKE_FOCUS); // support take focus window protocol - protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_PING); // support _NET_WM_PING protocol + protocols[n++] = QTestLiteStatic::atom(QTestLiteStatic::WM_DELETE_WINDOW); // support del window protocol + protocols[n++] = QTestLiteStatic::atom(QTestLiteStatic::WM_TAKE_FOCUS); // support take focus window protocol + protocols[n++] = QTestLiteStatic::atom(QTestLiteStatic::_NET_WM_PING); // support _NET_WM_PING protocol #ifndef QT_NO_XSYNC - protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol + protocols[n++] = QTestLiteStatic::atom(QTestLiteStatic::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol #endif // QT_NO_XSYNC if (window->windowFlags() & Qt::WindowContextHelpButtonHint) - protocols[n++] = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_NET_WM_CONTEXT_HELP); + protocols[n++] = QTestLiteStatic::atom(QTestLiteStatic::_NET_WM_CONTEXT_HELP); XSetWMProtocols(mScreen->display(), x_window, protocols, n); } @@ -344,7 +344,7 @@ QtMWMHints QTestLiteWindow::getMWMHints() const int format; ulong nitems, bytesLeft; uchar *data = 0; - Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS); + Atom atomForMotifWmHints = QTestLiteStatic::atom(QTestLiteStatic::_MOTIF_WM_HINTS); if ((XGetWindowProperty(mScreen->display(), x_window, atomForMotifWmHints, 0, 5, false, atomForMotifWmHints, &type, &format, &nitems, &bytesLeft, &data) == Success) @@ -368,7 +368,7 @@ QtMWMHints QTestLiteWindow::getMWMHints() const void QTestLiteWindow::setMWMHints(const QtMWMHints &mwmhints) { - Atom atomForMotifWmHints = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::_MOTIF_WM_HINTS); + Atom atomForMotifWmHints = QTestLiteStatic::atom(QTestLiteStatic::_MOTIF_WM_HINTS); if (mwmhints.flags != 0l) { XChangeProperty(mScreen->display(), x_window, atomForMotifWmHints, atomForMotifWmHints, 32, -- cgit v0.12 From 6138bcd3543ac605731c9626191e7914f0995858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 3 Jan 2011 16:30:32 +0100 Subject: Renamed variable name in TestLite event handling --- src/plugins/platforms/testlite/qtestlitescreen.cpp | 40 +++++++++++----------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestlitescreen.cpp b/src/plugins/platforms/testlite/qtestlitescreen.cpp index 82dab9a..c211ee6 100644 --- a/src/plugins/platforms/testlite/qtestlitescreen.cpp +++ b/src/plugins/platforms/testlite/qtestlitescreen.cpp @@ -251,7 +251,7 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) QTestLiteWindow *platformWindow = 0; QWidget *widget = QWidget::find(xe->xany.window); if (widget) { - xw = static_cast<QTestLiteWindow *>(widget->platformWindow()); + platformWindow = static_cast<QTestLiteWindow *>(widget->platformWindow()); } Atom wmProtocolsAtom = QTestLiteStatic::atom(QTestLiteStatic::WM_PROTOCOLS); @@ -262,33 +262,33 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { Atom a = xe->xclient.data.l[0]; if (a == wmDeleteWindowAtom) - xw->handleCloseEvent(); + platformWindow->handleCloseEvent(); } break; case Expose: - if (xw) + if (platformWindow) if (xe->xexpose.count == 0) - xw->paintEvent(); + platformWindow->paintEvent(); break; case ConfigureNotify: - if (xw) - xw->resizeEvent(&xe->xconfigure); + if (platformWindow) + platformWindow->resizeEvent(&xe->xconfigure); break; case ButtonPress: - if (xw) - xw->mousePressEvent(&xe->xbutton); + if (platformWindow) + platformWindow->mousePressEvent(&xe->xbutton); break; case ButtonRelease: - if (xw) - xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); + if (platformWindow) + platformWindow->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); break; case MotionNotify: - if (xw) - xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); + if (platformWindow) + platformWindow->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); break; case XKeyPress: @@ -300,23 +300,23 @@ bool QTestLiteScreen::handleEvent(XEvent *xe) break; case EnterNotify: - if (xw) - xw->handleEnterEvent(); + if (platformWindow) + platformWindow->handleEnterEvent(); break; case LeaveNotify: - if (xw) - xw->handleLeaveEvent(); + if (platformWindow) + platformWindow->handleLeaveEvent(); break; case XFocusIn: - if (xw) - xw->handleFocusInEvent(); + if (platformWindow) + platformWindow->handleFocusInEvent(); break; case XFocusOut: - if (xw) - xw->handleFocusOutEvent(); + if (platformWindow) + platformWindow->handleFocusOutEvent(); break; case PropertyNotify: -- cgit v0.12 From 0ceed999bbf25d19b3ded8a1b300cf0c6129f775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 3 Jan 2011 16:31:44 +0100 Subject: Create clearer sepperation between TestLiteMime and QTestliteClipboard --- .../platforms/testlite/qtestliteclipboard.cpp | 130 +++++++++++++++- .../platforms/testlite/qtestliteclipboard.h | 7 +- src/plugins/platforms/testlite/qtestlitemime.cpp | 173 ++++++--------------- src/plugins/platforms/testlite/qtestlitemime.h | 32 +--- 4 files changed, 181 insertions(+), 161 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp index 9e1b387..25c16ea 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.cpp +++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp @@ -7,6 +7,104 @@ #include <QtCore/QDebug> +class QTestLiteClipboardMime : public QTestLiteMime +{ + Q_OBJECT +public: + QTestLiteClipboardMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard) + : QTestLiteMime() + , m_clipboard(clipboard) + { + switch (mode) { + case QClipboard::Selection: + modeAtom = XA_PRIMARY; + break; + + case QClipboard::Clipboard: + modeAtom = QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD); + break; + + default: + qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode"); + break; + } + } + +protected: + QStringList formats_sys() const + { + if (empty()) + return QStringList(); + + if (!formatList.count()) { + QTestLiteClipboardMime *that = const_cast<QTestLiteClipboardMime *>(this); + // get the list of targets from the current clipboard owner - we do this + // once so that multiple calls to this function don't require multiple + // server round trips... + that->format_atoms = m_clipboard->getDataInFormat(modeAtom,QTestLiteStatic::atom(QTestLiteStatic::TARGETS)); + + if (format_atoms.size() > 0) { + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + + for (int i = 0; i < size; ++i) { + if (targets[i] == 0) + continue; + + QStringList formatsForAtom = mimeFormatsForAtom(m_clipboard->screen()->display(),targets[i]); + for (int j = 0; j < formatsForAtom.size(); ++j) { + if (!formatList.contains(formatsForAtom.at(j))) + that->formatList.append(formatsForAtom.at(j)); + } + } + } + } + + return formatList; + } + + bool hasFormat_sys(const QString &format) const + { + QStringList list = formats(); + return list.contains(format); + } + + QVariant retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const + { + if (fmt.isEmpty() || empty()) + return QByteArray(); + + (void)formats(); // trigger update of format list + + QList<Atom> atoms; + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + for (int i = 0; i < size; ++i) + atoms.append(targets[i]); + + QByteArray encoding; + Atom fmtatom = mimeAtomForFormat(m_clipboard->screen()->display(),fmt, requestedType, atoms, &encoding); + + if (fmtatom == 0) + return QVariant(); + + return mimeConvertToFormat(m_clipboard->screen()->display(),fmtatom, m_clipboard->getDataInFormat(modeAtom,fmtatom), fmt, requestedType, encoding); + } +private: + bool empty() const + { + Window win = XGetSelectionOwner(m_clipboard->screen()->display(), modeAtom); + + return win == XNone; + } + + + Atom modeAtom; + QTestLiteClipboard *m_clipboard; + QStringList formatList; + QByteArray format_atoms; +}; + const int QTestLiteClipboard::clipboard_timeout = 5000; QTestLiteClipboard::QTestLiteClipboard(QTestLiteScreen *screen) @@ -26,7 +124,7 @@ const QMimeData * QTestLiteClipboard::mimeData(QClipboard::Mode mode) const if (mode == QClipboard::Clipboard) { if (!m_xClipboard) { QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this); - that->m_xClipboard = new QTestLiteMime(mode,that); + that->m_xClipboard = new QTestLiteClipboardMime(mode,that); } Window clipboardOwner = XGetSelectionOwner(screen()->display(),QTestLiteStatic::atom(QTestLiteStatic::CLIPBOARD)); if (clipboardOwner == owner()) { @@ -34,6 +132,17 @@ const QMimeData * QTestLiteClipboard::mimeData(QClipboard::Mode mode) const } else { return m_xClipboard; } + } else if (mode == QClipboard::Selection) { + if (!m_xSelection) { + QTestLiteClipboard *that = const_cast<QTestLiteClipboard *>(this); + that->m_xSelection = new QTestLiteClipboardMime(mode,that); + } + Window clipboardOwner = XGetSelectionOwner(screen()->display(),XA_PRIMARY); + if (clipboardOwner == owner()) { + return m_clientSelection; + } else { + return m_xSelection; + } } return 0; } @@ -71,14 +180,19 @@ void QTestLiteClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) XSetSelectionOwner(m_screen->display(), modeAtom, newOwner, CurrentTime); if (XGetSelectionOwner(m_screen->display(), modeAtom) != newOwner) { -// qWarning("QClipboard::setData: Cannot set X11 selection owner for %s", -// xdndAtomToString(atom).data()); - *d = 0; - return; + qWarning("QClipboard::setData: Cannot set X11 selection owner"); } } +bool QTestLiteClipboard::supportsMode(QClipboard::Mode mode) const +{ + if (mode == QClipboard::Clipboard || mode == QClipboard::Selection) + return true; + return false; +} + + QTestLiteScreen * QTestLiteClipboard::screen() const { return m_screen; @@ -153,14 +267,14 @@ Atom QTestLiteClipboard::sendSelection(QMimeData *d, Atom target, Window window, int dataFormat = 0; QByteArray data; - QString fmt = QTestLiteMime::xdndMimeAtomToString(screen()->display(), target); + QString fmt = QTestLiteMime::mimeAtomToString(screen()->display(), target); if (fmt.isEmpty()) { // Not a MIME type we have qDebug() << "QClipboard: send_selection(): converting to type '%s' is not supported" << fmt.data(); return XNone; } qDebug() << "QClipboard: send_selection(): converting to type '%s'" << fmt.data(); - if (QTestLiteMime::xdndMimeDataForAtom(screen()->display(),target, d, &data, &atomFormat, &dataFormat)) { + if (QTestLiteMime::mimeDataForAtom(screen()->display(),target, d, &data, &atomFormat, &dataFormat)) { // don't allow INCR transfers when using MULTIPLE or to // Motif clients (since Motif doesn't support INCR) @@ -517,3 +631,5 @@ QByteArray QTestLiteClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom) return buf; } + +#include "qtestliteclipboard.moc" diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.h b/src/plugins/platforms/testlite/qtestliteclipboard.h index 31e42b7..22d3734 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.h +++ b/src/plugins/platforms/testlite/qtestliteclipboard.h @@ -5,7 +5,6 @@ #include "qtestlitestaticinfo.h" class QTestLiteScreen; -class QTestLiteMime; class QTestLiteClipboard : public QPlatformClipboard { public: @@ -14,6 +13,8 @@ public: const QMimeData *mimeData(QClipboard::Mode mode) const; void setMimeData(QMimeData *data, QClipboard::Mode mode); + bool supportsMode(QClipboard::Mode mode) const; + QTestLiteScreen *screen() const; Window requestor() const; @@ -36,10 +37,10 @@ private: QTestLiteScreen *m_screen; - QTestLiteMime *m_xClipboard; + QMimeData *m_xClipboard; QMimeData *m_clientClipboard; - QTestLiteMime *m_xSelection; + QMimeData *m_xSelection; QMimeData *m_clientSelection; Window m_requestor; diff --git a/src/plugins/platforms/testlite/qtestlitemime.cpp b/src/plugins/platforms/testlite/qtestlitemime.cpp index 6a08b8c..32cacce 100644 --- a/src/plugins/platforms/testlite/qtestlitemime.cpp +++ b/src/plugins/platforms/testlite/qtestlitemime.cpp @@ -4,98 +4,21 @@ #include "qtestlitescreen.h" #include <QtCore/QTextCodec> +#include <QtGui/QImageWriter> +#include <QtCore/QBuffer> -QTestLiteMime::QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard) - : QInternalMimeData(), m_clipboard(clipboard) -{ - switch (mode) { - case QClipboard::Selection: - modeAtom = XA_PRIMARY; - break; - - case QClipboard::Clipboard: - modeAtom = QTestLiteStaticInfo::atom(QTestLiteStaticInfo::CLIPBOARD); - break; - - default: - qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode"); - break; - } -} +QTestLiteMime::QTestLiteMime() + : QInternalMimeData() +{ } QTestLiteMime::~QTestLiteMime() -{ -} +{} -bool QTestLiteMime::empty() const -{ - Window win = XGetSelectionOwner(m_clipboard->screen()->display(), modeAtom); - - return win == XNone; -} -QStringList QTestLiteMime::formats_sys() const -{ - if (empty()) - return QStringList(); - if (!formatList.count()) { - // get the list of targets from the current clipboard owner - we do this - // once so that multiple calls to this function don't require multiple - // server round trips... - format_atoms = m_clipboard->getDataInFormat(modeAtom,QTestLiteStaticInfo::atom(QTestLiteStaticInfo::TARGETS)); - if (format_atoms.size() > 0) { - Atom *targets = (Atom *) format_atoms.data(); - int size = format_atoms.size() / sizeof(Atom); - - for (int i = 0; i < size; ++i) { - if (targets[i] == 0) - continue; - - QStringList formatsForAtom = xdndMimeFormatsForAtom(m_clipboard->screen()->display(),targets[i]); - for (int j = 0; j < formatsForAtom.size(); ++j) { - if (!formatList.contains(formatsForAtom.at(j))) - formatList.append(formatsForAtom.at(j)); - } - } - } - } - - return formatList; -} - -bool QTestLiteMime::hasFormat_sys(const QString &format) const -{ - QStringList list = formats(); - return list.contains(format); -} - -QVariant QTestLiteMime::retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const -{ - if (fmt.isEmpty() || empty()) - return QByteArray(); - - (void)formats(); // trigger update of format list - - QList<Atom> atoms; - Atom *targets = (Atom *) format_atoms.data(); - int size = format_atoms.size() / sizeof(Atom); - for (int i = 0; i < size; ++i) - atoms.append(targets[i]); - - QByteArray encoding; - Atom fmtatom = xdndMimeAtomForFormat(m_clipboard->screen()->display(),fmt, requestedType, atoms, &encoding); - - if (fmtatom == 0) - return QVariant(); - - return xdndMimeConvertToFormat(m_clipboard->screen()->display(),fmtatom, m_clipboard->getDataInFormat(modeAtom,fmtatom), fmt, requestedType, encoding); -} - - -QString QTestLiteMime::xdndMimeAtomToString(Display *display, Atom a) +QString QTestLiteMime::mimeAtomToString(Display *display, Atom a) { if (!a) return 0; @@ -108,18 +31,18 @@ QString QTestLiteMime::xdndMimeAtomToString(Display *display, Atom a) return result; } -Atom QTestLiteMime::xdndMimeStringToAtom(Display *display, const QString &mimeType) +Atom QTestLiteMime::mimeStringToAtom(Display *display, const QString &mimeType) { if (mimeType.isEmpty()) return 0; return XInternAtom(display, mimeType.toLatin1().constData(), False); } -QStringList QTestLiteMime::xdndMimeFormatsForAtom(Display *display, Atom a) +QStringList QTestLiteMime::mimeFormatsForAtom(Display *display, Atom a) { QStringList formats; if (a) { - QString atomName = xdndMimeAtomToString(display, a); + QString atomName = mimeAtomToString(display, a); formats.append(atomName); // special cases for string type @@ -140,12 +63,12 @@ QStringList QTestLiteMime::xdndMimeFormatsForAtom(Display *display, Atom a) return formats; } -bool QTestLiteMime::xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat) +bool QTestLiteMime::mimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat) { bool ret = false; *atomFormat = a; *dataFormat = 8; - QString atomName = xdndMimeAtomToString(display, a); + QString atomName = mimeAtomToString(display, a); if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) { *data = QInternalMimeData::renderDataHelper(atomName, mimeData); if (atomName == QLatin1String("application/x-color")) @@ -195,30 +118,16 @@ bool QTestLiteMime::xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mim *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2); ret = true; } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) { - QPixmap pm = qvariant_cast<QPixmap>(mimeData->imageData()); - if (a == XA_BITMAP && pm.depth() != 1) { - QImage img = pm.toImage(); - img = img.convertToFormat(QImage::Format_MonoLSB); - pm = QPixmap::fromImage(img); - } -// QDragManager *dm = QDragManager::self(); -// if (dm) { -// Pixmap handle = pm.handle(); -// *data = QByteArray((const char *) &handle, sizeof(Pixmap)); -// dm->xdndMimeTransferedPixmap[dm->xdndMimeTransferedPixmapIndex] = pm; -// dm->xdndMimeTransferedPixmapIndex = -// (dm->xdndMimeTransferedPixmapIndex + 1) % 2; -// ret = true; -// } + ret = true; } } return ret && data != 0; } -QList<Atom> QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QString &format) +QList<Atom> QTestLiteMime::mimeAtomsForFormat(Display *display, const QString &format) { QList<Atom> atoms; - atoms.append(xdndMimeStringToAtom(display, format)); + atoms.append(mimeStringToAtom(display, format)); // special cases for strings if (format == QLatin1String("text/plain")) { @@ -230,7 +139,7 @@ QList<Atom> QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QStrin // special cases for uris if (format == QLatin1String("text/uri-list")) { - atoms.append(xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url"))); + atoms.append(mimeStringToAtom(display,QLatin1String("text/x-moz-url"))); } //special cases for images @@ -242,9 +151,9 @@ QList<Atom> QTestLiteMime::xdndMimeAtomsForFormat(Display *display, const QStrin return atoms; } -QVariant QTestLiteMime::xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding) +QVariant QTestLiteMime::mimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding) { - QString atomName = xdndMimeAtomToString(display,a); + QString atomName = mimeAtomToString(display,a); if (atomName == format) return data; @@ -288,25 +197,35 @@ QVariant QTestLiteMime::xdndMimeConvertToFormat(Display *display, Atom a, const // special cas for images if (format == QLatin1String("image/ppm")) { if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { -// Pixmap xpm = *((Pixmap*)data.data()); -// if (!xpm) -// return QByteArray(); -// QPixmap qpm = QPixmap::fromX11Pixmap(xpm); -// QImageWriter imageWriter; -// imageWriter.setFormat("PPMRAW"); -// QImage imageToWrite = qpm.toImage(); -// QBuffer buf; -// buf.open(QIODevice::WriteOnly); -// imageWriter.setDevice(&buf); -// imageWriter.write(imageToWrite); -// return buf.buffer(); - return QVariant(); + Pixmap xpm = *((Pixmap*)data.data()); + if (!xpm) + return QByteArray(); + Window root; + int x; + int y; + uint width; + uint height; + uint border_width; + uint depth; + + XGetGeometry(display, xpm, &root, &x, &y, &width, &height, &border_width, &depth); + XImage *ximg = XGetImage(display,xpm,x,y,width,height,AllPlanes,depth==1 ? XYPixmap : ZPixmap); + QImage qimg = QTestLiteStatic::qimageFromXImage(ximg); + XDestroyImage(ximg); + + QImageWriter imageWriter; + imageWriter.setFormat("PPMRAW"); + QBuffer buf; + buf.open(QIODevice::WriteOnly); + imageWriter.setDevice(&buf); + imageWriter.write(qimg); + return buf.buffer(); } } return QVariant(); } -Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding) +Atom QTestLiteMime::mimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding) { requestedEncoding->clear(); @@ -324,10 +243,10 @@ Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &forma // find matches for uri types if (format == QLatin1String("text/uri-list")) { - Atom a = xdndMimeStringToAtom(display,format); + Atom a = mimeStringToAtom(display,format); if (a && atoms.contains(a)) return a; - a = xdndMimeStringToAtom(display,QLatin1String("text/x-moz-url")); + a = mimeStringToAtom(display,QLatin1String("text/x-moz-url")); if (a && atoms.contains(a)) return a; } @@ -347,14 +266,14 @@ Atom QTestLiteMime::xdndMimeAtomForFormat(Display *display, const QString &forma QString formatWithCharset = format; formatWithCharset.append(QLatin1String(";charset=utf-8")); - Atom a = xdndMimeStringToAtom(display,formatWithCharset); + Atom a = mimeStringToAtom(display,formatWithCharset); if (a && atoms.contains(a)) { *requestedEncoding = "utf-8"; return a; } } - Atom a = xdndMimeStringToAtom(display,format); + Atom a = mimeStringToAtom(display,format); if (a && atoms.contains(a)) return a; diff --git a/src/plugins/platforms/testlite/qtestlitemime.h b/src/plugins/platforms/testlite/qtestlitemime.h index e5ed7b0..449bbf3 100644 --- a/src/plugins/platforms/testlite/qtestlitemime.h +++ b/src/plugins/platforms/testlite/qtestlitemime.h @@ -11,32 +11,16 @@ class QTestLiteMime : public QInternalMimeData { Q_OBJECT public: - QTestLiteMime(QClipboard::Mode mode, QTestLiteClipboard *clipboard); + QTestLiteMime(); ~QTestLiteMime(); - bool empty() const; - static QList<Atom> xdndMimeAtomsForFormat(Display *display, const QString &format); - static QString xdndMimeAtomToString(Display *display, Atom a); - static bool xdndMimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat); - static QStringList xdndMimeFormatsForAtom(Display *display, Atom a); - static Atom xdndMimeStringToAtom(Display *display, const QString &mimeType); - - static QVariant xdndMimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding); - static Atom xdndMimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding); - - -protected: - virtual bool hasFormat_sys(const QString &mimetype) const; - virtual QStringList formats_sys() const; - - QVariant retrieveData_sys(const QString &mimetype, QVariant::Type type) const; - - -private: - QTestLiteClipboard *m_clipboard; - Atom modeAtom; - mutable QStringList formatList; - mutable QByteArray format_atoms; + static QList<Atom> mimeAtomsForFormat(Display *display, const QString &format); + static QString mimeAtomToString(Display *display, Atom a); + static bool mimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat); + static QStringList mimeFormatsForAtom(Display *display, Atom a); + static Atom mimeStringToAtom(Display *display, const QString &mimeType); + static QVariant mimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding); + static Atom mimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding); }; #endif // QTESTLITEMIME_H -- cgit v0.12 From 06568ff89c48dee8aab278b8b0538c331aa84595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 6 Dec 2010 16:05:55 +0100 Subject: Add styleHint to fallback api for fontdatabases in Lighthouse --- src/gui/text/qfont_qpa.cpp | 2 +- src/gui/text/qfontdatabase_qpa.cpp | 12 ++++++---- src/gui/text/qplatformfontdatabase_qpa.cpp | 3 ++- src/gui/text/qplatformfontdatabase_qpa.h | 2 +- .../fontconfig/qfontconfigdatabase.cpp | 27 +++++++++++++++++++++- .../fontdatabases/fontconfig/qfontconfigdatabase.h | 2 +- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp index 5fed18b..7b09b59 100644 --- a/src/gui/text/qfont_qpa.cpp +++ b/src/gui/text/qfont_qpa.cpp @@ -90,7 +90,7 @@ QString QFont::defaultFamily() const familyName = QString::fromLatin1("helvetica"); } - QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QUnicodeTables::Common); + QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QFont::StyleHint(d->request.styleHint),QUnicodeTables::Common); if (list.size()) { familyName = list.at(0); } diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index e54093c..e6d99c6 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -80,9 +80,9 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou size->handle = handle; } -static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QUnicodeTables::Script &script) +static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) { - QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,script); + QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); QFontDatabasePrivate *db = privateDb(); QStringList::iterator i; @@ -177,7 +177,11 @@ QFontEngine *loadEngine(int script, const QFontDef &request, && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) { if (family && !family->askedForFallback) { - family->fallbackFamilies = fallbackFamilies(family->name,QFont::Style(style->key.style),QUnicodeTables::Script(script)); + QFont::Style fontStyle = QFont::Style(style->key.style); + QFont::StyleHint styleHint = QFont::StyleHint(request.styleHint); + if (styleHint == QFont::AnyStyle && request.fixedPitch) + styleHint = QFont::TypeWriter; + family->fallbackFamilies = fallbackFamilies(family->name,fontStyle,styleHint,QUnicodeTables::Script(script)); family->askedForFallback = true; } @@ -287,7 +291,7 @@ QFontDatabase::findFont(int script, const QFontPrivate *fp, if (!engine) { if (!request.family.isEmpty()) { - QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QUnicodeTables::Script(script)); + QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QFont::StyleHint(request.styleHint),QUnicodeTables::Script(script)); for (int i = 0; i < fallbacks.size(); i++) { QFontDef def = request; def.family = fallbacks.at(i); diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp index d6dff41..afe762a 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.cpp +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -221,10 +221,11 @@ QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicode /*! */ -QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const { Q_UNUSED(family); Q_UNUSED(style); + Q_UNUSED(styleHint); Q_UNUSED(script); return QStringList(); } diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h index aa465ab..a1faea9 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.h +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -88,7 +88,7 @@ class Q_GUI_EXPORT QPlatformFontDatabase public: virtual void populateFontDatabase(); virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); - virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); virtual void releaseHandle(void *handle); diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 92f30fc..9b9be07 100644 --- a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -274,6 +274,25 @@ static const char *openType[] = { "nko " // N'Ko }; +static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) +{ + const char *stylehint = 0; + switch (style) { + case QFont::SansSerif: + stylehint = "sans-serif"; + break; + case QFont::Serif: + stylehint = "serif"; + break; + case QFont::TypeWriter: + stylehint = "monospace"; + break; + default: + break; + } + return stylehint; +} + void QFontconfigDatabase::populateFontDatabase() { FcFontSet *fonts; @@ -522,7 +541,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: return engine; } -QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const { QStringList fallbackFamilies; FcPattern *pattern = FcPatternCreate(); @@ -550,6 +569,12 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const FcLangSetDestroy(ls); } + const char *stylehint = getFcFamilyForStyleHint(styleHint); + if (stylehint) { + value.u.s = (const FcChar8 *)stylehint; + FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); + } + FcConfigSubstitute(0, pattern, FcMatchPattern); FcConfigSubstitute(0, pattern, FcMatchFont); diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h index 33382dc..cf62b88 100644 --- a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h @@ -50,7 +50,7 @@ class QFontconfigDatabase : public QBasicUnixFontDatabase public: void populateFontDatabase(); QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); - QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; }; #endif // QFONTCONFIGDATABASE_H -- cgit v0.12 From bc1e4e5bc898519c073b710f64c7a7da54062099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@nokia.com> Date: Wed, 5 Jan 2011 12:36:58 +0100 Subject: Compile on OS X. --- mkspecs/common/mac/qplatformdefs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/mac/qplatformdefs.h b/mkspecs/common/mac/qplatformdefs.h index 99d64ef..5d1f99a 100644 --- a/mkspecs/common/mac/qplatformdefs.h +++ b/mkspecs/common/mac/qplatformdefs.h @@ -75,7 +75,7 @@ #include <net/if.h> #endif -#include "../common/posix/qplatformdefs.h" +#include "../posix/qplatformdefs.h" #undef QT_OPEN_LARGEFILE #undef QT_SOCKLEN_T -- cgit v0.12 From 4c15dbb1eddb7bb3f3b72508be865feb97679d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@nokia.com> Date: Wed, 5 Jan 2011 14:02:58 +0100 Subject: Build on Mac OS X. --- src/plugins/platforms/testlite/testlite.pro | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index 9f8075c..eb196c3 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -28,6 +28,10 @@ HEADERS = \ LIBS += -lX11 -lXext +mac { + LIBS += -L/usr/X11/lib -lz -framework Carbon +} + include (../fontdatabases/genericunix/genericunix.pri) contains(QT_CONFIG, opengl) { -- cgit v0.12 From 1462a7ba51d25a7d022eab5533885cb1ed1c4c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Wed, 5 Jan 2011 09:04:37 +0100 Subject: Lighthouse: Make testlite compile on systems where QtOpenGL is ES2 compatible. Ie. it does not have glx. Haven't made the egl integration yet for testlite --- src/plugins/platforms/testlite/qglxintegration.cpp | 3 +++ src/plugins/platforms/testlite/qglxintegration.h | 3 +++ src/plugins/platforms/testlite/qtestliteintegration.cpp | 6 ++++-- src/plugins/platforms/testlite/qtestlitewindow.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/testlite/qglxintegration.cpp index 1dffb3e..8023014 100644 --- a/src/plugins/platforms/testlite/qglxintegration.cpp +++ b/src/plugins/platforms/testlite/qglxintegration.cpp @@ -46,6 +46,7 @@ #include "qtestlitewindow.h" #include "qtestlitescreen.h" +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include <X11/Xlib.h> #include <X11/Xutil.h> #include <GL/glx.h> @@ -371,3 +372,5 @@ QPlatformWindowFormat QGLXContext::platformWindowFormat() const } QT_END_NAMESPACE + +#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) diff --git a/src/plugins/platforms/testlite/qglxintegration.h b/src/plugins/platforms/testlite/qglxintegration.h index 5ae0b2a..abece45 100644 --- a/src/plugins/platforms/testlite/qglxintegration.h +++ b/src/plugins/platforms/testlite/qglxintegration.h @@ -49,6 +49,7 @@ #include <QtCore/QMutex> +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include <GL/glx.h> QT_BEGIN_NAMESPACE @@ -88,4 +89,6 @@ private: QT_END_NAMESPACE +#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) + #endif diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp index 537e22a..5dbe1e7 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -49,8 +49,10 @@ #include "qtestlitescreen.h" #include "qtestliteclipboard.h" -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) #include <GL/glx.h> +#endif //!defined(QT_OPENGL_ES_2) #include <private/qwindowsurface_gl_p.h> #include <private/qpixmapdata_gl_p.h> #endif //QT_NO_OPENGL @@ -128,7 +130,7 @@ QPlatformClipboard * QTestLiteIntegration::clipboard() const bool QTestLiteIntegration::hasOpenGL() const { -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) QTestLiteScreen *screen = static_cast<const QTestLiteScreen *>(mScreens.at(0)); return glXQueryExtension(screen->display(), 0, 0) != 0; #endif diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index e8d40d7..18fab4a 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -54,7 +54,7 @@ #include <QtGui/private/qwindowsurface_p.h> #include <QtGui/private/qapplication_p.h> -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include "qglxintegration.h" #endif @@ -74,7 +74,7 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); Colormap cmap = XCreateColormap(mScreen->display(),mScreen->rootWindow(),visualInfo->visual,AllocNone); @@ -83,7 +83,7 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) x_window = XCreateWindow(mScreen->display(), mScreen->rootWindow(),x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWColormap, &a); -#endif //QT_NO_OPENGL +#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) } else { x_window = XCreateSimpleWindow(mScreen->display(), mScreen->rootWindow(), x, y, w, h, 0 /*border_width*/, @@ -548,7 +548,7 @@ QPlatformGLContext *QTestLiteWindow::glContext() const return 0; if (!mGLContext) { QTestLiteWindow *that = const_cast<QTestLiteWindow *>(this); -#ifndef QT_NO_OPENGL +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat()); #endif } -- cgit v0.12 From cc8877068dc6ae8f3142ffec0b85f6fbac4a0d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Wed, 5 Jan 2011 17:14:54 +0100 Subject: Lighthouse: Adding support for EGL to testlite There is really no good way of detecting if to use EGL instead of GLX using qmake. So this is the behavior for now: if QtOpenGL is compiled with "desktop gl" then use GLX if its compiled with OpenGLES2 then use EGL. --- .../platforms/eglconvenience/qeglconvenience.cpp | 8 ++ .../platforms/eglconvenience/qeglconvenience.h | 1 + .../platforms/testlite/qtestliteeglintegration.cpp | 145 +++++++++++++++++++++ .../platforms/testlite/qtestliteeglintegration.h | 13 ++ .../platforms/testlite/qtestliteintegration.cpp | 19 ++- src/plugins/platforms/testlite/qtestlitewindow.cpp | 94 ++++++++++--- src/plugins/platforms/testlite/qtestlitewindow.h | 2 + src/plugins/platforms/testlite/testlite.pro | 37 ++++-- 8 files changed, 287 insertions(+), 32 deletions(-) create mode 100644 src/plugins/platforms/testlite/qtestliteeglintegration.cpp create mode 100644 src/plugins/platforms/testlite/qtestliteeglintegration.h diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp index b203fe8..1612f79 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -313,4 +313,12 @@ QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, con return format; } +bool q_hasEglExtension(EGLDisplay display, const char* extensionName) +{ + QList<QByteArray> extensions = + QByteArray(reinterpret_cast<const char *> + (eglQueryString(display, EGL_EXTENSIONS))).split(' '); + return extensions.contains(extensionName); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h index 604262b..98c30b8 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.h +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -53,6 +53,7 @@ QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat & bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes); EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format); QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); +bool q_hasEglExtension(EGLDisplay display,const char* extensionName); QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestliteeglintegration.cpp b/src/plugins/platforms/testlite/qtestliteeglintegration.cpp new file mode 100644 index 0000000..3cbcc05 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteeglintegration.cpp @@ -0,0 +1,145 @@ +#include "qtestliteeglintegration.h" + +static int countBits(unsigned long mask) +{ + int count = 0; + while (mask != 0) { + if (mask & 1) + ++count; + mask >>= 1; + } + return count; +} + +VisualID QTestLiteEglIntegration::getCompatibleVisualId(Display *display, EGLConfig config) +{ + VisualID visualId = 0; + EGLint eglValue = 0; + + EGLDisplay eglDisplay = eglGetDisplay(display); + + EGLint configRedSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize); + + EGLint configGreenSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize); + + EGLint configBlueSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize); + + EGLint configAlphaSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize); + + eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue); + int configId = eglValue; + + // See if EGL provided a valid VisualID: + eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue); + visualId = (VisualID)eglValue; + if (visualId) { + // EGL has suggested a visual id, so get the rest of the visual info for that id: + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = visualId; + + XVisualInfo *chosenVisualInfo; + int matchingCount = 0; + chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount); + if (chosenVisualInfo) { + // Skip size checks if implementation supports non-matching visual + // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). + if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) { + XFree(chosenVisualInfo); + return visualId; + } + + int visualRedSize = countBits(chosenVisualInfo->red_mask); + int visualGreenSize = countBits(chosenVisualInfo->green_mask); + int visualBlueSize = countBits(chosenVisualInfo->blue_mask); + int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size + + bool visualMatchesConfig = false; + if ( visualRedSize == configRedSize && + visualGreenSize == configGreenSize && + visualBlueSize == configBlueSize ) + { + // We need XRender to check the alpha channel size of the visual. If we don't have + // the alpha size, we don't check it against the EGL config's alpha size. + if (visualAlphaSize >= 0) + visualMatchesConfig = visualAlphaSize == configAlphaSize; + else + visualMatchesConfig = true; + } + + if (!visualMatchesConfig) { + if (visualAlphaSize >= 0) { + qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", + (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, + configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); + } else { + qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", + (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, + configId, configRedSize, configGreenSize, configBlueSize); + } + visualId = 0; + } + } else { + qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", + (int)visualId, configId); + visualId = 0; + } + XFree(chosenVisualInfo); + } +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + else + qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); +#endif + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + if (configAlphaSize > 0) + qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); + else + qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); +#endif + return visualId; + } + + // Finally, try to + // use XGetVisualInfo and only use the bit depths to match on: + if (!visualId) { + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + XVisualInfo *matchingVisuals; + int matchingCount = 0; + + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + if (!matchingVisuals) { + // Try again without taking the alpha channel into account: + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + } + + if (matchingVisuals) { + visualId = matchingVisuals[0].visualid; + XFree(matchingVisuals); + } + } + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); +#endif + return visualId; + } + + qWarning("Unable to find an X11 visual which matches EGL config %d", configId); + return (VisualID)0; +} diff --git a/src/plugins/platforms/testlite/qtestliteeglintegration.h b/src/plugins/platforms/testlite/qtestliteeglintegration.h new file mode 100644 index 0000000..3717976 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteeglintegration.h @@ -0,0 +1,13 @@ +#ifndef QTESTLITEEGLINTEGRATION_H +#define QTESTLITEEGLINTEGRATION_H + +#include "qtestlitestaticinfo.h" +#include "../eglconvenience/qeglconvenience.h" + +class QTestLiteEglIntegration +{ +public: + static VisualID getCompatibleVisualId(Display *display, EGLConfig config); +}; + +#endif // QTESTLITEEGLINTEGRATION_H diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp index 5dbe1e7..9b641d1 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -52,6 +52,8 @@ #if !defined(QT_NO_OPENGL) #if !defined(QT_OPENGL_ES_2) #include <GL/glx.h> +#else +#include <EGL/egl.h> #endif //!defined(QT_OPENGL_ES_2) #include <private/qwindowsurface_gl_p.h> #include <private/qpixmapdata_gl_p.h> @@ -59,7 +61,6 @@ QT_BEGIN_NAMESPACE - QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) : mUseOpenGL(useOpenGL) , mFontDb(new QGenericUnixFontDatabase()) @@ -130,9 +131,23 @@ QPlatformClipboard * QTestLiteIntegration::clipboard() const bool QTestLiteIntegration::hasOpenGL() const { -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) QTestLiteScreen *screen = static_cast<const QTestLiteScreen *>(mScreens.at(0)); return glXQueryExtension(screen->display(), 0, 0) != 0; +#else + static bool eglHasbeenInitialized = false; + static bool wasEglInitialized = false; + if (!eglHasbeenInitialized) { + eglHasbeenInitialized = true; + QTestLiteScreen *screen = static_cast<const QTestLiteScreen *>(mScreens.at(0)); + EGLint major, minor; + eglBindAPI(EGL_OPENGL_ES_API); + EGLDisplay disp = eglGetDisplay(screen->display()); + wasEglInitialized = eglInitialize(disp,&major,&minor); + } + return wasEglInitialized; +#endif #endif return false; } diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp index 18fab4a..d9c69e3 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -54,9 +54,15 @@ #include <QtGui/private/qwindowsurface_p.h> #include <QtGui/private/qapplication_p.h> -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) #include "qglxintegration.h" -#endif +#else +#include "../eglconvenience/qeglconvenience.h" +#include "../eglconvenience/qeglplatformcontext.h" +#include "qtestliteeglintegration.h" +#endif //QT_OPENGL_ES_2 +#endif //QT_NO_OPENGL //#define MYX11_DEBUG @@ -74,16 +80,36 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) + #if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); - Colormap cmap = XCreateColormap(mScreen->display(),mScreen->rootWindow(),visualInfo->visual,AllocNone); - - XSetWindowAttributes a; - a.colormap = cmap; - x_window = XCreateWindow(mScreen->display(), mScreen->rootWindow(),x, y, w, h, - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); -#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +#else + QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat()); + + EGLDisplay eglDisplay = eglGetDisplay(mScreen->display()); + EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat); + VisualID id = QTestLiteEglIntegration::getCompatibleVisualId(mScreen->display(),eglConfig); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = id; + + XVisualInfo *visualInfo; + int matchingCount = 0; + visualInfo = XGetVisualInfo(mScreen->display(), VisualIDMask, &visualInfoTemplate, &matchingCount); +#endif //!defined(QT_OPENGL_ES_2) + if (visualInfo) { + Colormap cmap = XCreateColormap(mScreen->display(),mScreen->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + x_window = XCreateWindow(mScreen->display(), mScreen->rootWindow(),x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + } else { + qFatal("no window!"); + } +#endif //!defined(QT_NO_OPENGL) } else { x_window = XCreateSimpleWindow(mScreen->display(), mScreen->rootWindow(), x, y, w, h, 0 /*border_width*/, @@ -93,12 +119,6 @@ QTestLiteWindow::QTestLiteWindow(QWidget *window) #ifdef MYX11_DEBUG qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; #endif -// } - -// width = -1; -// height = -1; -// xpos = -1; -// ypos = -1; XSetWindowBackgroundPixmap(mScreen->display(), x_window, XNone); @@ -548,8 +568,23 @@ QPlatformGLContext *QTestLiteWindow::glContext() const return 0; if (!mGLContext) { QTestLiteWindow *that = const_cast<QTestLiteWindow *>(this); -#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat()); +#else + EGLDisplay display = eglGetDisplay(mScreen->display()); + + QPlatformWindowFormat windowFormat = correctColorBuffers(widget()->platformWindowFormat()); + + EGLConfig config = q_configFromQPlatformWindowFormat(display,windowFormat); + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)x_window,0); + that->mGLContext = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API); +#endif #endif } return mGLContext; @@ -584,4 +619,27 @@ void QTestLiteWindow::doSizeHints() XSetWMNormalHints(mScreen->display(), x_window, &s); } +QPlatformWindowFormat QTestLiteWindow::correctColorBuffers(const QPlatformWindowFormat &platformWindowFormat) const +{ + // I have only tested this setup on a dodgy intel setup, where I didn't use standard libs, + // so this might be not what we want to do :) + if ( !(platformWindowFormat.redBufferSize() == -1 && + platformWindowFormat.greenBufferSize() == -1 && + platformWindowFormat.blueBufferSize() == -1)) + return platformWindowFormat; + + QPlatformWindowFormat windowFormat = platformWindowFormat; + if (mScreen->depth() == 16) { + windowFormat.setRedBufferSize(5); + windowFormat.setGreenBufferSize(6); + windowFormat.setBlueBufferSize(5); + } else { + windowFormat.setRedBufferSize(8); + windowFormat.setGreenBufferSize(8); + windowFormat.setBlueBufferSize(8); + } + + return windowFormat; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h index 4b952dc..e45c3fd 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -129,6 +129,8 @@ protected: void doSizeHints(); private: + QPlatformWindowFormat correctColorBuffers(const QPlatformWindowFormat &windowFormat)const; + Window x_window; GC gc; diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro index eb196c3..7fb3304 100644 --- a/src/plugins/platforms/testlite/testlite.pro +++ b/src/plugins/platforms/testlite/testlite.pro @@ -9,22 +9,22 @@ SOURCES = \ qtestlitewindowsurface.cpp \ qtestlitewindow.cpp \ qtestlitecursor.cpp \ - qtestlitescreen.cpp \ - qtestlitekeyboard.cpp \ - qtestliteclipboard.cpp \ - qtestlitemime.cpp \ - qtestlitestaticinfo.cpp + qtestlitescreen.cpp \ + qtestlitekeyboard.cpp \ + qtestliteclipboard.cpp \ + qtestlitemime.cpp \ + qtestlitestaticinfo.cpp HEADERS = \ qtestliteintegration.h \ qtestlitewindowsurface.h \ qtestlitewindow.h \ qtestlitecursor.h \ - qtestlitescreen.h \ - qtestlitekeyboard.h \ - qtestliteclipboard.h \ - qtestlitemime.h \ - qtestlitestaticinfo.h + qtestlitescreen.h \ + qtestlitekeyboard.h \ + qtestliteclipboard.h \ + qtestlitemime.h \ + qtestlitestaticinfo.h LIBS += -lX11 -lXext @@ -36,8 +36,21 @@ include (../fontdatabases/genericunix/genericunix.pri) contains(QT_CONFIG, opengl) { QT += opengl - HEADERS += qglxintegration.h - SOURCES += qglxintegration.cpp + !contains(QT_CONFIG, opengles2) { + HEADERS += qglxintegration.h + SOURCES += qglxintegration.cpp + } else { # There is no easy way to detect if we'r suppose to use glx or not + HEADERS += \ + ../eglconvenience/qeglplatformcontext.h \ + ../eglconvenience/qeglconvenience.h \ + qtestliteeglintegration.h + + SOURCES += \ + ../eglconvenience/qeglplatformcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + qtestliteeglintegration.cpp + LIBS += -lEGL + } } target.path += $$[QT_INSTALL_PLUGINS]/platforms -- cgit v0.12 From e24d7c9cab4a50fe682478d43ac74e867666d48b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@nokia.com> Date: Thu, 6 Jan 2011 10:30:18 +0100 Subject: Lighthouse: Support external plugins. Add -platformpluginpath command line option that spesifies an additional directory to scan for plugins. Also read QT_QPA_PLATFORM_PLUGIN_PATH. QlatformIntegrationFacgtory::create() now tries to load the plugin from the external path first. Similarly, keys() returns the keys from the extra path in addition to the "internal" keys API changes: QPlatformIntegration::create() and keys() now take an optional const QString &platformPluginPath. New file: externalplugin.pri, contains instructions and a base setup for building external plugins. --- src/gui/kernel/qapplication_qpa.cpp | 12 ++++++--- src/gui/kernel/qplatformintegrationfactory_qpa.cpp | 27 +++++++++++++++++--- src/gui/kernel/qplatformintegrationfactory_qpa_p.h | 4 +-- src/plugins/platforms/externalplugin.pri | 29 ++++++++++++++++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 src/plugins/platforms/externalplugin.pri diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index a164c2d..fdbb931 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -444,11 +444,11 @@ void QApplication::alert(QWidget *, int) { } -static void init_platform(const QString &name) +static void init_platform(const QString &name, const QString &platformPluginPath) { - QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name); + QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, platformPluginPath); if (!QApplicationPrivate::platform_integration) { - QStringList keys = QPlatformIntegrationFactory::keys(); + QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath); QString fatalMessage = QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name); foreach(QString key, keys) { @@ -513,6 +513,7 @@ void qt_init(QApplicationPrivate *priv, int type) } QList<QByteArray> pluginList; + QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH")); QString platformName = QLatin1String(qgetenv("QT_QPA_PLATFORM")); // Get command line params @@ -527,6 +528,9 @@ void qt_init(QApplicationPrivate *priv, int type) if (arg == "-fn" || arg == "-font") { if (++i < argc) appFont = QString::fromLocal8Bit(argv[i]); + } else if (arg == "-platformpluginpath") { + if (++i < argc) + platformPluginPath = QLatin1String(argv[i]); } else if (arg == "-platform") { if (++i < argc) platformName = QLatin1String(argv[i]); @@ -550,7 +554,7 @@ void qt_init(QApplicationPrivate *priv, int type) } #endif - init_platform(platformName); + init_platform(platformName, platformPluginPath); init_plugins(pluginList); QColormap::initialize(); diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp index 9122e1a..17a130d 100644 --- a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp +++ b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp @@ -52,15 +52,27 @@ QT_BEGIN_NAMESPACE #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QPlatformIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) #endif -QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key) +QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key, const QString &platformPluginPath) { QPlatformIntegration *ret = 0; QStringList paramList = key.split(QLatin1Char(':')); QString platform = paramList.takeFirst().toLower(); #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + // Try loading the plugin from platformPluginPath first: + if (!platformPluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(platformPluginPath); + if (QPlatformIntegrationFactoryInterface *factory = + qobject_cast<QPlatformIntegrationFactoryInterface*>(directLoader()->instance(platform))) + ret = factory->create(key, paramList); + + if (ret) + return ret; + } if (QPlatformIntegrationFactoryInterface *factory = qobject_cast<QPlatformIntegrationFactoryInterface*>(loader()->instance(platform))) ret = factory->create(platform, paramList); #endif @@ -74,10 +86,19 @@ QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key) \sa create() */ -QStringList QPlatformIntegrationFactory::keys() +QStringList QPlatformIntegrationFactory::keys(const QString &platformPluginPath) { #if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - QStringList list = loader()->keys(); + QStringList list; + + if (!platformPluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(platformPluginPath); + foreach (const QString &key, directLoader()->keys()) { + list += key + QString(QLatin1String(" (from %1)")).arg(platformPluginPath); + } + } + + list += loader()->keys(); #else QStringList list; #endif diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa_p.h b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h index ba02d2c..77e1da1 100644 --- a/src/gui/kernel/qplatformintegrationfactory_qpa_p.h +++ b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h @@ -66,8 +66,8 @@ class QPlatformIntegration; class QPlatformIntegrationFactory { public: - static QStringList keys(); - static QPlatformIntegration *create(const QString&); + static QStringList keys(const QString &platformPluginPath = QString()); + static QPlatformIntegration *create(const QString &key, const QString &platformPluginPath = QString()); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/externalplugin.pri b/src/plugins/platforms/externalplugin.pri new file mode 100644 index 0000000..54da4d9 --- /dev/null +++ b/src/plugins/platforms/externalplugin.pri @@ -0,0 +1,29 @@ +# +# Lighthouse now has preliminarily support for building and +# loading platform plugins from outside the Qt source/build +# tree. +# +# 1) Building external plugins: +# Set QTDIR to the Qt build directory, copy this file to +# the plugin source repository and include it at the top +# of the plugin's pro file. Use QT_SOURCE_TREE if you +# want to pull in source code from Qt: +# +# include($$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri) +# +# 2) Loading external plugins: +# Specify the path to the directory containing the +# plugin on the command line, in addition to the +# platform name. +# +# ./wiggly -platformPluginPath /path/to/myPlugin -platform gullfaksA +# + +!exists($$(QTDIR)/.qmake.cache) { + error("Please set QTDIR to the Qt build directory") +} + +QT_SOURCE_TREE = $$fromfile($$(QTDIR)/.qmake.cache,QT_SOURCE_TREE) +QT_BUILD_TREE = $$fromfile($$(QTDIR)/.qmake.cache,QT_BUILD_TREE) + +include($$QT_SOURCE_TREE/src/plugins/qpluginbase.pri) -- cgit v0.12 From 30080bdcb226a5a815465299bcb0dbb6a347cb1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Fri, 7 Jan 2011 12:12:35 +0100 Subject: Lighthouse: Fix keyboard modifier handling QApplication allready knows the modifiers --- src/gui/kernel/qapplication_qpa.cpp | 8 +++--- .../platforms/testlite/qtestlitekeyboard.cpp | 29 ++++++++++++++-------- src/plugins/platforms/testlite/qtestlitekeyboard.h | 1 + 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp index fdbb931..cd76adf 100644 --- a/src/gui/kernel/qapplication_qpa.cpp +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -79,7 +79,6 @@ int qt_last_x = 0; int qt_last_y = 0; QPointer<QWidget> qt_last_mouse_receiver = 0; -static Qt::KeyboardModifiers modifiers = Qt::NoModifier; static Qt::MouseButtons buttons = Qt::NoButton; static ulong mousePressTime; static Qt::MouseButton mousePressButton = Qt::NoButton; @@ -731,7 +730,7 @@ void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mouse // qDebug() << "sending mouse ev." << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber; - QMouseEvent ev(type, localPoint, globalPoint, button, buttons, modifiers); + QMouseEvent ev(type, localPoint, globalPoint, button, buttons, QApplication::keyboardModifiers()); QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances(); foreach (QWeakPointer<QPlatformCursor> cursor, cursors) { @@ -744,7 +743,7 @@ void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mouse #ifndef QT_NO_CONTEXTMENU if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { - QContextMenuEvent e(QContextMenuEvent::Mouse, localPoint, globalPoint, modifiers); + QContextMenuEvent e(QContextMenuEvent::Mouse, localPoint, globalPoint, QApplication::keyboardModifiers()); QApplication::sendSpontaneousEvent(mouseWidget, &e); } #endif // QT_NO_CONTEXTMENU @@ -786,7 +785,7 @@ void QApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wheel p = mouseWidget->mapFromGlobal(globalPoint); } - QWheelEvent ev(p, globalPoint, e->delta, buttons, modifiers, + QWheelEvent ev(p, globalPoint, e->delta, buttons, QApplication::keyboardModifiers(), e->orient); QApplication::sendSpontaneousEvent(mouseWidget, &ev); } @@ -817,7 +816,6 @@ void QApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEven if (app_do_modal && !qt_try_modal(focusW, e->keyType)) return; - modifiers = e->modifiers; QKeyEvent ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount); QApplication::sendSpontaneousEvent(focusW, &ev); } diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp index 93d21b3..ca4c203 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -1,5 +1,7 @@ #include "qtestlitekeyboard.h" +#include <QDebug> + #include "qtestlitescreen.h" #include <QtGui/QWindowSystemInterface> @@ -710,8 +712,8 @@ Qt::KeyboardModifiers QTestLiteKeyboard::translateModifiers(int s) ret |= Qt::AltModifier; if (s & m_meta_mask) ret |= Qt::MetaModifier; - if (s & m_mode_switch_mask) - ret |= Qt::GroupSwitchModifier; +// if (s & m_mode_switch_mask) //doesn't seem to work correctly +// ret |= Qt::GroupSwitchModifier; return ret; } @@ -947,14 +949,21 @@ static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) void QTestLiteKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev) { - int qtcode = 0; - Qt::KeyboardModifiers modifiers = translateModifiers(ev->state); + const int xkeycode = ev->keycode; + const uint xmodifiers = ev->state; + + KeySym baseKeySym; + uint consumedModifiers; + if (!XkbLookupKeySym(m_screen->display(), xkeycode, (xmodifiers & (LockMask | m_num_lock_mask)), + &consumedModifiers, &baseKeySym)) + return; + + Qt::KeyboardModifiers baseModifiers = 0; + int baseCode = -1; QByteArray chars; - chars.resize(513); int count = 0; - KeySym keySym; - count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); - QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); - modifiers ^= modifierFromKeyCode(qtcode); - QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text.left(count)); + QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count); + + QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,baseCode,baseModifiers,text.left(count)); + } diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.h b/src/plugins/platforms/testlite/qtestlitekeyboard.h index 65ead16..4e9d98d 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.h +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.h @@ -14,6 +14,7 @@ public: Qt::KeyboardModifiers translateModifiers(int s); + enum { MaxBits = sizeof(uint) * 8 }; private: void setMask(KeySym sym, uint mask); -- cgit v0.12 From 2bc7d2af6be2b09c38e989f339ec2ee33cc204eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Fri, 7 Jan 2011 17:38:59 +0100 Subject: Lighthouse: Fix keyboard on testlite Remove code which was wrong --- .../platforms/testlite/qtestlitekeyboard.cpp | 24 +++++++--------------- src/plugins/platforms/testlite/qtestlitekeyboard.h | 1 - 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp index ca4c203..72e6d50 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -1,7 +1,5 @@ #include "qtestlitekeyboard.h" -#include <QDebug> - #include "qtestlitescreen.h" #include <QtGui/QWindowSystemInterface> @@ -949,21 +947,13 @@ static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) void QTestLiteKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev) { - const int xkeycode = ev->keycode; - const uint xmodifiers = ev->state; - - KeySym baseKeySym; - uint consumedModifiers; - if (!XkbLookupKeySym(m_screen->display(), xkeycode, (xmodifiers & (LockMask | m_num_lock_mask)), - &consumedModifiers, &baseKeySym)) - return; - - Qt::KeyboardModifiers baseModifiers = 0; - int baseCode = -1; + int qtcode = 0; + Qt::KeyboardModifiers modifiers = translateModifiers(ev->state); QByteArray chars; + chars.resize(513); int count = 0; - QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count); - - QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,baseCode,baseModifiers,text.left(count)); - + KeySym keySym; + count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); + QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); + QWindowSystemInterface::handleKeyEvent(widget,ev->time,type,qtcode,modifiers,text.left(count)); } diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.h b/src/plugins/platforms/testlite/qtestlitekeyboard.h index 4e9d98d..65ead16 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.h +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.h @@ -14,7 +14,6 @@ public: Qt::KeyboardModifiers translateModifiers(int s); - enum { MaxBits = sizeof(uint) * 8 }; private: void setMask(KeySym sym, uint mask); -- cgit v0.12 From 18ced2568f524ff38ebf610125ca9611e787abe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= <morten.sorvig@nokia.com> Date: Fri, 14 Jan 2011 10:28:37 +0100 Subject: Configure: allow -no-framework for lighthouse. (configure has trouble separating host and target platforms.) --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index e8a5662..e3c0882 100755 --- a/configure +++ b/configure @@ -1525,7 +1525,7 @@ while [ "$#" -gt 0 ]; do ;; framework) - if [ "$PLATFORM_MAC" = "yes" ]; then + if [ "$PLATFORM_MAC" = "yes" ] || [ "$PLATFORM_QPA" = "yes" ]; then CFG_FRAMEWORK="$VAL" else UNKNOWN_OPT=yes -- cgit v0.12 From 04ad0434596714ff91f5fce66267c34e82654bd5 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete <paul.tvete@nokia.com> Date: Tue, 18 Jan 2011 12:42:36 +0100 Subject: Add Qt::Key_ScreenSaver --- src/gui/embedded/qkbd_defaultmap_qws_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h index 703dfcd..2f8eb37 100644 --- a/src/gui/embedded/qkbd_defaultmap_qws_p.h +++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h @@ -649,6 +649,7 @@ const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = { { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 }, { 138, 0xffff, 0x01000058, 0x00, 0x00, 0x0000 }, { 139, 0xffff, 0x01000055, 0x00, 0x00, 0x0000 }, + { 152, 0xffff, 0x010000ba, 0x00, 0x00, 0x0000 }, }; -- cgit v0.12 From 6c5ea196ff086b92687033208f15e36591dc70f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Wed, 6 Oct 2010 21:51:23 -0400 Subject: Add wayland lighthouse plugin --- config.tests/qpa/wayland/wayland.cpp | 7 + config.tests/qpa/wayland/wayland.pro | 6 + configure | 5 + src/plugins/platforms/platforms.pro | 4 + src/plugins/platforms/wayland/main.cpp | 72 ++++ .../platforms/wayland/qwaylandintegration.cpp | 399 +++++++++++++++++++++ .../platforms/wayland/qwaylandintegration.h | 156 ++++++++ .../platforms/wayland/qwaylandwindowsurface.cpp | 131 +++++++ .../platforms/wayland/qwaylandwindowsurface.h | 71 ++++ src/plugins/platforms/wayland/wayland.pro | 19 + 10 files changed, 870 insertions(+) create mode 100644 config.tests/qpa/wayland/wayland.cpp create mode 100644 config.tests/qpa/wayland/wayland.pro create mode 100644 src/plugins/platforms/wayland/main.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandintegration.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandintegration.h create mode 100644 src/plugins/platforms/wayland/qwaylandwindowsurface.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandwindowsurface.h create mode 100644 src/plugins/platforms/wayland/wayland.pro diff --git a/config.tests/qpa/wayland/wayland.cpp b/config.tests/qpa/wayland/wayland.cpp new file mode 100644 index 0000000..40ff2cb --- /dev/null +++ b/config.tests/qpa/wayland/wayland.cpp @@ -0,0 +1,7 @@ +#include "wayland-client.h" +#include "wayland-glib.h" + +int main(int, char **) +{ + return 0; +} diff --git a/config.tests/qpa/wayland/wayland.pro b/config.tests/qpa/wayland/wayland.pro new file mode 100644 index 0000000..83f5efe --- /dev/null +++ b/config.tests/qpa/wayland/wayland.pro @@ -0,0 +1,6 @@ +SOURCES = client.cpp +CONFIG -= qt + +QMAKE_CXXFLAGS += $$QT_CFLAGS_WAYLAND +LIBS += $$QT_LIBS_WAYLAND -lfreetype -lfontconfig -lwayland-client + diff --git a/configure b/configure index e3c0882..e1c41ec 100755 --- a/configure +++ b/configure @@ -6185,6 +6185,11 @@ if [ "$PLATFORM_QPA" = "yes" ]; then QMakeVar set QMAKE_LIBS_FONTCONFIG "$QT_LIBS_FONTCONFIG" CFG_LIBFREETYPE=system fi + + if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/qpa/wayland "Wayland" $L_FLAGS $I_FLAGS $l_FLAGS; then + QT_CONFIG="$QT_CONFIG wayland" + fi + fi if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/mac/coreservices "CoreServices" $L_FLAGS $I_FLAGS $l_FLAGS $MAC_CONFIG_TEST_COMMANDLINE; then diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 26ccd44..57015e7 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,3 +2,7 @@ TEMPLATE = subdirs SUBDIRS += minimal +contains(QT_CONFIG, wayland) { + SUBDIRS += wayland +} + diff --git a/src/plugins/platforms/wayland/main.cpp b/src/plugins/platforms/wayland/main.cpp new file mode 100644 index 0000000..056cc64 --- /dev/null +++ b/src/plugins/platforms/wayland/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qwaylandintegration.h" + +QT_BEGIN_NAMESPACE + +class QWaylandIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWaylandIntegrationPlugin::keys() const +{ + QStringList list; + list << "Wayland"; + return list; +} + +QPlatformIntegration *QWaylandIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "wayland") + return new QWaylandIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(wayland, QWaylandIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp new file mode 100644 index 0000000..577dd28 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -0,0 +1,399 @@ +#include <QWindowSystemInterface> +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" +#include "qfontconfigdatabase.h" + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <unistd.h> +#include <fcntl.h> + +extern "C" { +#include <xf86drm.h> +} + +struct wl_surface *QWaylandDisplay::createSurface() +{ + return wl_compositor_create_surface(mCompositor); +} + +struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); +} + +struct wl_visual *QWaylandDisplay::argbVisual() +{ + return wl_display_get_argb_visual(mDisplay); +} + +void QWaylandDisplay::drmHandleDevice(void *data, + struct wl_drm *drm, const char *device) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + qwd->mDeviceName = strdup(device); +} + +void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + qwd->mAuthenticated = true; +} + +const struct wl_drm_listener QWaylandDisplay::drmListener = { + QWaylandDisplay::drmHandleDevice, + QWaylandDisplay::drmHandleAuthenticated +}; + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t width, int32_t height) +{ + Q_UNUSED(output); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + QWaylandScreen *screen; + + screen = new QWaylandScreen(); + screen->mGeometry = QRect(0, 0, width, height); + screen->mDepth = 32; + screen->mFormat = QImage::Format_ARGB32; + screen->mOutput = output; + + qwd->mScreens.append(screen); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + struct wl_surface *mPointerFocus; + struct wl_surface *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, + uint32_t id) + : mDisplay(display) + , mInputDevice(wl_input_device_create(display, id)) + , mPointerFocus(NULL) + , mKeyboardFocus(NULL) + , mButtons(0) +{ + wl_input_device_add_listener(mInputDevice, + &inputDeviceListener, + this); + wl_input_device_set_user_data(mInputDevice, this); +} + +void QWaylandInputDevice::inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t surface_x, int32_t surface_y) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + + inputDevice->mSurfacePos = QPoint(surface_x, surface_y); + inputDevice->mGlobalPos = QPoint(x, y); + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + Qt::MouseButton qt_button; + + switch (button) { + case 272: + qt_button = Qt::LeftButton; + break; + case 273: + qt_button = Qt::RightButton; + break; + case 274: + qt_button = Qt::MidButton; + break; + default: + return; + } + + if (state) + inputDevice->mButtons |= qt_button; + else + inputDevice->mButtons &= ~qt_button; + + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ +} + +void QWaylandInputDevice::inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mPointerFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mPointerFocus); + QWindowSystemInterface::handleLeaveEvent(window->widget()); + inputDevice->mPointerFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + QWindowSystemInterface::handleEnterEvent(window->widget()); + inputDevice->mPointerFocus = surface; + } +} + +void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mKeyboardFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mKeyboardFocus); + inputDevice->mKeyboardFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + inputDevice->mKeyboardFocus = surface; + } +} + +const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { + QWaylandInputDevice::inputHandleMotion, + QWaylandInputDevice::inputHandleButton, + QWaylandInputDevice::inputHandleKey, + QWaylandInputDevice::inputHandlePointerFocus, + QWaylandInputDevice::inputHandleKeyboardFocus, +}; + +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data) +{ + Q_UNUSED(version); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + if (strcmp(interface, "compositor") == 0) { + qwd->mCompositor = wl_compositor_create(display, id); + } else if (strcmp(interface, "drm") == 0) { + qwd->mDrm = wl_drm_create(display, id); + wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); + } else if (strcmp(interface, "shm") == 0) { + qwd->mShm = wl_shm_create(display, id); + } else if (strcmp(interface, "output") == 0) { + struct wl_output *output = wl_output_create(display, id); + wl_output_add_listener(output, &outputListener, qwd); + } else if (strcmp(interface, "input_device") == 0) { + QWaylandInputDevice *inputDevice = new QWaylandInputDevice(display, id); + qwd->mInputDevices.append(inputDevice); + } +} + +static void initial_roundtrip(void *data) +{ + bool *done = (bool *) data; + + *done = true; +} + +static const char socket_name[] = "\0wayland"; + +void QWaylandDisplay::eventDispatcher(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int +QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + /* FIXME: We get a callback here when we ask wl_display for the + * fd, but at that point we don't have the socket notifier as we + * need the fd to create that. We'll probably need to split that + * API into get_fd and set_update_func functions. */ + if (qwd->mWriteNotifier == NULL) + return 0; + + qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); + + return 0; +} + +void QWaylandDisplay::flushRequests(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +QWaylandDisplay::QWaylandDisplay(void) + : mWriteNotifier(0) +{ + drm_magic_t magic; + bool done; + + mDisplay = wl_display_create(socket_name, sizeof socket_name); + if (mDisplay == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return; + } + + wl_display_add_global_listener(mDisplay, + QWaylandDisplay::displayHandleGlobal, this); + + /* Process connection events. */ + wl_display_sync_callback(mDisplay, initial_roundtrip, &done); + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + + mFd = open(mDeviceName, O_RDWR); + if (mFd < 0) { + qWarning("drm open failed: %m\n"); + return; + } + + if (drmGetMagic(mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + /* Wait for authenticated event */ + wl_drm_authenticate(mDrm, magic); + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); + while (!mAuthenticated) + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + + int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); + mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(mReadNotifier, + SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(mWriteNotifier, + SIGNAL(activated(int)), this, SLOT(flushRequests())); + mWriteNotifier->setEnabled(false); +} + +QWaylandDisplay::~QWaylandDisplay(void) +{ + close(mFd); + wl_display_destroy(mDisplay); +} + +QWaylandIntegration::QWaylandIntegration() + : mFontDb(new QFontconfigDatabase()) + , mDisplay(new QWaylandDisplay()) +{ +} + +QList<QPlatformScreen *> +QWaylandIntegration::screens() const +{ + return mDisplay->screens(); +} + +QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) + : QPlatformWindow(window) + , mDisplay(display) +{ + mSurface = mDisplay->createSurface(); + wl_surface_set_user_data(mSurface, this); +} + +QWaylandWindow::~QWaylandWindow() +{ + /* mDisplay->destroySurface() */ +} + +QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QWaylandWindow(widget, mDisplay); +} + +QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QWaylandWindowSurface(widget, mDisplay); +} + +QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const +{ + return mFontDb; +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h new file mode 100644 index 0000000..d777175 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_WAYLAND_H +#define QPLATFORMINTEGRATION_WAYLAND_H + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> + +QT_BEGIN_NAMESPACE + +class QWaylandInputDevice; + +class QWaylandDisplay : public QObject { + Q_OBJECT; + +public: + QWaylandDisplay(void); + ~QWaylandDisplay(void); + + QList<QPlatformScreen *> screens() const { return mScreens; } + struct wl_surface *createSurface(); + struct wl_buffer *createShmBuffer(int fd, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *argbVisual(); + +public slots: + void eventDispatcher(void); + void flushRequests(void); + +private: + struct wl_display *mDisplay; + struct wl_compositor *mCompositor; + struct wl_drm *mDrm; + struct wl_shm *mShm; + char *mDeviceName; + int mFd; + bool mAuthenticated; + QList<QPlatformScreen *> mScreens; + QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + QSocketNotifier *mWriteNotifier; + + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + + static void drmHandleDevice(void *data, + struct wl_drm *drm, const char *device); + static void drmHandleAuthenticated(void *data, struct wl_drm *drm); + + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t width, int32_t height); + + static int sourceUpdate(uint32_t mask, void *data); + + static const struct wl_drm_listener drmListener; + static const struct wl_output_listener outputListener; +}; + +class QWaylandScreen : public QPlatformScreen +{ +public: + QWaylandScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + struct wl_output *mOutput; +}; + + +class QWaylandWindow : public QPlatformWindow +{ +public: + QWaylandWindow(QWidget *window, QWaylandDisplay *display); + ~QWaylandWindow(); + struct wl_surface *surface() { return mSurface; } + +private: + struct wl_surface *mSurface; + QWaylandDisplay *mDisplay; +}; + +class QWaylandIntegration : public QPlatformIntegration +{ +public: + QWaylandIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp new file mode 100644 index 0000000..f0f5018 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +QWaylandWindowSurface::QWaylandWindowSurface(QWidget *window, + QWaylandDisplay *display) + : QWindowSurface(window) + , mImage(0) + , mDisplay(display) +{ + //qDebug() << "QWaylandWindowSurface::QWaylandWindowSurface:" << (long)this; +} + +QWaylandWindowSurface::~QWaylandWindowSurface() +{ +} + +QPaintDevice *QWaylandWindowSurface::paintDevice() +{ + //qDebug() << "QWaylandWindowSurface::paintDevice"; + return mImage; +} + +void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; + + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } +} + +void QWaylandWindowSurface::resize(const QSize &size) +{ + //qDebug() << "QWaylandWindowSurface::setGeometry:" << (long)this << rect; + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mImage != NULL && mImage->size() == size) + return; + + if (mImage != NULL) { + delete mImage; + munmap(mData, mSize); + } + + mStride = size.width() * 4; + mSize = mStride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, mSize) < 0) + qWarning("ftruncate failed: %s", strerror(errno)); + mData = (uchar *) + mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (mData == (uchar *) MAP_FAILED) + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + + mImage = new QImage(mData, size.width(), size.height(), mStride, format); + + struct wl_buffer *buffer = + mDisplay->createShmBuffer(fd, size.width(), size.height(), + mStride, mDisplay->argbVisual()); + wl_surface_attach(ww->surface(), buffer); + wl_surface_map(ww->surface(), 0, 0, size.width(), size.height()); + wl_buffer_destroy(buffer); + close(fd); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h new file mode 100644 index 0000000..1054c51 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_WAYLAND_H +#define QWINDOWSURFACE_WAYLAND_H + +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QWaylandWindowSurface : public QWindowSurface +{ +public: + QWaylandWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QImage *mImage; + uchar *mData; + int mSize; + int mStride; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro new file mode 100644 index 0000000..62ff4df --- /dev/null +++ b/src/plugins/platforms/wayland/wayland.pro @@ -0,0 +1,19 @@ +TARGET = qwayland +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qwaylandintegration.cpp \ + qwaylandwindowsurface.cpp + +HEADERS = qwaylandintegration.h \ + qwaylandwindowsurface.h + +INCLUDEPATH += /usr/include/libdrm +LIBS += -lwayland-client -ldrm + +include (../fontdatabases/fontconfig/fontconfig.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target -- cgit v0.12 From 3c2bb14b11f590f425281184ae6a1dadb98d6326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 7 Oct 2010 10:54:39 -0400 Subject: wayland: Split input device out to its own file --- .../platforms/wayland/qwaylandinputdevice.cpp | 178 +++++++++++++++++++++ .../platforms/wayland/qwaylandintegration.cpp | 164 +------------------ .../platforms/wayland/qwaylandintegration.h | 3 + src/plugins/platforms/wayland/wayland.pro | 3 +- 4 files changed, 185 insertions(+), 163 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandinputdevice.cpp diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp new file mode 100644 index 0000000..eeda105 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -0,0 +1,178 @@ +#include <QWindowSystemInterface> +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" +#include "qfontconfigdatabase.h" + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <unistd.h> +#include <fcntl.h> + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + struct wl_surface *mPointerFocus; + struct wl_surface *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, + uint32_t id) + : mDisplay(display) + , mInputDevice(wl_input_device_create(display, id)) + , mPointerFocus(NULL) + , mKeyboardFocus(NULL) + , mButtons(0) +{ + wl_input_device_add_listener(mInputDevice, + &inputDeviceListener, + this); + wl_input_device_set_user_data(mInputDevice, this); +} + +void QWaylandInputDevice::inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t surface_x, int32_t surface_y) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + + inputDevice->mSurfacePos = QPoint(surface_x, surface_y); + inputDevice->mGlobalPos = QPoint(x, y); + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = + (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + Qt::MouseButton qt_button; + + switch (button) { + case 272: + qt_button = Qt::LeftButton; + break; + case 273: + qt_button = Qt::RightButton; + break; + case 274: + qt_button = Qt::MidButton; + break; + default: + return; + } + + if (state) + inputDevice->mButtons |= qt_button; + else + inputDevice->mButtons &= ~qt_button; + + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ +} + +void QWaylandInputDevice::inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mPointerFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mPointerFocus); + QWindowSystemInterface::handleLeaveEvent(window->widget()); + inputDevice->mPointerFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + QWindowSystemInterface::handleEnterEvent(window->widget()); + inputDevice->mPointerFocus = surface; + } +} + +void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys) +{ + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mKeyboardFocus) { + window = (QWaylandWindow *) + wl_surface_get_user_data(inputDevice->mKeyboardFocus); + inputDevice->mKeyboardFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + inputDevice->mKeyboardFocus = surface; + } +} + +const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { + QWaylandInputDevice::inputHandleMotion, + QWaylandInputDevice::inputHandleButton, + QWaylandInputDevice::inputHandleKey, + QWaylandInputDevice::inputHandlePointerFocus, + QWaylandInputDevice::inputHandleKeyboardFocus, +}; + + +QWaylandInputDevice * +waylandInputDeviceCreate(struct wl_display *display, uint32_t id) +{ + return new QWaylandInputDevice(display, id); +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 577dd28..c93ff25 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -74,167 +74,6 @@ const struct wl_output_listener QWaylandDisplay::outputListener = { QWaylandDisplay::outputHandleGeometry }; -class QWaylandInputDevice { -public: - QWaylandInputDevice(struct wl_display *display, uint32_t id); - -private: - struct wl_display *mDisplay; - struct wl_input_device *mInputDevice; - struct wl_surface *mPointerFocus; - struct wl_surface *mKeyboardFocus; - static const struct wl_input_device_listener inputDeviceListener; - Qt::MouseButtons mButtons; - QPoint mSurfacePos; - QPoint mGlobalPos; - - static void inputHandleMotion(void *data, - struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy); - static void inputHandleButton(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state); - static void inputHandleKey(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state); - static void inputHandlePointerFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy); - static void inputHandleKeyboardFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys); -}; - -QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, - uint32_t id) - : mDisplay(display) - , mInputDevice(wl_input_device_create(display, id)) - , mPointerFocus(NULL) - , mKeyboardFocus(NULL) - , mButtons(0) -{ - wl_input_device_add_listener(mInputDevice, - &inputDeviceListener, - this); - wl_input_device_set_user_data(mInputDevice, this); -} - -void QWaylandInputDevice::inputHandleMotion(void *data, - struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, - int32_t surface_x, int32_t surface_y) -{ - QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window = - (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); - - inputDevice->mSurfacePos = QPoint(surface_x, surface_y); - inputDevice->mGlobalPos = QPoint(x, y); - QWindowSystemInterface::handleMouseEvent(window->widget(), - time, - inputDevice->mSurfacePos, - inputDevice->mGlobalPos, - inputDevice->mButtons); -} - -void QWaylandInputDevice::inputHandleButton(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state) -{ - QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window = - (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); - Qt::MouseButton qt_button; - - switch (button) { - case 272: - qt_button = Qt::LeftButton; - break; - case 273: - qt_button = Qt::RightButton; - break; - case 274: - qt_button = Qt::MidButton; - break; - default: - return; - } - - if (state) - inputDevice->mButtons |= qt_button; - else - inputDevice->mButtons &= ~qt_button; - - QWindowSystemInterface::handleMouseEvent(window->widget(), - time, - inputDevice->mSurfacePos, - inputDevice->mGlobalPos, - inputDevice->mButtons); -} - -void QWaylandInputDevice::inputHandleKey(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state) -{ -} - -void QWaylandInputDevice::inputHandlePointerFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy) -{ - QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window; - - if (inputDevice->mPointerFocus) { - window = (QWaylandWindow *) - wl_surface_get_user_data(inputDevice->mPointerFocus); - QWindowSystemInterface::handleLeaveEvent(window->widget()); - inputDevice->mPointerFocus = NULL; - } - - if (surface) { - window = (QWaylandWindow *) wl_surface_get_user_data(surface); - QWindowSystemInterface::handleEnterEvent(window->widget()); - inputDevice->mPointerFocus = surface; - } -} - -void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys) -{ - QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window; - - if (inputDevice->mKeyboardFocus) { - window = (QWaylandWindow *) - wl_surface_get_user_data(inputDevice->mKeyboardFocus); - inputDevice->mKeyboardFocus = NULL; - } - - if (surface) { - window = (QWaylandWindow *) wl_surface_get_user_data(surface); - inputDevice->mKeyboardFocus = surface; - } -} - -const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { - QWaylandInputDevice::inputHandleMotion, - QWaylandInputDevice::inputHandleButton, - QWaylandInputDevice::inputHandleKey, - QWaylandInputDevice::inputHandlePointerFocus, - QWaylandInputDevice::inputHandleKeyboardFocus, -}; - void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, uint32_t id, const char *interface, @@ -254,7 +93,8 @@ void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, struct wl_output *output = wl_output_create(display, id); wl_output_add_listener(output, &outputListener, qwd); } else if (strcmp(interface, "input_device") == 0) { - QWaylandInputDevice *inputDevice = new QWaylandInputDevice(display, id); + QWaylandInputDevice *inputDevice = + waylandInputDeviceCreate(display, id); qwd->mInputDevices.append(inputDevice); } } diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index d777175..20d890e 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -53,6 +53,9 @@ QT_BEGIN_NAMESPACE class QWaylandInputDevice; +QWaylandInputDevice * +waylandInputDeviceCreate(struct wl_display *display, uint32_t id); + class QWaylandDisplay : public QObject { Q_OBJECT; diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 62ff4df..c1f5bae 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -5,7 +5,8 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms SOURCES = main.cpp \ qwaylandintegration.cpp \ - qwaylandwindowsurface.cpp + qwaylandwindowsurface.cpp \ + qwaylandinputdevice.cpp HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h -- cgit v0.12 From 918baf0ce0132d7751751c3b1a6a5cae3eb566e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 7 Oct 2010 11:46:13 -0400 Subject: wayland: Create and destroy surface at show and hide --- .../platforms/wayland/qwaylandintegration.cpp | 19 ++++++++++++++++--- .../platforms/wayland/qwaylandintegration.h | 2 ++ .../platforms/wayland/qwaylandwindowsurface.cpp | 22 +++++++++++++++------- .../platforms/wayland/qwaylandwindowsurface.h | 2 ++ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index c93ff25..277e965 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -210,15 +210,28 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) : QPlatformWindow(window) + , mSurface(0) , mDisplay(display) { - mSurface = mDisplay->createSurface(); - wl_surface_set_user_data(mSurface, this); } QWaylandWindow::~QWaylandWindow() { - /* mDisplay->destroySurface() */ +} + +void QWaylandWindow::setVisible(bool visible) +{ + QWaylandWindowSurface *wws = + (QWaylandWindowSurface *) widget()->windowSurface(); + + if (visible) { + mSurface = mDisplay->createSurface(); + wl_surface_set_user_data(mSurface, this); + wws->attach(); + } else { + wl_surface_destroy(mSurface); + mSurface = NULL; + } } QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 20d890e..4e50f3c 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -131,6 +131,8 @@ public: ~QWaylandWindow(); struct wl_surface *surface() { return mSurface; } + void setVisible(bool visible); + private: struct wl_surface *mSurface; QWaylandDisplay *mDisplay; diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index f0f5018..41f72d0 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -87,10 +87,19 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const } } +void QWaylandWindowSurface::attach(void) +{ + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + + if (ww->surface()) { + wl_surface_attach(ww->surface(), mBuffer); + wl_surface_map(ww->surface(), 0, 0, mImage->width(), mImage->height()); + } +} + void QWaylandWindowSurface::resize(const QSize &size) { //qDebug() << "QWaylandWindowSurface::setGeometry:" << (long)this << rect; - QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); @@ -100,6 +109,7 @@ void QWaylandWindowSurface::resize(const QSize &size) if (mImage != NULL) { delete mImage; munmap(mData, mSize); + wl_buffer_destroy(mBuffer); } mStride = size.width() * 4; @@ -119,13 +129,11 @@ void QWaylandWindowSurface::resize(const QSize &size) mImage = new QImage(mData, size.width(), size.height(), mStride, format); - struct wl_buffer *buffer = - mDisplay->createShmBuffer(fd, size.width(), size.height(), - mStride, mDisplay->argbVisual()); - wl_surface_attach(ww->surface(), buffer); - wl_surface_map(ww->surface(), 0, 0, size.width(), size.height()); - wl_buffer_destroy(buffer); + mBuffer = mDisplay->createShmBuffer(fd, size.width(), size.height(), + mStride, mDisplay->argbVisual()); close(fd); + + attach(); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 1054c51..1da6ab4 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -57,6 +57,7 @@ public: QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size); + void attach(void); private: QImage *mImage; @@ -64,6 +65,7 @@ private: int mSize; int mStride; QWaylandDisplay *mDisplay; + struct wl_buffer *mBuffer; }; QT_END_NAMESPACE -- cgit v0.12 From 4f073a5ae720fc89eda2430f3aaa9e5f4a533af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 7 Oct 2010 11:47:08 -0400 Subject: wayland: Assign a window id to wayland windows --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 8 ++++++++ src/plugins/platforms/wayland/qwaylandintegration.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 277e965..01affac 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -213,12 +213,20 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) , mSurface(0) , mDisplay(display) { + static WId id = 1; + + mWindowId = id++; } QWaylandWindow::~QWaylandWindow() { } +WId QWaylandWindow::winId() const +{ + return mWindowId; +} + void QWaylandWindow::setVisible(bool visible) { QWaylandWindowSurface *wws = diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 4e50f3c..ed9ca3b 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -132,10 +132,12 @@ public: struct wl_surface *surface() { return mSurface; } void setVisible(bool visible); + WId winId() const; private: struct wl_surface *mSurface; QWaylandDisplay *mDisplay; + WId mWindowId; }; class QWaylandIntegration : public QPlatformIntegration -- cgit v0.12 From e53dd775ae46b99d61e3aebe0de6b48f94f89678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 7 Oct 2010 12:23:14 -0400 Subject: wayland: Track the QWaylandWindow in the input device instead of the surface The surface is destroyed when the window is hidden, so we can't use that for looking up the widget to send events to. --- .../platforms/wayland/qwaylandinputdevice.cpp | 29 +++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index eeda105..5bddf2f 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -16,8 +16,8 @@ public: private: struct wl_display *mDisplay; struct wl_input_device *mInputDevice; - struct wl_surface *mPointerFocus; - struct wl_surface *mKeyboardFocus; + QWaylandWindow *mPointerFocus; + QWaylandWindow *mKeyboardFocus; static const struct wl_input_device_listener inputDeviceListener; Qt::MouseButtons mButtons; QPoint mSurfacePos; @@ -65,9 +65,9 @@ void QWaylandInputDevice::inputHandleMotion(void *data, int32_t x, int32_t y, int32_t surface_x, int32_t surface_y) { + Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window = - (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + QWaylandWindow *window = inputDevice->mPointerFocus; inputDevice->mSurfacePos = QPoint(surface_x, surface_y); inputDevice->mGlobalPos = QPoint(x, y); @@ -82,9 +82,9 @@ void QWaylandInputDevice::inputHandleButton(void *data, struct wl_input_device *input_device, uint32_t time, uint32_t button, uint32_t state) { + Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; - QWaylandWindow *window = - (QWaylandWindow *) wl_surface_get_user_data(inputDevice->mPointerFocus); + QWaylandWindow *window = inputDevice->mPointerFocus; Qt::MouseButton qt_button; switch (button) { @@ -117,6 +117,9 @@ void QWaylandInputDevice::inputHandleKey(void *data, struct wl_input_device *input_device, uint32_t time, uint32_t key, uint32_t state) { + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mKeyboardFocus; } void QWaylandInputDevice::inputHandlePointerFocus(void *data, @@ -124,12 +127,14 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, uint32_t time, struct wl_surface *surface, int32_t x, int32_t y, int32_t sx, int32_t sy) { + Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; + qWarning("pointer focus %p", surface); + if (inputDevice->mPointerFocus) { - window = (QWaylandWindow *) - wl_surface_get_user_data(inputDevice->mPointerFocus); + window = inputDevice->mPointerFocus; QWindowSystemInterface::handleLeaveEvent(window->widget()); inputDevice->mPointerFocus = NULL; } @@ -137,7 +142,7 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, if (surface) { window = (QWaylandWindow *) wl_surface_get_user_data(surface); QWindowSystemInterface::handleEnterEvent(window->widget()); - inputDevice->mPointerFocus = surface; + inputDevice->mPointerFocus = window; } } @@ -147,18 +152,18 @@ void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, struct wl_surface *surface, struct wl_array *keys) { + Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; if (inputDevice->mKeyboardFocus) { - window = (QWaylandWindow *) - wl_surface_get_user_data(inputDevice->mKeyboardFocus); + window = inputDevice->mKeyboardFocus; inputDevice->mKeyboardFocus = NULL; } if (surface) { window = (QWaylandWindow *) wl_surface_get_user_data(surface); - inputDevice->mKeyboardFocus = surface; + inputDevice->mKeyboardFocus = window; } } -- cgit v0.12 From 9598483764d0c95751abcfb384422916b64fd283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 7 Oct 2010 17:07:59 -0400 Subject: Use QImage::Format_ARGB32_Premultiplied for the surface --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 01affac..21e7be7 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -64,7 +64,7 @@ void QWaylandDisplay::outputHandleGeometry(void *data, screen = new QWaylandScreen(); screen->mGeometry = QRect(0, 0, width, height); screen->mDepth = 32; - screen->mFormat = QImage::Format_ARGB32; + screen->mFormat = QImage::Format_ARGB32_Premultiplied; screen->mOutput = output; qwd->mScreens.append(screen); -- cgit v0.12 From a052aafacb81482f694c4c41d166439c30d12eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Fri, 8 Oct 2010 16:02:01 -0400 Subject: Cursors, keyboard support, move/resize --- .../platforms/wayland/qwaylandinputdevice.cpp | 162 ++++++++++++++----- .../platforms/wayland/qwaylandinputdevice.h | 58 +++++++ .../platforms/wayland/qwaylandintegration.cpp | 177 ++++++++++++++++++++- .../platforms/wayland/qwaylandintegration.h | 18 ++- .../platforms/wayland/qwaylandwindowsurface.cpp | 79 +++++---- .../platforms/wayland/qwaylandwindowsurface.h | 17 +- src/plugins/platforms/wayland/wayland.pro | 2 +- 7 files changed, 426 insertions(+), 87 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandinputdevice.h diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 5bddf2f..fd7a649 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -1,49 +1,14 @@ #include <QWindowSystemInterface> #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" -#include "qfontconfigdatabase.h" #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> #include <unistd.h> #include <fcntl.h> - -class QWaylandInputDevice { -public: - QWaylandInputDevice(struct wl_display *display, uint32_t id); - -private: - struct wl_display *mDisplay; - struct wl_input_device *mInputDevice; - QWaylandWindow *mPointerFocus; - QWaylandWindow *mKeyboardFocus; - static const struct wl_input_device_listener inputDeviceListener; - Qt::MouseButtons mButtons; - QPoint mSurfacePos; - QPoint mGlobalPos; - - static void inputHandleMotion(void *data, - struct wl_input_device *input_device, - uint32_t time, - int32_t x, int32_t y, - int32_t sx, int32_t sy); - static void inputHandleButton(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t button, uint32_t state); - static void inputHandleKey(void *data, - struct wl_input_device *input_device, - uint32_t time, uint32_t key, uint32_t state); - static void inputHandlePointerFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, struct wl_surface *surface, - int32_t x, int32_t y, int32_t sx, int32_t sy); - static void inputHandleKeyboardFocus(void *data, - struct wl_input_device *input_device, - uint32_t time, - struct wl_surface *surface, - struct wl_array *keys); -}; +#include <X11/extensions/XKBcommon.h> +#include <X11/keysym.h> QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, uint32_t id) @@ -53,10 +18,20 @@ QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, , mKeyboardFocus(NULL) , mButtons(0) { + struct xkb_rule_names names; + wl_input_device_add_listener(mInputDevice, &inputDeviceListener, this); wl_input_device_set_user_data(mInputDevice, this); + + names.rules = "evdev"; + names.model = "pc105"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + + mXkb = xkb_compile_keymap_from_rules(&names); } void QWaylandInputDevice::inputHandleMotion(void *data, @@ -71,6 +46,7 @@ void QWaylandInputDevice::inputHandleMotion(void *data, inputDevice->mSurfacePos = QPoint(surface_x, surface_y); inputDevice->mGlobalPos = QPoint(x, y); + inputDevice->mTime = time; QWindowSystemInterface::handleMouseEvent(window->widget(), time, inputDevice->mSurfacePos, @@ -95,7 +71,7 @@ void QWaylandInputDevice::inputHandleButton(void *data, qt_button = Qt::RightButton; break; case 274: - qt_button = Qt::MidButton; + qt_button = Qt::MiddleButton; break; default: return; @@ -106,6 +82,7 @@ void QWaylandInputDevice::inputHandleButton(void *data, else inputDevice->mButtons &= ~qt_button; + inputDevice->mTime = time; QWindowSystemInterface::handleMouseEvent(window->widget(), time, inputDevice->mSurfacePos, @@ -113,6 +90,72 @@ void QWaylandInputDevice::inputHandleButton(void *data, inputDevice->mButtons); } +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK; + const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK; + + Qt::KeyboardModifiers ret = 0; + if (s & XKB_COMMON_SHIFT_MASK) + ret |= Qt::ShiftModifier; + if (s & XKB_COMMON_CONTROL_MASK) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; + + return ret; +} + +static uint32_t translateKey(uint32_t sym, char *string, size_t size) +{ + string[0] = '\0'; + + switch (sym) { + case XK_Escape: return Qt::Key_Escape; + case XK_Tab: return Qt::Key_Tab; + case XK_ISO_Left_Tab: return Qt::Key_Backtab; + case XK_BackSpace: return Qt::Key_Backspace; + case XK_Return: return Qt::Key_Return; + case XK_Insert: return Qt::Key_Insert; + case XK_Delete: return Qt::Key_Delete; + case XK_Clear: return Qt::Key_Delete; + case XK_Pause: return Qt::Key_Pause; + case XK_Print: return Qt::Key_Print; + + case XK_Home: return Qt::Key_Home; + case XK_End: return Qt::Key_End; + case XK_Left: return Qt::Key_Left; + case XK_Up: return Qt::Key_Up; + case XK_Right: return Qt::Key_Right; + case XK_Down: return Qt::Key_Down; + case XK_Prior: return Qt::Key_PageUp; + case XK_Next: return Qt::Key_PageDown; + + case XK_Shift_L: return Qt::Key_Shift; + case XK_Shift_R: return Qt::Key_Shift; + case XK_Shift_Lock: return Qt::Key_Shift; + case XK_Control_L: return Qt::Key_Control; + case XK_Control_R: return Qt::Key_Control; + case XK_Meta_L: return Qt::Key_Meta; + case XK_Meta_R: return Qt::Key_Meta; + case XK_Alt_L: return Qt::Key_Alt; + case XK_Alt_R: return Qt::Key_Alt; + case XK_Caps_Lock: return Qt::Key_CapsLock; + case XK_Num_Lock: return Qt::Key_NumLock; + case XK_Scroll_Lock: return Qt::Key_ScrollLock; + case XK_Super_L: return Qt::Key_Super_L; + case XK_Super_R: return Qt::Key_Super_R; + case XK_Menu: return Qt::Key_Menu; + + default: + string[0] = sym; + string[1] = '\0'; + return toupper(sym); + } +} + void QWaylandInputDevice::inputHandleKey(void *data, struct wl_input_device *input_device, uint32_t time, uint32_t key, uint32_t state) @@ -120,6 +163,39 @@ void QWaylandInputDevice::inputHandleKey(void *data, Q_UNUSED(input_device); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window = inputDevice->mKeyboardFocus; + uint32_t code, sym, level; + Qt::KeyboardModifiers modifiers; + QEvent::Type type; + char s[2]; + + code = key + inputDevice->mXkb->min_key_code; + + level = 0; + if (inputDevice->mModifiers & Qt::ShiftModifier && + XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1) + level = 1; + + sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0); + + modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]); + + if (state) { + inputDevice->mModifiers |= modifiers; + type = QEvent::KeyPress; + } else { + inputDevice->mModifiers &= ~modifiers; + type = QEvent::KeyRelease; + } + + sym = translateKey(sym, s, sizeof s); + + qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", + code, sym, s[0], (int) inputDevice->mModifiers); + + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); } void QWaylandInputDevice::inputHandlePointerFocus(void *data, @@ -131,8 +207,6 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; - qWarning("pointer focus %p", surface); - if (inputDevice->mPointerFocus) { window = inputDevice->mPointerFocus; QWindowSystemInterface::handleLeaveEvent(window->widget()); @@ -144,6 +218,8 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, QWindowSystemInterface::handleEnterEvent(window->widget()); inputDevice->mPointerFocus = window; } + + inputDevice->mTime = time; } void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, @@ -175,9 +251,7 @@ const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = QWaylandInputDevice::inputHandleKeyboardFocus, }; - -QWaylandInputDevice * -waylandInputDeviceCreate(struct wl_display *display, uint32_t id) +void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) { - return new QWaylandInputDevice(display, id); + wl_input_device_attach(mInputDevice, mTime, buffer->mBuffer, x, y); } diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h new file mode 100644 index 0000000..749ef70 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -0,0 +1,58 @@ +#ifndef QWAYLANDINPUTDEVICE_H +#define QWAYLANDINPUTDEVICE_H + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> +#include "qwaylandwindowsurface.h" + +QT_BEGIN_NAMESPACE + +class QWaylandWindow; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + void attach(QWaylandBuffer *buffer, int x, int y); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + QWaylandWindow *mPointerFocus; + QWaylandWindow *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + struct xkb_desc *mXkb; + Qt::KeyboardModifiers mModifiers; + uint32_t mTime; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 21e7be7..a728f78 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,4 +1,6 @@ +#include <QImageReader> #include <QWindowSystemInterface> +#include <QPlatformCursor> #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" #include "qfontconfigdatabase.h" @@ -13,6 +15,150 @@ extern "C" { #include <xf86drm.h> } +class QWaylandCursor : QPlatformCursor { +public: + QWaylandCursor(QWaylandDisplay *display, + QPlatformScreen *screen) + : QPlatformCursor(screen) + , mDisplay(display) { } + + void changeCursor(QCursor *cursor, QWidget *widget); + QWaylandBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +#define DATADIR "/usr/share" + +static const struct pointer_image { + const char *filename; + int hotspot_x, hotspot_y; +} pointer_images[] = { + /* FIXME: Half of these are wrong... */ + /* Qt::ArrowCursor */ + { DATADIR "/wayland/left_ptr.png", 10, 5 }, + /* Qt::UpArrowCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::CrossCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::WaitCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::IBeamCursor */ + { DATADIR "/wayland/xterm.png", 15, 15 }, + /* Qt::SizeVerCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::SizeHorCursor */ + { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, + /* Qt::SizeBDiagCursor */ + { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, + /* Qt::SizeFDiagCursor */ + { DATADIR "/wayland/bottom_side.png", 16, 20 }, + /* Qt::SizeAllCursor */ + { DATADIR "/wayland/left_side.png", 10, 20 }, + /* Qt::BlankCursor */ + { DATADIR "/wayland/right_side.png", 30, 19 }, + /* Qt::SplitVCursor */ + { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, + /* Qt::SplitHCursor */ + { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, + /* Qt::PointingHandCursor */ + { DATADIR "/wayland/hand2.png", 14, 8 }, + /* Qt::ForbiddenCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::WhatsThisCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::BusyCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::OpenHandCursor */ + { DATADIR "/wayland/hand1.png", 18, 11 }, + /* Qt::ClosedHandCursor */ + { DATADIR "/wayland/grabbing.png", 20, 17 }, + /* Qt::DragCopyCursor */ + { DATADIR "/wayland/dnd-copy.png", 13, 13 }, + /* Qt::DragMoveCursor */ + { DATADIR "/wayland/dnd-move.png", 13, 13 }, + /* Qt::DragLinkCursor */ + { DATADIR "/wayland/dnd-link.png", 13, 13 }, +}; + +void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + const struct pointer_image *p; + + if (widget == NULL) + return; + + p = NULL; + + switch (cursor->shape()) { + case Qt::ArrowCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::UpArrowCursor: + case Qt::CrossCursor: + case Qt::WaitCursor: + break; + case Qt::IBeamCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::SizeVerCursor: /* 5 */ + case Qt::SizeHorCursor: + case Qt::SizeBDiagCursor: + case Qt::SizeFDiagCursor: + case Qt::SizeAllCursor: + case Qt::BlankCursor: /* 10 */ + break; + case Qt::SplitVCursor: + case Qt::SplitHCursor: + case Qt::PointingHandCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::ForbiddenCursor: + case Qt::WhatsThisCursor: /* 15 */ + case Qt::BusyCursor: + break; + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: /* 20 */ + case Qt::DragLinkCursor: + p = &pointer_images[cursor->shape()]; + break; + + default: + case Qt::BitmapCursor: + break; + } + + if (!p) { + p = &pointer_images[0]; + qWarning("unhandled cursor %d", cursor->shape()); + } + + QImageReader reader(p->filename); + + if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { + if (mBuffer) + delete mBuffer; + + mBuffer = new QWaylandBuffer(mDisplay, reader.size(), + QImage::Format_ARGB32); + } + + reader.read(&mBuffer->mImage); + + mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); +} + +void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) +{ + /* Qt doesn't tell us which input device we should set the cursor + * for, so set it for all devices. */ + for (int i = 0; i < mInputDevices.count(); i++) { + QWaylandInputDevice *inputDevice = mInputDevices.at(i); + inputDevice->attach(buffer, x, y); + } +} + struct wl_surface *QWaylandDisplay::createSurface() { return wl_compositor_create_surface(mCompositor); @@ -53,6 +199,21 @@ const struct wl_drm_listener QWaylandDisplay::drmListener = { QWaylandDisplay::drmHandleAuthenticated }; +void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); + + ww->configure(time, edges, x, y, width, height); +} + +const struct wl_shell_listener QWaylandDisplay::shellListener = { + QWaylandDisplay::shellHandleConfigure, +}; + void QWaylandDisplay::outputHandleGeometry(void *data, struct wl_output *output, int32_t width, int32_t height) @@ -67,6 +228,8 @@ void QWaylandDisplay::outputHandleGeometry(void *data, screen->mFormat = QImage::Format_ARGB32_Premultiplied; screen->mOutput = output; + new QWaylandCursor(qwd, screen); + qwd->mScreens.append(screen); } @@ -89,12 +252,15 @@ void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); } else if (strcmp(interface, "shm") == 0) { qwd->mShm = wl_shm_create(display, id); + } else if (strcmp(interface, "shell") == 0) { + qwd->mShell = wl_shell_create(display, id); + wl_shell_add_listener(qwd->mShell, &shellListener, qwd); } else if (strcmp(interface, "output") == 0) { struct wl_output *output = wl_output_create(display, id); wl_output_add_listener(output, &outputListener, qwd); } else if (strcmp(interface, "input_device") == 0) { QWaylandInputDevice *inputDevice = - waylandInputDeviceCreate(display, id); + new QWaylandInputDevice(display, id); qwd->mInputDevices.append(inputDevice); } } @@ -242,6 +408,15 @@ void QWaylandWindow::setVisible(bool visible) } } +void QWaylandWindow::configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QRect geometry = QRect(x, y, width, height); + + QWindowSystemInterface::handleGeometryChange(widget(), geometry); +} + QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index ed9ca3b..9f0b371 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -48,13 +48,11 @@ #include <QtGui/QPlatformScreen> #include <wayland-client.h> +#include "qwaylandinputdevice.h" QT_BEGIN_NAMESPACE -class QWaylandInputDevice; - -QWaylandInputDevice * -waylandInputDeviceCreate(struct wl_display *display, uint32_t id); +class QWaylandBuffer; class QWaylandDisplay : public QObject { Q_OBJECT; @@ -70,6 +68,8 @@ public: struct wl_visual *visual); struct wl_visual *argbVisual(); + void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + public slots: void eventDispatcher(void); void flushRequests(void); @@ -79,6 +79,7 @@ private: struct wl_compositor *mCompositor; struct wl_drm *mDrm; struct wl_shm *mShm; + struct wl_shell *mShell; char *mDeviceName; int mFd; bool mAuthenticated; @@ -100,10 +101,17 @@ private: struct wl_output *output, int32_t width, int32_t height); + static void shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t x, int32_t y, + int32_t width, int32_t height); + static int sourceUpdate(uint32_t mask, void *data); static const struct wl_drm_listener drmListener; static const struct wl_output_listener outputListener; + static const struct wl_shell_listener shellListener; }; class QWaylandScreen : public QPlatformScreen @@ -132,6 +140,8 @@ public: struct wl_surface *surface() { return mSurface; } void setVisible(bool visible); + void configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; private: diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 41f72d0..a988d63 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -52,10 +52,46 @@ QT_BEGIN_NAMESPACE +QWaylandBuffer::QWaylandBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) +{ + int stride = size.width() * 4; + int alloc = stride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + uchar *data = (uchar *) + mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == (uchar *) MAP_FAILED) { + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + close(fd); + return; + } + + mImage = QImage(data, size.width(), size.height(), stride, format); + mBuffer = display->createShmBuffer(fd, size.width(), size.height(), + stride, display->argbVisual()); + close(fd); +} + +QWaylandBuffer::~QWaylandBuffer(void) +{ + munmap((void *) mImage.constBits(), mImage.byteCount()); + wl_buffer_destroy(mBuffer); +} + QWaylandWindowSurface::QWaylandWindowSurface(QWidget *window, QWaylandDisplay *display) : QWindowSurface(window) - , mImage(0) + , mBuffer(0) , mDisplay(display) { //qDebug() << "QWaylandWindowSurface::QWaylandWindowSurface:" << (long)this; @@ -67,8 +103,7 @@ QWaylandWindowSurface::~QWaylandWindowSurface() QPaintDevice *QWaylandWindowSurface::paintDevice() { - //qDebug() << "QWaylandWindowSurface::paintDevice"; - return mImage; + return &mBuffer->mImage; } void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -90,10 +125,12 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const void QWaylandWindowSurface::attach(void) { QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QRect geometry = window()->geometry(); - if (ww->surface()) { - wl_surface_attach(ww->surface(), mBuffer); - wl_surface_map(ww->surface(), 0, 0, mImage->width(), mImage->height()); + if (ww->surface() && mBuffer) { + wl_surface_attach(ww->surface(), mBuffer->mBuffer); + wl_surface_map(ww->surface(), geometry.x(), geometry.y(), + mBuffer->mImage.width(), mBuffer->mImage.height()); } } @@ -103,35 +140,13 @@ void QWaylandWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - if (mImage != NULL && mImage->size() == size) + if (mBuffer != NULL && mBuffer->mImage.size() == size) return; - if (mImage != NULL) { - delete mImage; - munmap(mData, mSize); - wl_buffer_destroy(mBuffer); - } - - mStride = size.width() * 4; - mSize = mStride * size.height(); - char filename[] = "/tmp/wayland-shm-XXXXXX"; - int fd = mkstemp(filename); - if (fd < 0) - qWarning("open %s failed: %s", filename, strerror(errno)); - if (ftruncate(fd, mSize) < 0) - qWarning("ftruncate failed: %s", strerror(errno)); - mData = (uchar *) - mmap(NULL, mSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - unlink(filename); - - if (mData == (uchar *) MAP_FAILED) - qWarning("mmap /dev/zero failed: %s", strerror(errno)); - - mImage = new QImage(mData, size.width(), size.height(), mStride, format); + if (mBuffer != NULL) + delete mBuffer; - mBuffer = mDisplay->createShmBuffer(fd, size.width(), size.height(), - mStride, mDisplay->argbVisual()); - close(fd); + mBuffer = new QWaylandBuffer(mDisplay, size, format); attach(); } diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 1da6ab4..711b0c1 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -48,6 +48,17 @@ QT_BEGIN_NAMESPACE +class QWaylandDisplay; + +class QWaylandBuffer { +public: + QWaylandBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandBuffer(); + QImage mImage; + struct wl_buffer *mBuffer; +}; + class QWaylandWindowSurface : public QWindowSurface { public: @@ -60,12 +71,8 @@ public: void attach(void); private: - QImage *mImage; - uchar *mData; - int mSize; - int mStride; + QWaylandBuffer *mBuffer; QWaylandDisplay *mDisplay; - struct wl_buffer *mBuffer; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index c1f5bae..f5751e2 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -12,7 +12,7 @@ HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h INCLUDEPATH += /usr/include/libdrm -LIBS += -lwayland-client -ldrm +LIBS += -lwayland-client -ldrm -lxkbcommon include (../fontdatabases/fontconfig/fontconfig.pri) -- cgit v0.12 From d0c99dada04785c95f321495c621cd18eaef8b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 14 Oct 2010 15:36:59 -0400 Subject: Initialize EGL --- .../platforms/wayland/qwaylandintegration.cpp | 161 +++++++++++++++++---- .../platforms/wayland/qwaylandintegration.h | 10 +- src/plugins/platforms/wayland/wayland.pro | 2 +- 3 files changed, 142 insertions(+), 31 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index a728f78..5882ad4 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,13 +1,18 @@ +#include "qfontconfigdatabase.h" + #include <QImageReader> #include <QWindowSystemInterface> #include <QPlatformCursor> -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" -#include "qfontconfigdatabase.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" + #include <unistd.h> #include <fcntl.h> @@ -182,16 +187,50 @@ void QWaylandDisplay::drmHandleDevice(void *data, { Q_UNUSED(drm); QWaylandDisplay *qwd = (QWaylandDisplay *) data; + drm_magic_t magic; qwd->mDeviceName = strdup(device); + + qwd->mFd = open(qwd->mDeviceName, O_RDWR); + if (qwd->mFd < 0) { + qWarning("drm open failed: %m"); + return; + } + + if (drmGetMagic(qwd->mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + wl_drm_authenticate(qwd->mDrm, magic); } void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) { Q_UNUSED(drm); QWaylandDisplay *qwd = (QWaylandDisplay *) data; + EGLint major, minor; + const char *extensions; + + qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); + if (qwd->mEglDisplay == NULL) { + qWarning("failed to create display"); + return; + } + + if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { + qWarning("failed to initialize display"); + qwd->mEglDisplay = NULL; + return; + } - qwd->mAuthenticated = true; + extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); + if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { + qWarning("EGL_KHR_surfaceless_opengles2 not available"); + eglTerminate(qwd->mEglDisplay); + qwd->mEglDisplay = NULL; + return; + } } const struct wl_drm_listener QWaylandDisplay::drmListener = { @@ -265,13 +304,24 @@ void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, } } -static void initial_roundtrip(void *data) +static void roundtripCallback(void *data) { bool *done = (bool *) data; *done = true; } +static void forceRoundtrip(struct wl_display *display) +{ + bool done; + + wl_display_sync_callback(display, roundtripCallback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + static const char socket_name[] = "\0wayland"; void QWaylandDisplay::eventDispatcher(void) @@ -304,9 +354,6 @@ void QWaylandDisplay::flushRequests(void) QWaylandDisplay::QWaylandDisplay(void) : mWriteNotifier(0) { - drm_magic_t magic; - bool done; - mDisplay = wl_display_create(socket_name, sizeof socket_name); if (mDisplay == NULL) { fprintf(stderr, "failed to create display: %m\n"); @@ -317,28 +364,17 @@ QWaylandDisplay::QWaylandDisplay(void) QWaylandDisplay::displayHandleGlobal, this); /* Process connection events. */ - wl_display_sync_callback(mDisplay, initial_roundtrip, &done); - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); - done = false; - while (!done) - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); - - mFd = open(mDeviceName, O_RDWR); - if (mFd < 0) { - qWarning("drm open failed: %m\n"); - return; - } - - if (drmGetMagic(mFd, &magic)) { - qWarning("DRI2: failed to get drm magic"); - return; - } + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + if (!mShm || !mDeviceName) + forceRoundtrip(mDisplay); - /* Wait for authenticated event */ - wl_drm_authenticate(mDrm, magic); - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); - while (!mAuthenticated) - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + /* Force a roundtrip to finish the drm authentication so we + * initialize EGL before proceeding */ + forceRoundtrip(mDisplay); + if (mEglDisplay == NULL) + qWarning("EGL not available"); + else + qWarning("EGL initialized"); int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); @@ -417,6 +453,73 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + +private: + EGLContext mContext; + QPlatformWindowFormat mFormat; + QWaylandDisplay *mDisplay; +}; + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , mContext(0) + , mFormat(format) + , mDisplay(wd) +{ + EGLDisplay eglDisplay; + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + eglDisplay = mDisplay->eglDisplay(); + mContext = eglCreateContext(eglDisplay, NULL, + EGL_NO_CONTEXT, contextAttribs); +} + +QWaylandGLContext::~QWaylandGLContext() +{ + if (mContext) + eglDestroyContext(mDisplay->eglDisplay(), mContext); +} + +void QWaylandGLContext::makeCurrent() +{ +} + +void QWaylandGLContext::doneCurrent() +{ +} + +void QWaylandGLContext::swapBuffers() +{ +} + +void *QWaylandGLContext::getProcAddress(const QString &string) +{ + return (void *) eglGetProcAddress(string.toLatin1().data()); +} + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast<QWaylandWindow *>(this); + that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + } + + return mGLContext; +} + QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 9f0b371..81819be 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -50,6 +50,11 @@ #include <wayland-client.h> #include "qwaylandinputdevice.h" +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + QT_BEGIN_NAMESPACE class QWaylandBuffer; @@ -67,6 +72,7 @@ public: uint32_t stride, struct wl_visual *visual); struct wl_visual *argbVisual(); + EGLDisplay eglDisplay() { return mEglDisplay; } void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); @@ -82,11 +88,11 @@ private: struct wl_shell *mShell; char *mDeviceName; int mFd; - bool mAuthenticated; QList<QPlatformScreen *> mScreens; QList<QWaylandInputDevice *> mInputDevices; QSocketNotifier *mReadNotifier; QSocketNotifier *mWriteNotifier; + EGLDisplay mEglDisplay; static void displayHandleGlobal(struct wl_display *display, uint32_t id, @@ -143,10 +149,12 @@ public: void configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; + QPlatformGLContext *glContext() const; private: struct wl_surface *mSurface; QWaylandDisplay *mDisplay; + QPlatformGLContext *mGLContext; WId mWindowId; }; diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index f5751e2..7a3d0b9 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -12,7 +12,7 @@ HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h INCLUDEPATH += /usr/include/libdrm -LIBS += -lwayland-client -ldrm -lxkbcommon +LIBS += -lwayland-client -ldrm -lxkbcommon -lEGL -lGLESv2 include (../fontdatabases/fontconfig/fontconfig.pri) -- cgit v0.12 From f9d0a75c066ecc464907c2021874d9e2c347d9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= <krh@bitplanet.net> Date: Thu, 14 Oct 2010 21:25:15 -0400 Subject: Introduce drm wayland buffer --- .../platforms/wayland/qwaylandintegration.cpp | 33 ++++-- .../platforms/wayland/qwaylandintegration.h | 7 ++ .../platforms/wayland/qwaylandwindowsurface.cpp | 130 +++++++++++++++++---- .../platforms/wayland/qwaylandwindowsurface.h | 21 ++-- 4 files changed, 151 insertions(+), 40 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 5882ad4..30e0f6a 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -28,7 +28,7 @@ public: , mDisplay(display) { } void changeCursor(QCursor *cursor, QWidget *widget); - QWaylandBuffer *mBuffer; + QWaylandShmBuffer *mBuffer; QWaylandDisplay *mDisplay; }; @@ -145,8 +145,8 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) if (mBuffer) delete mBuffer; - mBuffer = new QWaylandBuffer(mDisplay, reader.size(), - QImage::Format_ARGB32); + mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), + QImage::Format_ARGB32); } reader.read(&mBuffer->mImage); @@ -177,6 +177,14 @@ struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); } +struct wl_buffer *QWaylandDisplay::createDrmBuffer(int name, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); +} + struct wl_visual *QWaylandDisplay::argbVisual() { return wl_display_get_argb_visual(mDisplay); @@ -431,19 +439,28 @@ WId QWaylandWindow::winId() const void QWaylandWindow::setVisible(bool visible) { - QWaylandWindowSurface *wws = - (QWaylandWindowSurface *) widget()->windowSurface(); - if (visible) { mSurface = mDisplay->createSurface(); wl_surface_set_user_data(mSurface, this); - wws->attach(); + attach(mBuffer); } else { wl_surface_destroy(mSurface); mSurface = NULL; } } +void QWaylandWindow::attach(QWaylandBuffer *buffer) +{ + QRect geometry = widget()->geometry(); + + mBuffer = buffer; + if (mSurface) { + wl_surface_attach(mSurface, mBuffer->mBuffer); + wl_surface_map(mSurface, geometry.x(), geometry.y(), + geometry.width(), geometry.height()); + } +} + void QWaylandWindow::configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height) @@ -529,7 +546,7 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const { Q_UNUSED(winId); - return new QWaylandWindowSurface(widget, mDisplay); + return new QWaylandShmWindowSurface(widget, mDisplay); } QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 81819be..6267e9b 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -71,6 +71,10 @@ public: struct wl_buffer *createShmBuffer(int fd, int width, int height, uint32_t stride, struct wl_visual *visual); + struct wl_buffer *createDrmBuffer(int name, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *argbVisual(); EGLDisplay eglDisplay() { return mEglDisplay; } @@ -150,12 +154,15 @@ public: int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; QPlatformGLContext *glContext() const; + void attach(QWaylandBuffer *buffer); private: struct wl_surface *mSurface; QWaylandDisplay *mDisplay; QPlatformGLContext *mGLContext; WId mWindowId; + + QWaylandBuffer *mBuffer; }; class QWaylandIntegration : public QPlatformIntegration diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index a988d63..0fd519e 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -50,10 +50,19 @@ #include <errno.h> #include <sys/mman.h> +#define GL_GLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#define MESA_EGL_NO_X11_HEADERS + +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + QT_BEGIN_NAMESPACE -QWaylandBuffer::QWaylandBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format) +QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) { int stride = size.width() * 4; int alloc = stride * size.height(); @@ -82,31 +91,30 @@ QWaylandBuffer::QWaylandBuffer(QWaylandDisplay *display, close(fd); } -QWaylandBuffer::~QWaylandBuffer(void) +QWaylandShmBuffer::~QWaylandShmBuffer(void) { munmap((void *) mImage.constBits(), mImage.byteCount()); wl_buffer_destroy(mBuffer); } -QWaylandWindowSurface::QWaylandWindowSurface(QWidget *window, - QWaylandDisplay *display) +QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window, + QWaylandDisplay *display) : QWindowSurface(window) , mBuffer(0) , mDisplay(display) { - //qDebug() << "QWaylandWindowSurface::QWaylandWindowSurface:" << (long)this; } -QWaylandWindowSurface::~QWaylandWindowSurface() +QWaylandShmWindowSurface::~QWaylandShmWindowSurface() { } -QPaintDevice *QWaylandWindowSurface::paintDevice() +QPaintDevice *QWaylandShmWindowSurface::paintDevice() { return &mBuffer->mImage; } -void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(widget); Q_UNUSED(offset); @@ -122,21 +130,9 @@ void QWaylandWindowSurface::flush(QWidget *widget, const QRegion ®ion, const } } -void QWaylandWindowSurface::attach(void) +void QWaylandShmWindowSurface::resize(const QSize &size) { QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QRect geometry = window()->geometry(); - - if (ww->surface() && mBuffer) { - wl_surface_attach(ww->surface(), mBuffer->mBuffer); - wl_surface_map(ww->surface(), geometry.x(), geometry.y(), - mBuffer->mImage.width(), mBuffer->mImage.height()); - } -} - -void QWaylandWindowSurface::resize(const QSize &size) -{ - //qDebug() << "QWaylandWindowSurface::setGeometry:" << (long)this << rect; QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); @@ -146,9 +142,95 @@ void QWaylandWindowSurface::resize(const QSize &size) if (mBuffer != NULL) delete mBuffer; - mBuffer = new QWaylandBuffer(mDisplay, size, format); + mBuffer = new QWaylandShmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); +} + - attach(); +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + EGLImageKHR mImage; + GLuint mTexture; + QWaylandDisplay *mDisplay; +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandDrmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QWaylandDrmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) + : mDisplay(display) +{ + EGLint name, stride; + EGLint imageAttribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_NONE + }; + + imageAttribs[1] = size.width(); + imageAttribs[3] = size.height(); + mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + glGenTextures(1, &mTexture); + glBindTexture(GL_TEXTURE_2D, mTexture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + + eglExportDRMImageMESA(mDisplay->eglDisplay(), + mImage, &name, NULL, &stride); + + mBuffer = display->createDrmBuffer(name, size.width(), size.height(), + stride, display->argbVisual()); +} + +QWaylandDrmBuffer::~QWaylandDrmBuffer(void) +{ + glDeleteTextures(1, &mTexture); + eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); + wl_buffer_destroy(mBuffer); +} + + +QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, + QWaylandDisplay *display) + : QWindowSurface(window) + , mBuffer(0) + , mDisplay(display) +{ +} + +QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() +{ +} + +QPaintDevice *QWaylandDrmWindowSurface::paintDevice() +{ + return NULL; +} + +void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ +} + +void QWaylandDrmWindowSurface::resize(const QSize &size) +{ } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 711b0c1..2246db6 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -52,26 +52,31 @@ class QWaylandDisplay; class QWaylandBuffer { public: - QWaylandBuffer(QWaylandDisplay *display, + QWaylandBuffer() { } + virtual ~QWaylandBuffer() { } + struct wl_buffer *mBuffer; +}; + +class QWaylandShmBuffer : public QWaylandBuffer { +public: + QWaylandShmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format); - ~QWaylandBuffer(); + ~QWaylandShmBuffer(); QImage mImage; - struct wl_buffer *mBuffer; }; -class QWaylandWindowSurface : public QWindowSurface +class QWaylandShmWindowSurface : public QWindowSurface { public: - QWaylandWindowSurface(QWidget *window, QWaylandDisplay *display); - ~QWaylandWindowSurface(); + QWaylandShmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandShmWindowSurface(); QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size); - void attach(void); private: - QWaylandBuffer *mBuffer; + QWaylandShmBuffer *mBuffer; QWaylandDisplay *mDisplay; }; -- cgit v0.12 From 229d9d36c3ba3f4149d050a6942886b181a90db7 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Fri, 22 Oct 2010 10:30:27 -0700 Subject: Wayland: misc cleanups Unused variables, debug output. --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 12 ++++++++++-- src/plugins/platforms/wayland/qwaylandwindowsurface.cpp | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 30e0f6a..248158d 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -252,6 +252,10 @@ void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, int32_t x, int32_t y, int32_t width, int32_t height) { + Q_UNUSED(data); + Q_UNUSED(shell); + Q_UNUSED(time); + Q_UNUSED(edges); QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); ww->configure(time, edges, x, y, width, height); @@ -380,9 +384,9 @@ QWaylandDisplay::QWaylandDisplay(void) * initialize EGL before proceeding */ forceRoundtrip(mDisplay); if (mEglDisplay == NULL) - qWarning("EGL not available"); + qDebug("EGL not available"); else - qWarning("EGL initialized"); + qDebug("EGL initialized"); int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); @@ -465,6 +469,8 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height) { + Q_UNUSED(time); + Q_UNUSED(edges); QRect geometry = QRect(x, y, width, height); QWindowSystemInterface::handleGeometryChange(widget(), geometry); @@ -546,6 +552,8 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const { Q_UNUSED(winId); + Q_UNUSED(winId); + return new QWaylandShmWindowSurface(widget, mDisplay); } diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 0fd519e..0954bc5 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -177,6 +177,8 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format) : mDisplay(display) { + Q_UNUSED(format); + EGLint name, stride; EGLint imageAttribs[] = { EGL_WIDTH, 0, -- cgit v0.12 From 506e3535c85de2b41e0d31bbcd3b726ce8adbeca Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Fri, 22 Oct 2010 10:31:03 -0700 Subject: Wayland: add GL drawing support Works with analogclock, draws upside down, fails to resize, and doesn't show GL widget with hello_es2. --- .../platforms/wayland/qwaylandintegration.cpp | 17 ++- .../platforms/wayland/qwaylandintegration.h | 5 +- .../platforms/wayland/qwaylandwindowsurface.cpp | 140 ++++++++++++++++----- .../platforms/wayland/qwaylandwindowsurface.h | 37 ++++++ 4 files changed, 167 insertions(+), 32 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 248158d..c433983 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -3,6 +3,7 @@ #include <QImageReader> #include <QWindowSystemInterface> #include <QPlatformCursor> +#include <QPaintEngine> #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> @@ -10,6 +11,9 @@ #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> +#include <private/qwindowsurface_gl_p.h> +#include <private/qpixmapdata_gl_p.h> + #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" @@ -405,9 +409,10 @@ QWaylandDisplay::~QWaylandDisplay(void) wl_display_destroy(mDisplay); } -QWaylandIntegration::QWaylandIntegration() +QWaylandIntegration::QWaylandIntegration(bool useOpenGL) : mFontDb(new QFontconfigDatabase()) , mDisplay(new QWaylandDisplay()) + , mUseOpenGL(useOpenGL) { } @@ -419,6 +424,8 @@ QWaylandIntegration::screens() const QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const { + if (mUseOpenGL) + return new QGLPixmapData(type); return new QRasterPixmapData(type); } @@ -426,6 +433,7 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) : QPlatformWindow(window) , mSurface(0) , mDisplay(display) + , mGLContext(0) { static WId id = 1; @@ -434,6 +442,8 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) QWaylandWindow::~QWaylandWindow() { + if (mGLContext) + delete mGLContext; } WId QWaylandWindow::winId() const @@ -508,6 +518,7 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowF eglDisplay = mDisplay->eglDisplay(); mContext = eglCreateContext(eglDisplay, NULL, EGL_NO_CONTEXT, contextAttribs); + eglMakeCurrent(eglDisplay, NULL, NULL, mContext); } QWaylandGLContext::~QWaylandGLContext() @@ -518,10 +529,12 @@ QWaylandGLContext::~QWaylandGLContext() void QWaylandGLContext::makeCurrent() { + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::doneCurrent() { + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::swapBuffers() @@ -554,6 +567,8 @@ QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId wi Q_UNUSED(winId); Q_UNUSED(winId); + if (mUseOpenGL) + return new QWaylandDrmWindowSurface(widget, mDisplay); return new QWaylandShmWindowSurface(widget, mDisplay); } diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 6267e9b..70fb538 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -46,6 +46,7 @@ #include <QObject> #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> +#include "qgl.h" #include <wayland-client.h> #include "qwaylandinputdevice.h" @@ -155,6 +156,7 @@ public: WId winId() const; QPlatformGLContext *glContext() const; void attach(QWaylandBuffer *buffer); + QWaylandBuffer *getBuffer(void) { return mBuffer; } private: struct wl_surface *mSurface; @@ -168,7 +170,7 @@ private: class QWaylandIntegration : public QPlatformIntegration { public: - QWaylandIntegration(); + QWaylandIntegration(bool useOpenGL = false); QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; @@ -181,6 +183,7 @@ public: private: QPlatformFontDatabase *mFontDb; QWaylandDisplay *mDisplay; + bool mUseOpenGL; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 0954bc5..78900ba 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -39,10 +39,18 @@ ** ****************************************************************************/ -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <QGLFramebufferObject> #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" #include <wayland-client.h> #include <unistd.h> @@ -50,15 +58,6 @@ #include <errno.h> #include <sys/mman.h> -#define GL_GLEXT_PROTOTYPES -#define EGL_EGLEXT_PROTOTYPES -#define MESA_EGL_NO_X11_HEADERS - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - QT_BEGIN_NAMESPACE QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, @@ -147,35 +146,77 @@ void QWaylandShmWindowSurface::resize(const QSize &size) ww->attach(mBuffer); } - -class QWaylandDrmBuffer : public QWaylandBuffer { +class QWaylandPaintDevice : public QGLPaintDevice +{ public: - QWaylandDrmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format); - ~QWaylandDrmBuffer(); - EGLImageKHR mImage; - GLuint mTexture; + QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) + : QGLPaintDevice(), mDisplay(display), mWidget(widget) + { + QGLFormat format; + mContext = new QGLContext(format, widget); + mContext->create(); + glGenFramebuffers(1, &mFbo); + glGenRenderbuffers(1, &mRbo); + } + ~QWaylandPaintDevice() + { + glDeleteFramebuffers(1, &mFbo); + glDeleteRenderbuffers(1, &mRbo); + } + + QSize size() const { return mWidget->size(); } + QGLContext *context() const { return mContext; } + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + + void beginPaint(); + void endPaint(); +private: QWaylandDisplay *mDisplay; + QWidget *mWidget; + QGLContext *mContext; + GLuint mFbo, mRbo; }; -class QWaylandDrmWindowSurface : public QWindowSurface +void QWaylandPaintDevice::beginPaint(void) { -public: - QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); - ~QWaylandDrmWindowSurface(); + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = mWidget->geometry(); - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size); + QGLPaintDevice::beginPaint(); -private: - QWaylandDrmBuffer *mBuffer; - QWaylandDisplay *mDisplay; -}; + ctx->makeCurrent(); + glBindFramebuffer(GL_FRAMEBUFFER, mFbo); + glBindRenderbuffer(GL_RENDERBUFFER, mRbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, mRbo); +} + +void QWaylandPaintDevice::endPaint(void) +{ + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = mWidget->geometry(); + + wl_surface_damage(mWindow->surface(), 0, 0, + geometry.width(), geometry.height()); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + ctx->doneCurrent(); + + QGLPaintDevice::endPaint(); +} + +/* + * Shared DRM surface for GL based drawing + */ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format) : mDisplay(display) + , mSize(size) { Q_UNUSED(format); @@ -216,23 +257,62 @@ QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, , mBuffer(0) , mDisplay(display) { + mPaintDevice = new QWaylandPaintDevice(display, window); } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() { + delete mPaintDevice; } QPaintDevice *QWaylandDrmWindowSurface::paintDevice() { - return NULL; + return mPaintDevice; } void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { + Q_UNUSED(region); + Q_UNUSED(offset); + Q_UNUSED(widget); +#if 0 + GLuint surf_rbo, surf_fbo; + QWaylandWindow *mWindow = (QWaylandWindow *)widget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = widget->geometry(); + + ctx->makeCurrent(); + + glGenFramebuffers(1, &surf_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, surf_fbo); + glGenRenderbuffers(1, &surf_rbo); + glBindRenderbuffer(GL_RENDERBUFFER, surf_rbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, surf_rbo); + + wl_surface_damage(mWindow->surface(), 0, 0, + geometry.width(), geometry.height()); + + ctx->doneCurrent(); +#endif } void QWaylandDrmWindowSurface::resize(const QSize &size) { + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mBuffer != NULL && mBuffer->mSize == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 2246db6..a033531 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -42,10 +42,18 @@ #ifndef QWINDOWSURFACE_WAYLAND_H #define QWINDOWSURFACE_WAYLAND_H +#include <QGLFramebufferObject> #include <QtGui/private/qwindowsurface_p.h> #include <QtGui/QPlatformWindow> +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#include <QtOpenGL/qgl.h> + QT_BEGIN_NAMESPACE class QWaylandDisplay; @@ -80,6 +88,35 @@ private: QWaylandDisplay *mDisplay; }; +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + EGLImageKHR mImage; + GLuint mTexture; + QWaylandDisplay *mDisplay; + QGLFramebufferObject *pdev; + QSize mSize; +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandDrmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QWaylandDrmBuffer *mBuffer; + QWaylandDisplay *mDisplay; + QPaintDevice *mPaintDevice; +}; + + QT_END_NAMESPACE #endif -- cgit v0.12 From 632b53c1e2704cf1f922f5b0378693361abb7a3d Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Fri, 22 Oct 2010 14:00:08 -0700 Subject: Wayland: silence unused variable warnings in qwaylandinputdevice.cpp --- src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index fd7a649..6d489b6 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -110,6 +110,7 @@ static Qt::KeyboardModifiers translateModifiers(int s) static uint32_t translateKey(uint32_t sym, char *string, size_t size) { + Q_UNUSED(size); string[0] = '\0'; switch (sym) { @@ -204,6 +205,10 @@ void QWaylandInputDevice::inputHandlePointerFocus(void *data, int32_t x, int32_t y, int32_t sx, int32_t sy) { Q_UNUSED(input_device); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(sx); + Q_UNUSED(sy); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; @@ -229,6 +234,8 @@ void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, struct wl_array *keys) { Q_UNUSED(input_device); + Q_UNUSED(time); + Q_UNUSED(keys); QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; QWaylandWindow *window; -- cgit v0.12 From ca63274bd2e4def7b6b8c8daec978bb5e44faf6e Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 25 Oct 2010 11:36:45 -0700 Subject: Wayland: add waylandgl platform type This will set mUseOpenGL when -platform waylandgl is passed to clients. --- src/plugins/platforms/wayland/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/wayland/main.cpp b/src/plugins/platforms/wayland/main.cpp index 056cc64..1bca661 100644 --- a/src/plugins/platforms/wayland/main.cpp +++ b/src/plugins/platforms/wayland/main.cpp @@ -55,6 +55,7 @@ QStringList QWaylandIntegrationPlugin::keys() const { QStringList list; list << "Wayland"; + list << "WaylandGL"; return list; } @@ -63,6 +64,8 @@ QPlatformIntegration *QWaylandIntegrationPlugin::create(const QString& system, c Q_UNUSED(paramList); if (system.toLower() == "wayland") return new QWaylandIntegration; + if (system.toLower() == "waylandgl") + return new QWaylandIntegration(true); return 0; } -- cgit v0.12 From 4e417fd2d89c99184c939296d969a6fd312c9257 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 25 Oct 2010 11:38:29 -0700 Subject: Wayland: add partial GL widget support GL widgets need a platform GL context. Add one to get hellogl_es2 limping along. --- .../platforms/wayland/qwaylandintegration.cpp | 46 +++++++++++++++++-- .../platforms/wayland/qwaylandintegration.h | 1 + .../platforms/wayland/qwaylandwindowsurface.cpp | 51 ++++------------------ src/plugins/platforms/wayland/wayland.pro | 4 +- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index c433983..9ac22e8 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,3 +1,7 @@ +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + #include "qfontconfigdatabase.h" #include <QImageReader> @@ -434,6 +438,7 @@ QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) , mSurface(0) , mDisplay(display) , mGLContext(0) + , mBuffer(0) { static WId id = 1; @@ -451,6 +456,14 @@ WId QWaylandWindow::winId() const return mWindowId; } +void QWaylandWindow::setParent(const QPlatformWindow *parent) +{ + QWaylandWindow *wParent = (QWaylandWindow *)parent; + + mSurface = wParent->surface(); + wParent->attach(mBuffer); +} + void QWaylandWindow::setVisible(bool visible) { if (visible) { @@ -488,7 +501,7 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, class QWaylandGLContext : public QPlatformGLContext { public: - QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); ~QWaylandGLContext(); void makeCurrent(); void doneCurrent(); @@ -500,13 +513,16 @@ private: EGLContext mContext; QPlatformWindowFormat mFormat; QWaylandDisplay *mDisplay; + QWaylandWindow *mWindow; + GLuint mFbo, mRbo; }; -QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) : QPlatformGLContext() , mContext(0) , mFormat(format) , mDisplay(wd) + , mWindow(window) { EGLDisplay eglDisplay; static const EGLint contextAttribs[] = { @@ -519,26 +535,50 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowF mContext = eglCreateContext(eglDisplay, NULL, EGL_NO_CONTEXT, contextAttribs); eglMakeCurrent(eglDisplay, NULL, NULL, mContext); + + glGenFramebuffers(1, &mFbo); + glGenRenderbuffers(1, &mRbo); } QWaylandGLContext::~QWaylandGLContext() { if (mContext) eglDestroyContext(mDisplay->eglDisplay(), mContext); + glDeleteFramebuffers(1, &mFbo); + glDeleteRenderbuffers(1, &mRbo); } void QWaylandGLContext::makeCurrent() { + QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + QRect geometry = mWindow->geometry(); + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); + if (!mBuffer) + return; + glBindFramebuffer(GL_FRAMEBUFFER, mFbo); + glBindRenderbuffer(GL_RENDERBUFFER, mRbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, mRbo); } void QWaylandGLContext::doneCurrent() { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindRenderbuffer(GL_RENDERBUFFER, 0); eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::swapBuffers() { + QRect geometry = mWindow->geometry(); + + if (!mWindow->surface()) + return; + + wl_surface_damage(mWindow->surface(), 0, 0, + geometry.width(), geometry.height()); } void *QWaylandGLContext::getProcAddress(const QString &string) @@ -550,7 +590,7 @@ QPlatformGLContext *QWaylandWindow::glContext() const { if (!mGLContext) { QWaylandWindow *that = const_cast<QWaylandWindow *>(this); - that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + that->mGLContext = new QWaylandGLContext(mDisplay, that, widget()->platformWindowFormat()); } return mGLContext; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 70fb538..e26f9e3 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -154,6 +154,7 @@ public: void configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; + void setParent(const QPlatformWindow *parent); QPlatformGLContext *glContext() const; void attach(QWaylandBuffer *buffer); QWaylandBuffer *getBuffer(void) { return mBuffer; } diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 78900ba..6e7fa89 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -155,13 +155,6 @@ public: QGLFormat format; mContext = new QGLContext(format, widget); mContext->create(); - glGenFramebuffers(1, &mFbo); - glGenRenderbuffers(1, &mRbo); - } - ~QWaylandPaintDevice() - { - glDeleteFramebuffers(1, &mFbo); - glDeleteRenderbuffers(1, &mRbo); } QSize size() const { return mWidget->size(); } @@ -174,25 +167,16 @@ private: QWaylandDisplay *mDisplay; QWidget *mWidget; QGLContext *mContext; - GLuint mFbo, mRbo; }; void QWaylandPaintDevice::beginPaint(void) { QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); QPlatformGLContext *ctx = mWindow->glContext(); - QRect geometry = mWidget->geometry(); QGLPaintDevice::beginPaint(); ctx->makeCurrent(); - - glBindFramebuffer(GL_FRAMEBUFFER, mFbo); - glBindRenderbuffer(GL_RENDERBUFFER, mRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, mRbo); } void QWaylandPaintDevice::endPaint(void) @@ -201,10 +185,6 @@ void QWaylandPaintDevice::endPaint(void) QPlatformGLContext *ctx = mWindow->glContext(); QRect geometry = mWidget->geometry(); - wl_surface_damage(mWindow->surface(), 0, 0, - geometry.width(), geometry.height()); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBindRenderbuffer(GL_RENDERBUFFER, 0); ctx->doneCurrent(); QGLPaintDevice::endPaint(); @@ -272,30 +252,17 @@ QPaintDevice *QWaylandDrmWindowSurface::paintDevice() void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(region); Q_UNUSED(offset); - Q_UNUSED(widget); -#if 0 - GLuint surf_rbo, surf_fbo; - QWaylandWindow *mWindow = (QWaylandWindow *)widget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); - QRect geometry = widget->geometry(); - - ctx->makeCurrent(); - - glGenFramebuffers(1, &surf_fbo); - glBindFramebuffer(GL_FRAMEBUFFER, surf_fbo); - glGenRenderbuffers(1, &surf_rbo); - glBindRenderbuffer(GL_RENDERBUFFER, surf_rbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, surf_rbo); - - wl_surface_damage(mWindow->surface(), 0, 0, - geometry.width(), geometry.height()); + QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; - ctx->doneCurrent(); -#endif + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } } void QWaylandDrmWindowSurface::resize(const QSize &size) diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 7a3d0b9..ec3f9d3 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -11,7 +11,9 @@ SOURCES = main.cpp \ HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h -INCLUDEPATH += /usr/include/libdrm +contains(QT_CONFIG, opengl) { + QT += opengl +} LIBS += -lwayland-client -ldrm -lxkbcommon -lEGL -lGLESv2 include (../fontdatabases/fontconfig/fontconfig.pri) -- cgit v0.12 From 8288733d680bba6be762ed0e26aa4e95cdfe68e8 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Wed, 27 Oct 2010 14:38:03 -0700 Subject: Wayland: put context & drawing objects into the drm surface Even GL widgets will allocate window surfaces, so share everything there. This still leaves a hole when we mix GL widgets and the raster back end (the created platform GL context won't have a DRM buffer to use for its objects & context), but that won't work right now anyway... --- .../platforms/wayland/qwaylandintegration.cpp | 34 ++++------------------ .../platforms/wayland/qwaylandwindowsurface.cpp | 19 ++++++++++++ .../platforms/wayland/qwaylandwindowsurface.h | 2 ++ 3 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 9ac22e8..6842dbf 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -510,42 +510,21 @@ public: QPlatformWindowFormat platformWindowFormat() const { return mFormat; } private: - EGLContext mContext; QPlatformWindowFormat mFormat; QWaylandDisplay *mDisplay; QWaylandWindow *mWindow; - GLuint mFbo, mRbo; }; QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) : QPlatformGLContext() - , mContext(0) , mFormat(format) , mDisplay(wd) , mWindow(window) { - EGLDisplay eglDisplay; - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - eglBindAPI(EGL_OPENGL_ES_API); - eglDisplay = mDisplay->eglDisplay(); - mContext = eglCreateContext(eglDisplay, NULL, - EGL_NO_CONTEXT, contextAttribs); - eglMakeCurrent(eglDisplay, NULL, NULL, mContext); - - glGenFramebuffers(1, &mFbo); - glGenRenderbuffers(1, &mRbo); } QWaylandGLContext::~QWaylandGLContext() { - if (mContext) - eglDestroyContext(mDisplay->eglDisplay(), mContext); - glDeleteFramebuffers(1, &mFbo); - glDeleteRenderbuffers(1, &mRbo); } void QWaylandGLContext::makeCurrent() @@ -553,21 +532,20 @@ void QWaylandGLContext::makeCurrent() QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); QRect geometry = mWindow->geometry(); - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); if (!mBuffer) return; - glBindFramebuffer(GL_FRAMEBUFFER, mFbo); - glBindRenderbuffer(GL_RENDERBUFFER, mRbo); + + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); + + glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); + glBindRenderbuffer(GL_RENDERBUFFER, mBuffer->mRbo); glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, mRbo); + GL_RENDERBUFFER, mBuffer->mRbo); } void QWaylandGLContext::doneCurrent() { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); } void QWaylandGLContext::swapBuffers() diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 6e7fa89..4ae04be 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -201,6 +201,10 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, Q_UNUSED(format); EGLint name, stride; + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; EGLint imageAttribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, @@ -209,9 +213,16 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, EGL_NONE }; + eglBindAPI(EGL_OPENGL_ES_API); + mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + EGL_NO_CONTEXT, contextAttribs); + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); + imageAttribs[1] = size.width(); imageAttribs[3] = size.height(); mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + glGenFramebuffers(1, &mFbo); + glGenRenderbuffers(1, &mRbo); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); @@ -225,9 +236,12 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, QWaylandDrmBuffer::~QWaylandDrmBuffer(void) { + glDeleteFramebuffers(1, &mFbo); + glDeleteRenderbuffers(1, &mRbo); glDeleteTextures(1, &mTexture); eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); wl_buffer_destroy(mBuffer); + eglDestroyContext(mDisplay->eglDisplay(), mContext); } @@ -237,7 +251,12 @@ QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, , mBuffer(0) , mDisplay(display) { + QWaylandWindow *ww = (QWaylandWindow *) window->platformWindow(); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + mPaintDevice = new QWaylandPaintDevice(display, window); + mBuffer = new QWaylandDrmBuffer(mDisplay, window->size(), format); + ww->attach(mBuffer); } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index a033531..c8ccdb1 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -93,11 +93,13 @@ public: QWaylandDrmBuffer(QWaylandDisplay *display, const QSize &size, QImage::Format format); ~QWaylandDrmBuffer(); + EGLContext mContext; EGLImageKHR mImage; GLuint mTexture; QWaylandDisplay *mDisplay; QGLFramebufferObject *pdev; QSize mSize; + GLuint mFbo, mRbo; }; class QWaylandDrmWindowSurface : public QWindowSurface -- cgit v0.12 From 81e5d2db862cfaf58eb6394c9fe1968547926c78 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Wed, 27 Oct 2010 14:44:04 -0700 Subject: Wayland: render to a texture, not a renderbuffer This will let us source from offscreen GL widget surfaces and copy into the parent surface. --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 8 ++++---- src/plugins/platforms/wayland/qwaylandwindowsurface.cpp | 2 -- src/plugins/platforms/wayland/qwaylandwindowsurface.h | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 6842dbf..866a197 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -538,10 +538,10 @@ void QWaylandGLContext::makeCurrent() eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); - glBindRenderbuffer(GL_RENDERBUFFER, mBuffer->mRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, mBuffer->mRbo); + glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mBuffer->mTexture, 0); } void QWaylandGLContext::doneCurrent() diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp index 4ae04be..2374eac 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp @@ -222,7 +222,6 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, imageAttribs[3] = size.height(); mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); glGenFramebuffers(1, &mFbo); - glGenRenderbuffers(1, &mRbo); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); @@ -237,7 +236,6 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, QWaylandDrmBuffer::~QWaylandDrmBuffer(void) { glDeleteFramebuffers(1, &mFbo); - glDeleteRenderbuffers(1, &mRbo); glDeleteTextures(1, &mTexture); eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); wl_buffer_destroy(mBuffer); diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index c8ccdb1..eb9cc40 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -99,7 +99,7 @@ public: QWaylandDisplay *mDisplay; QGLFramebufferObject *pdev; QSize mSize; - GLuint mFbo, mRbo; + GLuint mFbo; }; class QWaylandDrmWindowSurface : public QWindowSurface -- cgit v0.12 From cbe7ab5f5da9c14fb6acef3f6d29b319ec2dcc4a Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Wed, 27 Oct 2010 14:49:16 -0700 Subject: Wayland: set parent window pointer in setParent() We'll need this to handle GL widgets. --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 3 +-- src/plugins/platforms/wayland/qwaylandintegration.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 866a197..29cd0ee 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -460,8 +460,7 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent) { QWaylandWindow *wParent = (QWaylandWindow *)parent; - mSurface = wParent->surface(); - wParent->attach(mBuffer); + mParentWindow = wParent; } void QWaylandWindow::setVisible(bool visible) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index e26f9e3..e65c141 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -158,6 +158,7 @@ public: QPlatformGLContext *glContext() const; void attach(QWaylandBuffer *buffer); QWaylandBuffer *getBuffer(void) { return mBuffer; } + QWaylandWindow *getParentWindow(void) { return mParentWindow; } private: struct wl_surface *mSurface; @@ -166,6 +167,7 @@ private: WId mWindowId; QWaylandBuffer *mBuffer; + QWaylandWindow *mParentWindow; }; class QWaylandIntegration : public QPlatformIntegration -- cgit v0.12 From 4a3d4dcdcf2782530c76a6aff4775ec5f8ebd157 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Wed, 27 Oct 2010 15:01:38 -0700 Subject: Wayland: add GL widget support Make sure we copy from the private surface into the parent surface at swapBuffers time. --- .../platforms/wayland/qwaylandintegration.cpp | 99 +++++++++++++++++++++- .../platforms/wayland/qwaylandwindowsurface.h | 1 - 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 29cd0ee..a3237fb 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -17,6 +17,7 @@ #include <private/qwindowsurface_gl_p.h> #include <private/qpixmapdata_gl_p.h> +#include <private/qpaintengineex_opengl2_p.h> #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" @@ -547,14 +548,106 @@ void QWaylandGLContext::doneCurrent() { } +static void drawTexture(const QRectF &rect, GLuint tex_id, + const QSize &texSize, const QRectF &br) +{ + QRectF src = br.isEmpty() + ? QRectF(QPointF(), texSize) + : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); + qreal width = texSize.width(); + qreal height = texSize.height(); + + src.setLeft(src.left() / width); + src.setRight(src.right() / width); + src.setTop(src.top() / height); + src.setBottom(src.bottom() / height); + + const GLfloat tx1 = src.left(); + const GLfloat tx2 = src.right(); + const GLfloat ty1 = src.top(); + const GLfloat ty2 = src.bottom(); + + GLfloat texCoordArray[4*2] = { + tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 + }; + + GLfloat vertexArray[4*2]; + extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); + qt_add_rect_to_array(rect, vertexArray); + + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); + + glBindTexture(GL_TEXTURE_2D, tex_id); + + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + + glBindTexture(GL_TEXTURE_2D, 0); +} + void QWaylandGLContext::swapBuffers() { - QRect geometry = mWindow->geometry(); + QWaylandWindow *mParentWindow = mWindow->getParentWindow(); + QWaylandDrmBuffer *mBuffer, *mParentBuffer; + QRect geometry = mWindow->geometry(), parentGeometry; + GLuint parentFbo, parentRbo; - if (!mWindow->surface()) + if (!mParentWindow) { + qDebug("swap without parent widget?\n"); return; + } + + if (!mParentWindow->surface()) { + qDebug("parent has no surface??\n"); + return; + } + + parentGeometry = mParentWindow->geometry(); + mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); + + qDebug("copying from texture image %d, texture %d to image %d, texture %d\n", + mBuffer->mImage, mBuffer->mTexture, mParentBuffer->mImage, mParentBuffer->mTexture); + + glDisable(GL_DEPTH_TEST); + + glGenFramebuffers(1, &parentFbo); + glGenRenderbuffers(1, &parentRbo); + glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); + glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mParentBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, parentRbo); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); + glViewport(0, 0, geometry.width(), geometry.height()); + + QGLShaderProgram *blitProgram = + QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); + blitProgram->bind(); + blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); + // The shader manager's blit program does not multiply the + // vertices by the pmv matrix, so we need to do the effect + // of the orthographic projection here ourselves. + QRectF r; + qreal w = geometry.width() ? geometry.width() : 1.0f; + qreal h = geometry.height() ? geometry.height() : 1.0f; + r.setLeft((geometry.left() / w) * 2.0f - 1.0f); + if (geometry.right() == (geometry.width() - 1)) + r.setRight(1.0f); + else + r.setRight((geometry.right() / w) * 2.0f - 1.0f); + r.setBottom((geometry.top() / h) * 2.0f - 1.0f); + if (geometry.bottom() == (geometry.height() - 1)) + r.setTop(1.0f); + else + r.setTop((geometry.bottom() / w) * 2.0f - 1.0f); + drawTexture(r, mBuffer->mTexture, mWindow->widget()->size(), geometry); - wl_surface_damage(mWindow->surface(), 0, 0, + wl_surface_damage(mParentWindow->surface(), 0, 0, geometry.width(), geometry.height()); } diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index eb9cc40..21c48f9 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -97,7 +97,6 @@ public: EGLImageKHR mImage; GLuint mTexture; QWaylandDisplay *mDisplay; - QGLFramebufferObject *pdev; QSize mSize; GLuint mFbo; }; -- cgit v0.12 From adbcd0f749e7ce8d7a95ed919e0a37fa5b219f06 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Thu, 28 Oct 2010 11:13:13 -0700 Subject: Wayland: clean up swapBuffers code Pull the swap fbo and rbo into the context and make sure to destroy them when the context goes away. Add unfortunate lazy allocation of the fbo and rbo because we need them to be part of the right context. --- .../platforms/wayland/qwaylandintegration.cpp | 38 ++++++++++++++-------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index a3237fb..879fd73 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -513,6 +513,7 @@ private: QPlatformWindowFormat mFormat; QWaylandDisplay *mDisplay; QWaylandWindow *mWindow; + GLuint parentFbo, parentRbo; }; QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) @@ -520,11 +521,15 @@ QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window , mFormat(format) , mDisplay(wd) , mWindow(window) + , parentFbo(0) + , parentRbo(0) { } QWaylandGLContext::~QWaylandGLContext() { + glDeleteRenderbuffers(1, &parentRbo); + glDeleteFramebuffers(1, &parentFbo); } void QWaylandGLContext::makeCurrent() @@ -594,7 +599,10 @@ void QWaylandGLContext::swapBuffers() QWaylandWindow *mParentWindow = mWindow->getParentWindow(); QWaylandDrmBuffer *mBuffer, *mParentBuffer; QRect geometry = mWindow->geometry(), parentGeometry; - GLuint parentFbo, parentRbo; + QGLShaderProgram *blitProgram; + QRectF r; + qreal w; + qreal h; if (!mParentWindow) { qDebug("swap without parent widget?\n"); @@ -610,31 +618,33 @@ void QWaylandGLContext::swapBuffers() mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); - qDebug("copying from texture image %d, texture %d to image %d, texture %d\n", - mBuffer->mImage, mBuffer->mTexture, mParentBuffer->mImage, mParentBuffer->mTexture); - glDisable(GL_DEPTH_TEST); - glGenFramebuffers(1, &parentFbo); - glGenRenderbuffers(1, &parentRbo); + w = geometry.width() ? geometry.width() : 1.0f; + h = geometry.height() ? geometry.height() : 1.0f; + + /* These need to be generated against the src context */ + if (!parentFbo) + glGenFramebuffers(1, &parentFbo); + if (!parentRbo) + glGenRenderbuffers(1, &parentRbo); + glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, mParentBuffer->mImage); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, + mParentBuffer->mImage); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, parentRbo); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); glViewport(0, 0, geometry.width(), geometry.height()); - QGLShaderProgram *blitProgram = - QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); + blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); + blitProgram->setUniformValue("imageTexture", 0); + // The shader manager's blit program does not multiply the // vertices by the pmv matrix, so we need to do the effect // of the orthographic projection here ourselves. - QRectF r; - qreal w = geometry.width() ? geometry.width() : 1.0f; - qreal h = geometry.height() ? geometry.height() : 1.0f; r.setLeft((geometry.left() / w) * 2.0f - 1.0f); if (geometry.right() == (geometry.width() - 1)) r.setRight(1.0f); @@ -649,6 +659,8 @@ void QWaylandGLContext::swapBuffers() wl_surface_damage(mParentWindow->surface(), 0, 0, geometry.width(), geometry.height()); + /* restore things to the last valid GL state */ + makeCurrent(); } void *QWaylandGLContext::getProcAddress(const QString &string) -- cgit v0.12 From b026c22b06647dadbe76943fe174e57f82ac2b50 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Thu, 28 Oct 2010 11:15:04 -0700 Subject: Wayland: fix geometry of swapBuffers If the geometry isn't mapped 1:1 we need to divide the bottom by height, not width, to calculate the texture rectangle. --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 879fd73..4767f56 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -654,7 +654,8 @@ void QWaylandGLContext::swapBuffers() if (geometry.bottom() == (geometry.height() - 1)) r.setTop(1.0f); else - r.setTop((geometry.bottom() / w) * 2.0f - 1.0f); + r.setTop((geometry.bottom() / h) * 2.0f - 1.0f); + drawTexture(r, mBuffer->mTexture, mWindow->widget()->size(), geometry); wl_surface_damage(mParentWindow->surface(), 0, 0, -- cgit v0.12 From 513f396c7a888473a32cf212f1ce969fe38fdf2e Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Thu, 28 Oct 2010 16:18:15 -0700 Subject: Wayland: use correct viewport for swapBuffers and correct coords We're drawing into the parent, so we need to use the parent's geometry for the GL viewport, or we may not be able to draw it. We also need to use the parent width & height when checking whether to normalize to 1.0 or -1.0 in the coord transform calculations. --- .../platforms/wayland/qwaylandintegration.cpp | 43 ++++++++++++++-------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 4767f56..b8b7c2f 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -542,6 +542,7 @@ void QWaylandGLContext::makeCurrent() eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); + glViewport(0, 0, geometry.width(), geometry.height()); glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); @@ -553,6 +554,12 @@ void QWaylandGLContext::doneCurrent() { } +/* drawTexture - Draw from a texture into a the current framebuffer + * @rect: GL normalized coords for drawing (between -1.0f and 1.0f) + * @tex_id: texture source + * @texSize: size of source rectangle in Qt coords + * @br: bounding rect for drawing + */ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) { @@ -585,6 +592,11 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, glBindTexture(GL_TEXTURE_2D, tex_id); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -620,9 +632,6 @@ void QWaylandGLContext::swapBuffers() glDisable(GL_DEPTH_TEST); - w = geometry.width() ? geometry.width() : 1.0f; - h = geometry.height() ? geometry.height() : 1.0f; - /* These need to be generated against the src context */ if (!parentFbo) glGenFramebuffers(1, &parentFbo); @@ -636,32 +645,36 @@ void QWaylandGLContext::swapBuffers() glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, parentRbo); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glViewport(0, 0, geometry.width(), geometry.height()); + glViewport(0, 0, parentGeometry.width(), parentGeometry.height()); blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); blitProgram->bind(); blitProgram->setUniformValue("imageTexture", 0); - // The shader manager's blit program does not multiply the - // vertices by the pmv matrix, so we need to do the effect - // of the orthographic projection here ourselves. + /* Transform the target rect to the appropriate coords on the parent */ + w = parentGeometry.width(); + h = parentGeometry.height(); + r.setLeft((geometry.left() / w) * 2.0f - 1.0f); - if (geometry.right() == (geometry.width() - 1)) + if (geometry.right() == (parentGeometry.width() - 1)) r.setRight(1.0f); else r.setRight((geometry.right() / w) * 2.0f - 1.0f); - r.setBottom((geometry.top() / h) * 2.0f - 1.0f); - if (geometry.bottom() == (geometry.height() - 1)) - r.setTop(1.0f); + + r.setTop((geometry.top() / h) * 2.0f - 1.0f); + if (geometry.bottom() == (parentGeometry.height() - 1)) + r.setBottom(-1.0f); else - r.setTop((geometry.bottom() / h) * 2.0f - 1.0f); + r.setBottom((geometry.bottom() / h) * 2.0f - 1.0f); - drawTexture(r, mBuffer->mTexture, mWindow->widget()->size(), geometry); + drawTexture(r, mBuffer->mTexture, mParentWindow->widget()->size(), parentGeometry); - wl_surface_damage(mParentWindow->surface(), 0, 0, - geometry.width(), geometry.height()); + wl_surface_damage(mParentWindow->surface(), geometry.left(), geometry.top(), + geometry.right(), geometry.bottom()); /* restore things to the last valid GL state */ makeCurrent(); + /* hack: avoid tight swapBuffers loops */ + usleep(20000); } void *QWaylandGLContext::getProcAddress(const QString &string) -- cgit v0.12 From f3bb98a1fa89a505ae3015977840ddbe2219ab5a Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 8 Nov 2010 12:24:09 -0800 Subject: Wayland: split GL code into separate files For clarity and to prevent merge conflicts etc. in future. --- .../platforms/wayland/qwaylanddrmsurface.cpp | 216 +++++++++++++++ .../platforms/wayland/qwaylandglcontext.cpp | 207 ++++++++++++++ .../platforms/wayland/qwaylandintegration.cpp | 202 -------------- .../platforms/wayland/qwaylandintegration.h | 21 ++ .../platforms/wayland/qwaylandshmsurface.cpp | 142 ++++++++++ .../platforms/wayland/qwaylandwindowsurface.cpp | 302 --------------------- src/plugins/platforms/wayland/wayland.pro | 6 +- 7 files changed, 590 insertions(+), 506 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylanddrmsurface.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandglcontext.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandshmsurface.cpp delete mode 100644 src/plugins/platforms/wayland/qwaylandwindowsurface.cpp diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp new file mode 100644 index 0000000..c9fb187 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <QGLFramebufferObject> +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +class QWaylandPaintDevice : public QGLPaintDevice +{ +public: + QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) + : QGLPaintDevice(), mDisplay(display), mWidget(widget) + { + QGLFormat format; + mContext = new QGLContext(format, widget); + mContext->create(); + } + + QSize size() const { return mWidget->size(); } + QGLContext *context() const { return mContext; } + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + + void beginPaint(); + void endPaint(); +private: + QWaylandDisplay *mDisplay; + QWidget *mWidget; + QGLContext *mContext; +}; + +void QWaylandPaintDevice::beginPaint(void) +{ + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + + QGLPaintDevice::beginPaint(); + + ctx->makeCurrent(); +} + +void QWaylandPaintDevice::endPaint(void) +{ + QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); + QPlatformGLContext *ctx = mWindow->glContext(); + QRect geometry = mWidget->geometry(); + + ctx->doneCurrent(); + + QGLPaintDevice::endPaint(); +} + +/* + * Shared DRM surface for GL based drawing + */ +QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) + : mDisplay(display) + , mSize(size) +{ + Q_UNUSED(format); + + EGLint name, stride; + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + EGLint imageAttribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + EGL_NO_CONTEXT, contextAttribs); + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); + + imageAttribs[1] = size.width(); + imageAttribs[3] = size.height(); + mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + glGenFramebuffers(1, &mFbo); + glGenTextures(1, &mTexture); + glBindTexture(GL_TEXTURE_2D, mTexture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + + eglExportDRMImageMESA(mDisplay->eglDisplay(), + mImage, &name, NULL, &stride); + + mBuffer = display->createDrmBuffer(name, size.width(), size.height(), + stride, display->argbVisual()); +} + +QWaylandDrmBuffer::~QWaylandDrmBuffer(void) +{ + glDeleteFramebuffers(1, &mFbo); + glDeleteTextures(1, &mTexture); + eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); + wl_buffer_destroy(mBuffer); + eglDestroyContext(mDisplay->eglDisplay(), mContext); +} + + +QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, + QWaylandDisplay *display) + : QWindowSurface(window) + , mBuffer(0) + , mDisplay(display) +{ + QWaylandWindow *ww = (QWaylandWindow *) window->platformWindow(); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + mPaintDevice = new QWaylandPaintDevice(display, window); + mBuffer = new QWaylandDrmBuffer(mDisplay, window->size(), format); + ww->attach(mBuffer); +} + +QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() +{ + delete mPaintDevice; +} + +QPaintDevice *QWaylandDrmWindowSurface::paintDevice() +{ + return mPaintDevice; +} + +void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; + + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } +} + +void QWaylandDrmWindowSurface::resize(const QSize &size) +{ + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mBuffer != NULL && mBuffer->mSize == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp new file mode 100644 index 0000000..264da2e --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -0,0 +1,207 @@ +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "qfontconfigdatabase.h" + +#include <QImageReader> +#include <QWindowSystemInterface> +#include <QPlatformCursor> +#include <QPaintEngine> + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <private/qwindowsurface_gl_p.h> +#include <private/qpixmapdata_gl_p.h> +#include <private/qpaintengineex_opengl2_p.h> + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" + +#include <unistd.h> +#include <fcntl.h> + +extern "C" { +#include <xf86drm.h> +} + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , mFormat(format) + , mDisplay(wd) + , mWindow(window) + , parentFbo(0) + , parentRbo(0) +{ +} + +QWaylandGLContext::~QWaylandGLContext() +{ + glDeleteRenderbuffers(1, &parentRbo); + glDeleteFramebuffers(1, &parentFbo); +} + +void QWaylandGLContext::makeCurrent() +{ + QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + QRect geometry = mWindow->geometry(); + + if (!mBuffer) + return; + + eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); + + glViewport(0, 0, geometry.width(), geometry.height()); + glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); + glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mBuffer->mTexture, 0); +} + +void QWaylandGLContext::doneCurrent() +{ +} + +/* drawTexture - Draw from a texture into a the current framebuffer + * @rect: GL normalized coords for drawing (between -1.0f and 1.0f) + * @tex_id: texture source + * @texSize: size of source rectangle in Qt coords + * @br: bounding rect for drawing + */ +static void drawTexture(const QRectF &rect, GLuint tex_id, + const QSize &texSize, const QRectF &br) +{ + QRectF src = br.isEmpty() + ? QRectF(QPointF(), texSize) + : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); + qreal width = texSize.width(); + qreal height = texSize.height(); + + src.setLeft(src.left() / width); + src.setRight(src.right() / width); + src.setTop(src.top() / height); + src.setBottom(src.bottom() / height); + + const GLfloat tx1 = src.left(); + const GLfloat tx2 = src.right(); + const GLfloat ty1 = src.top(); + const GLfloat ty2 = src.bottom(); + + GLfloat texCoordArray[4*2] = { + tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 + }; + + GLfloat vertexArray[4*2]; + extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); + qt_add_rect_to_array(rect, vertexArray); + + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); + + glBindTexture(GL_TEXTURE_2D, tex_id); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + + glBindTexture(GL_TEXTURE_2D, 0); +} + +void QWaylandGLContext::swapBuffers() +{ + QWaylandWindow *mParentWindow = mWindow->getParentWindow(); + QWaylandDrmBuffer *mBuffer, *mParentBuffer; + QRect geometry = mWindow->geometry(), parentGeometry; + QGLShaderProgram *blitProgram; + QRectF r; + qreal w; + qreal h; + + if (!mParentWindow) { + qDebug("swap without parent widget?\n"); + return; + } + + if (!mParentWindow->surface()) { + qDebug("parent has no surface??\n"); + return; + } + + parentGeometry = mParentWindow->geometry(); + mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); + mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); + + glDisable(GL_DEPTH_TEST); + + /* These need to be generated against the src context */ + if (!parentFbo) + glGenFramebuffers(1, &parentFbo); + if (!parentRbo) + glGenRenderbuffers(1, &parentRbo); + + glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); + glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, + mParentBuffer->mImage); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, parentRbo); + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); + glViewport(0, 0, parentGeometry.width(), parentGeometry.height()); + + blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); + blitProgram->bind(); + blitProgram->setUniformValue("imageTexture", 0); + + /* Transform the target rect to the appropriate coords on the parent */ + w = parentGeometry.width(); + h = parentGeometry.height(); + + r.setLeft((geometry.left() / w) * 2.0f - 1.0f); + if (geometry.right() == (parentGeometry.width() - 1)) + r.setRight(1.0f); + else + r.setRight((geometry.right() / w) * 2.0f - 1.0f); + + r.setTop((geometry.top() / h) * 2.0f - 1.0f); + if (geometry.bottom() == (parentGeometry.height() - 1)) + r.setBottom(-1.0f); + else + r.setBottom((geometry.bottom() / h) * 2.0f - 1.0f); + + drawTexture(r, mBuffer->mTexture, mParentWindow->widget()->size(), parentGeometry); + + wl_surface_damage(mParentWindow->surface(), geometry.left(), geometry.top(), + geometry.right(), geometry.bottom()); + /* restore things to the last valid GL state */ + makeCurrent(); + /* hack: avoid tight swapBuffers loops */ + usleep(20000); +} + +void *QWaylandGLContext::getProcAddress(const QString &string) +{ + return (void *) eglGetProcAddress(string.toLatin1().data()); +} + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast<QWaylandWindow *>(this); + that->mGLContext = new QWaylandGLContext(mDisplay, that, widget()->platformWindowFormat()); + } + + return mGLContext; +} + diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index b8b7c2f..0109678 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,7 +1,3 @@ -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - #include "qfontconfigdatabase.h" #include <QImageReader> @@ -9,16 +5,11 @@ #include <QPlatformCursor> #include <QPaintEngine> -#include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> -#include <private/qwindowsurface_gl_p.h> -#include <private/qpixmapdata_gl_p.h> -#include <private/qpaintengineex_opengl2_p.h> - #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" @@ -499,199 +490,6 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } -class QWaylandGLContext : public QPlatformGLContext { -public: - QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); - ~QWaylandGLContext(); - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString&); - QPlatformWindowFormat platformWindowFormat() const { return mFormat; } - -private: - QPlatformWindowFormat mFormat; - QWaylandDisplay *mDisplay; - QWaylandWindow *mWindow; - GLuint parentFbo, parentRbo; -}; - -QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) - : QPlatformGLContext() - , mFormat(format) - , mDisplay(wd) - , mWindow(window) - , parentFbo(0) - , parentRbo(0) -{ -} - -QWaylandGLContext::~QWaylandGLContext() -{ - glDeleteRenderbuffers(1, &parentRbo); - glDeleteFramebuffers(1, &parentFbo); -} - -void QWaylandGLContext::makeCurrent() -{ - QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - QRect geometry = mWindow->geometry(); - - if (!mBuffer) - return; - - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); - - glViewport(0, 0, geometry.width(), geometry.height()); - glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); - glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, mBuffer->mTexture, 0); -} - -void QWaylandGLContext::doneCurrent() -{ -} - -/* drawTexture - Draw from a texture into a the current framebuffer - * @rect: GL normalized coords for drawing (between -1.0f and 1.0f) - * @tex_id: texture source - * @texSize: size of source rectangle in Qt coords - * @br: bounding rect for drawing - */ -static void drawTexture(const QRectF &rect, GLuint tex_id, - const QSize &texSize, const QRectF &br) -{ - QRectF src = br.isEmpty() - ? QRectF(QPointF(), texSize) - : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); - qreal width = texSize.width(); - qreal height = texSize.height(); - - src.setLeft(src.left() / width); - src.setRight(src.right() / width); - src.setTop(src.top() / height); - src.setBottom(src.bottom() / height); - - const GLfloat tx1 = src.left(); - const GLfloat tx2 = src.right(); - const GLfloat ty1 = src.top(); - const GLfloat ty2 = src.bottom(); - - GLfloat texCoordArray[4*2] = { - tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 - }; - - GLfloat vertexArray[4*2]; - extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); - qt_add_rect_to_array(rect, vertexArray); - - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); - - glBindTexture(GL_TEXTURE_2D, tex_id); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - - glBindTexture(GL_TEXTURE_2D, 0); -} - -void QWaylandGLContext::swapBuffers() -{ - QWaylandWindow *mParentWindow = mWindow->getParentWindow(); - QWaylandDrmBuffer *mBuffer, *mParentBuffer; - QRect geometry = mWindow->geometry(), parentGeometry; - QGLShaderProgram *blitProgram; - QRectF r; - qreal w; - qreal h; - - if (!mParentWindow) { - qDebug("swap without parent widget?\n"); - return; - } - - if (!mParentWindow->surface()) { - qDebug("parent has no surface??\n"); - return; - } - - parentGeometry = mParentWindow->geometry(); - mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); - - glDisable(GL_DEPTH_TEST); - - /* These need to be generated against the src context */ - if (!parentFbo) - glGenFramebuffers(1, &parentFbo); - if (!parentRbo) - glGenRenderbuffers(1, &parentRbo); - - glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); - glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - mParentBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, parentRbo); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glViewport(0, 0, parentGeometry.width(), parentGeometry.height()); - - blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); - blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0); - - /* Transform the target rect to the appropriate coords on the parent */ - w = parentGeometry.width(); - h = parentGeometry.height(); - - r.setLeft((geometry.left() / w) * 2.0f - 1.0f); - if (geometry.right() == (parentGeometry.width() - 1)) - r.setRight(1.0f); - else - r.setRight((geometry.right() / w) * 2.0f - 1.0f); - - r.setTop((geometry.top() / h) * 2.0f - 1.0f); - if (geometry.bottom() == (parentGeometry.height() - 1)) - r.setBottom(-1.0f); - else - r.setBottom((geometry.bottom() / h) * 2.0f - 1.0f); - - drawTexture(r, mBuffer->mTexture, mParentWindow->widget()->size(), parentGeometry); - - wl_surface_damage(mParentWindow->surface(), geometry.left(), geometry.top(), - geometry.right(), geometry.bottom()); - /* restore things to the last valid GL state */ - makeCurrent(); - /* hack: avoid tight swapBuffers loops */ - usleep(20000); -} - -void *QWaylandGLContext::getProcAddress(const QString &string) -{ - return (void *) eglGetProcAddress(string.toLatin1().data()); -} - -QPlatformGLContext *QWaylandWindow::glContext() const -{ - if (!mGLContext) { - QWaylandWindow *that = const_cast<QWaylandWindow *>(this); - that->mGLContext = new QWaylandGLContext(mDisplay, that, widget()->platformWindowFormat()); - } - - return mGLContext; -} - QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index e65c141..1c5f834 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -46,8 +46,12 @@ #include <QObject> #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> #include "qgl.h" +#include <private/qpixmapdata_gl_p.h> + #include <wayland-client.h> #include "qwaylandinputdevice.h" @@ -189,6 +193,23 @@ private: bool mUseOpenGL; }; +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + +private: + QPlatformWindowFormat mFormat; + QWaylandDisplay *mDisplay; + QWaylandWindow *mWindow; + GLuint parentFbo, parentRbo; +}; + QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp new file mode 100644 index 0000000..004b93a --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) +{ + int stride = size.width() * 4; + int alloc = stride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + uchar *data = (uchar *) + mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == (uchar *) MAP_FAILED) { + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + close(fd); + return; + } + + mImage = QImage(data, size.width(), size.height(), stride, format); + mBuffer = display->createShmBuffer(fd, size.width(), size.height(), + stride, display->argbVisual()); + close(fd); +} + +QWaylandShmBuffer::~QWaylandShmBuffer(void) +{ + munmap((void *) mImage.constBits(), mImage.byteCount()); + wl_buffer_destroy(mBuffer); +} + +QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window, + QWaylandDisplay *display) + : QWindowSurface(window) + , mBuffer(0) + , mDisplay(display) +{ +} + +QWaylandShmWindowSurface::~QWaylandShmWindowSurface() +{ +} + +QPaintDevice *QWaylandShmWindowSurface::paintDevice() +{ + return &mBuffer->mImage; +} + +void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QVector<QRect> rects = region.rects(); + const QRect *r; + int i; + + for (i = 0; i < rects.size(); i++) { + r = &rects.at(i); + wl_surface_damage(ww->surface(), + r->x(), r->y(), r->width(), r->height()); + } +} + +void QWaylandShmWindowSurface::resize(const QSize &size) +{ + QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + + if (mBuffer != NULL && mBuffer->mImage.size() == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, size, format); + + ww->attach(mBuffer); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp b/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp deleted file mode 100644 index 2374eac..0000000 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenVG module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <QGLFramebufferObject> -#include <QtCore/qdebug.h> -#include <QtGui/private/qapplication_p.h> -#include <QtOpenGL/private/qgl_p.h> -#include <QtOpenGL/private/qglpaintdevice_p.h> - -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" - -#include <wayland-client.h> -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mman.h> - -QT_BEGIN_NAMESPACE - -QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format) -{ - int stride = size.width() * 4; - int alloc = stride * size.height(); - char filename[] = "/tmp/wayland-shm-XXXXXX"; - int fd = mkstemp(filename); - if (fd < 0) - qWarning("open %s failed: %s", filename, strerror(errno)); - if (ftruncate(fd, alloc) < 0) { - qWarning("ftruncate failed: %s", strerror(errno)); - close(fd); - return; - } - uchar *data = (uchar *) - mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - unlink(filename); - - if (data == (uchar *) MAP_FAILED) { - qWarning("mmap /dev/zero failed: %s", strerror(errno)); - close(fd); - return; - } - - mImage = QImage(data, size.width(), size.height(), stride, format); - mBuffer = display->createShmBuffer(fd, size.width(), size.height(), - stride, display->argbVisual()); - close(fd); -} - -QWaylandShmBuffer::~QWaylandShmBuffer(void) -{ - munmap((void *) mImage.constBits(), mImage.byteCount()); - wl_buffer_destroy(mBuffer); -} - -QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window, - QWaylandDisplay *display) - : QWindowSurface(window) - , mBuffer(0) - , mDisplay(display) -{ -} - -QWaylandShmWindowSurface::~QWaylandShmWindowSurface() -{ -} - -QPaintDevice *QWaylandShmWindowSurface::paintDevice() -{ - return &mBuffer->mImage; -} - -void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) -{ - Q_UNUSED(widget); - Q_UNUSED(offset); - QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QVector<QRect> rects = region.rects(); - const QRect *r; - int i; - - for (i = 0; i < rects.size(); i++) { - r = &rects.at(i); - wl_surface_damage(ww->surface(), - r->x(), r->y(), r->width(), r->height()); - } -} - -void QWaylandShmWindowSurface::resize(const QSize &size) -{ - QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QWindowSurface::resize(size); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - - if (mBuffer != NULL && mBuffer->mImage.size() == size) - return; - - if (mBuffer != NULL) - delete mBuffer; - - mBuffer = new QWaylandShmBuffer(mDisplay, size, format); - - ww->attach(mBuffer); -} - -class QWaylandPaintDevice : public QGLPaintDevice -{ -public: - QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) - : QGLPaintDevice(), mDisplay(display), mWidget(widget) - { - QGLFormat format; - mContext = new QGLContext(format, widget); - mContext->create(); - } - - QSize size() const { return mWidget->size(); } - QGLContext *context() const { return mContext; } - QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } - - void beginPaint(); - void endPaint(); -private: - QWaylandDisplay *mDisplay; - QWidget *mWidget; - QGLContext *mContext; -}; - -void QWaylandPaintDevice::beginPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); - - QGLPaintDevice::beginPaint(); - - ctx->makeCurrent(); -} - -void QWaylandPaintDevice::endPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); - QRect geometry = mWidget->geometry(); - - ctx->doneCurrent(); - - QGLPaintDevice::endPaint(); -} - -/* - * Shared DRM surface for GL based drawing - */ -QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format) - : mDisplay(display) - , mSize(size) -{ - Q_UNUSED(format); - - EGLint name, stride; - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - EGLint imageAttribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, - EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, - EGL_NONE - }; - - eglBindAPI(EGL_OPENGL_ES_API); - mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, - EGL_NO_CONTEXT, contextAttribs); - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); - - imageAttribs[1] = size.width(); - imageAttribs[3] = size.height(); - mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); - glGenFramebuffers(1, &mFbo); - glGenTextures(1, &mTexture); - glBindTexture(GL_TEXTURE_2D, mTexture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); - - eglExportDRMImageMESA(mDisplay->eglDisplay(), - mImage, &name, NULL, &stride); - - mBuffer = display->createDrmBuffer(name, size.width(), size.height(), - stride, display->argbVisual()); -} - -QWaylandDrmBuffer::~QWaylandDrmBuffer(void) -{ - glDeleteFramebuffers(1, &mFbo); - glDeleteTextures(1, &mTexture); - eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); - wl_buffer_destroy(mBuffer); - eglDestroyContext(mDisplay->eglDisplay(), mContext); -} - - -QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, - QWaylandDisplay *display) - : QWindowSurface(window) - , mBuffer(0) - , mDisplay(display) -{ - QWaylandWindow *ww = (QWaylandWindow *) window->platformWindow(); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - - mPaintDevice = new QWaylandPaintDevice(display, window); - mBuffer = new QWaylandDrmBuffer(mDisplay, window->size(), format); - ww->attach(mBuffer); -} - -QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() -{ - delete mPaintDevice; -} - -QPaintDevice *QWaylandDrmWindowSurface::paintDevice() -{ - return mPaintDevice; -} - -void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) -{ - Q_UNUSED(offset); - QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); - QVector<QRect> rects = region.rects(); - const QRect *r; - int i; - - for (i = 0; i < rects.size(); i++) { - r = &rects.at(i); - wl_surface_damage(ww->surface(), - r->x(), r->y(), r->width(), r->height()); - } -} - -void QWaylandDrmWindowSurface::resize(const QSize &size) -{ - QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QWindowSurface::resize(size); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - - if (mBuffer != NULL && mBuffer->mSize == size) - return; - - if (mBuffer != NULL) - delete mBuffer; - - mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); - - ww->attach(mBuffer); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index ec3f9d3..b0cb98b 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -5,8 +5,10 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms SOURCES = main.cpp \ qwaylandintegration.cpp \ - qwaylandwindowsurface.cpp \ - qwaylandinputdevice.cpp + qwaylandshmsurface.cpp \ + qwaylanddrmsurface.cpp \ + qwaylandinputdevice.cpp \ + qwaylandglcontext.cpp HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h -- cgit v0.12 From aba46c644461616a2b14fc422efba74d5c44d017 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Mon, 8 Nov 2010 13:05:19 -0800 Subject: Wayland: clamp window resizes to screen size --- src/plugins/platforms/wayland/qwaylanddrmsurface.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index c9fb187..7756e85 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -196,11 +196,13 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con } } -void QWaylandDrmWindowSurface::resize(const QSize &size) +void QWaylandDrmWindowSurface::resize(const QSize &requestedSize) { QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QWindowSurface::resize(size); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + QWaylandScreen *screen = (QWaylandScreen *)QApplicationPrivate::platformIntegration()->screens().first(); + QImage::Format format = screen->format(); + QSize screenSize = screen->geometry().size(); + QSize size = requestedSize; if (mBuffer != NULL && mBuffer->mSize == size) return; @@ -208,6 +210,14 @@ void QWaylandDrmWindowSurface::resize(const QSize &size) if (mBuffer != NULL) delete mBuffer; + /* Clamp to screen size */ + if (size.width() > screenSize.width()) + size.setWidth(screenSize.width()); + if (size.height() > screenSize.height()) + size.setHeight(screenSize.height()); + + QWindowSurface::resize(size); + mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); ww->attach(mBuffer); -- cgit v0.12 From 73a2833abc1c9e9d5d3abe461e2ce9196bcb2a74 Mon Sep 17 00:00:00 2001 From: Jesse Barnes <jbarnes@virtuousgeek.org> Date: Tue, 9 Nov 2010 12:44:18 -0800 Subject: Wayland: request rbg and premultiplied argb visuals as needed When creating DRM buffers we should try to match the visual type requested with the buffer format. --- src/plugins/platforms/wayland/qwaylanddrmsurface.cpp | 17 +++++++++++++++-- src/plugins/platforms/wayland/qwaylandintegration.cpp | 10 ++++++++++ src/plugins/platforms/wayland/qwaylandintegration.h | 3 ++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index 7756e85..cb4445c 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -112,7 +112,7 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, : mDisplay(display) , mSize(size) { - Q_UNUSED(format); + struct wl_visual *visual; EGLint name, stride; static const EGLint contextAttribs[] = { @@ -143,8 +143,21 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, eglExportDRMImageMESA(mDisplay->eglDisplay(), mImage, &name, NULL, &stride); + switch (format) { + case QImage::Format_ARGB32: + visual = display->argbVisual(); + break; + case QImage::Format_ARGB32_Premultiplied: + visual = display->argbPremultipliedVisual(); + break; + default: + qDebug("unsupported buffer format %d requested\n", format); + visual = display->argbVisual(); + break; + } + mBuffer = display->createDrmBuffer(name, size.width(), size.height(), - stride, display->argbVisual()); + stride, visual); } QWaylandDrmBuffer::~QWaylandDrmBuffer(void) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 0109678..19f339a 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -185,11 +185,21 @@ struct wl_buffer *QWaylandDisplay::createDrmBuffer(int name, return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); } +struct wl_visual *QWaylandDisplay::rgbVisual() +{ + return wl_display_get_rgb_visual(mDisplay); +} + struct wl_visual *QWaylandDisplay::argbVisual() { return wl_display_get_argb_visual(mDisplay); } +struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() +{ + return wl_display_get_premultiplied_argb_visual(mDisplay); +} + void QWaylandDisplay::drmHandleDevice(void *data, struct wl_drm *drm, const char *device) { diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 1c5f834..611ce43 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -79,8 +79,9 @@ public: struct wl_buffer *createDrmBuffer(int name, int width, int height, uint32_t stride, struct wl_visual *visual); - + struct wl_visual *rgbVisual(); struct wl_visual *argbVisual(); + struct wl_visual *argbPremultipliedVisual(); EGLDisplay eglDisplay() { return mEglDisplay; } void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); -- cgit v0.12 From 53d2a41e3afd86a8571de40ff91b00d4f11a111a Mon Sep 17 00:00:00 2001 From: Benjamin Franzke <benjaminfranzke@googlemail.com> Date: Sun, 21 Nov 2010 14:14:30 +0100 Subject: wayland: fix SOURCES to point to wayland.cpp in config.tests --- config.tests/qpa/wayland/wayland.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.tests/qpa/wayland/wayland.pro b/config.tests/qpa/wayland/wayland.pro index 83f5efe..266e4d6 100644 --- a/config.tests/qpa/wayland/wayland.pro +++ b/config.tests/qpa/wayland/wayland.pro @@ -1,4 +1,4 @@ -SOURCES = client.cpp +SOURCES = wayland.cpp CONFIG -= qt QMAKE_CXXFLAGS += $$QT_CFLAGS_WAYLAND -- cgit v0.12 From 959b42b5f227486554ab82d50c29d3d2d3f40c08 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke <benjaminfranzke@googlemail.com> Date: Sun, 21 Nov 2010 14:15:37 +0100 Subject: wayland: remove non-public header from config.tests --- config.tests/qpa/wayland/wayland.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config.tests/qpa/wayland/wayland.cpp b/config.tests/qpa/wayland/wayland.cpp index 40ff2cb..28a904d 100644 --- a/config.tests/qpa/wayland/wayland.cpp +++ b/config.tests/qpa/wayland/wayland.cpp @@ -1,5 +1,4 @@ -#include "wayland-client.h" -#include "wayland-glib.h" +#include <wayland-client.h> int main(int, char **) { -- cgit v0.12 From 9d8b093f05a936cdd18f50474cb47c59ed42ac14 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke <benjaminfranzke@googlemail.com> Date: Sun, 21 Nov 2010 14:18:51 +0100 Subject: wayland: use pkgconfig for libdrm in wayland.pro On this system the IncludePath for drm.h was missing So maybe pkgconfig should be additionally also used for libxkbcommon, EGL and GLESv2 to prevent such problems. but i dont know whether its common to use pkg-config in qmake --- src/plugins/platforms/wayland/wayland.pro | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index b0cb98b..4c01fa2 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -16,7 +16,11 @@ HEADERS = qwaylandintegration.h \ contains(QT_CONFIG, opengl) { QT += opengl } -LIBS += -lwayland-client -ldrm -lxkbcommon -lEGL -lGLESv2 +LIBS += -lwayland-client -lxkbcommon -lEGL -lGLESv2 +unix { + CONFIG += link_pkgconfig + PKGCONFIG += libdrm +} include (../fontdatabases/fontconfig/fontconfig.pri) -- cgit v0.12 From 01f21cb23b83ec36267fd606e6137bd7765133c1 Mon Sep 17 00:00:00 2001 From: Rolf Offermanns <roffermanns@sysgo.com> Date: Thu, 25 Nov 2010 12:13:30 +0100 Subject: Fix for uninitialized member in QWaylandCursor Without this patch Qt applications will crash the moment the mouse pointer enters the window. Signed-off-by: Rolf Offermanns <roffermanns@sysgo.com> --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 19f339a..82789c8 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -25,7 +25,7 @@ public: QWaylandCursor(QWaylandDisplay *display, QPlatformScreen *screen) : QPlatformCursor(screen) - , mDisplay(display) { } + , mBuffer(0), mDisplay(display) { } void changeCursor(QCursor *cursor, QWidget *widget); QWaylandShmBuffer *mBuffer; -- cgit v0.12 From 9787509be13bfe9e05c4e6f7ab76150edecf133f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Thu, 20 Jan 2011 13:31:48 +0100 Subject: Fix X11 clipboard bug. Truth be told, the x11 clipboard integration in testlite was done rather quickly, thus leaving some cornercases open --- src/plugins/platforms/testlite/qtestliteclipboard.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp index 25c16ea..d77d45a 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.cpp +++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp @@ -386,9 +386,9 @@ void QTestLiteClipboard::handleSelectionRequest(XEvent *xevent) ; } else if (target == xa_timestamp) { // if (d->timestamp != CurrentTime) { - XChangeProperty(screen()->display(), req->requestor, property, XA_INTEGER, 32, - PropModeReplace, CurrentTime, 1); - ret = property; +// XChangeProperty(screen()->display(), req->requestor, property, XA_INTEGER, 32, +// PropModeReplace, CurrentTime, 1); +// ret = property; // } else { // qWarning("QClipboard: Invalid data timestamp"); // } -- cgit v0.12 From fd28a6ab14fc3c54c443718d405eeb9f98c7dd27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 17 Jan 2011 13:11:08 +0100 Subject: Remove Lighthouse specific code from QGLWindowSurface --- src/opengl/qwindowsurface_gl.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 6185ff8..ea5e9a7 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -401,11 +401,6 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) if (widgetPrivate->extraData()->glContext) return; -#ifdef Q_WS_QPA - QGLContext *ctx = QGLContext::fromPlatformGLContext(widget->platformWindow()->glContext()); - if (!d_ptr->fbo && d_ptr->tried_fbo) - d_ptr->ctx = ctx; -#else QGLContext *ctx = NULL; // For translucent top-level widgets we need alpha in the format. @@ -418,8 +413,7 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) } else ctx = new QGLContext(surfaceFormat, widget); - ctx->create(qt_gl_share_widget()->context()); -#endif + ctx->create(qt_gl_share_context()); #ifndef QT_NO_EGL static bool checkedForNOKSwapRegion = false; -- cgit v0.12 From 37207d16cb51616c0b506dcc57126ff06c9073a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Thu, 20 Jan 2011 08:44:27 +0100 Subject: Make QGLContext::fromPlatformGLContext show correct sharing information. Prior to this, if a context was created with QGLWidget it would setup the sharing correct, but all sharing actually created on a QPlatformGLContext level was ignored by the QGLContext, thus indicating that it wasnt sharing with any other context. --- src/gui/kernel/qplatformglcontext_qpa.cpp | 2 +- src/gui/kernel/qplatformglcontext_qpa.h | 2 +- src/opengl/qgl_p.h | 1 + src/opengl/qgl_qpa.cpp | 30 ++++++++++++++---------------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp index 14bd718..1673aed 100644 --- a/src/gui/kernel/qplatformglcontext_qpa.cpp +++ b/src/gui/kernel/qplatformglcontext_qpa.cpp @@ -138,7 +138,7 @@ void QPlatformGLContext::setDefaultSharedContext(QPlatformGLContext *sharedConte Default shared context is intended to be a globally awailable pointer to a context which can be used for sharing resources when creating new contexts. Its default value is 0; */ -const QPlatformGLContext *QPlatformGLContext::defaultSharedContext() +QPlatformGLContext *QPlatformGLContext::defaultSharedContext() { return QPlatformGLContextPrivate::staticSharedContext; } diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformglcontext_qpa.h index a70e046..807ed3d 100644 --- a/src/gui/kernel/qplatformglcontext_qpa.h +++ b/src/gui/kernel/qplatformglcontext_qpa.h @@ -69,7 +69,7 @@ public: virtual QPlatformWindowFormat platformWindowFormat() const = 0; const static QPlatformGLContext *currentContext(); - const static QPlatformGLContext *defaultSharedContext(); + static QPlatformGLContext *defaultSharedContext(); protected: diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index ca8bc55..858a915 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -373,6 +373,7 @@ public: #if defined(Q_WS_QPA) QPlatformGLContext *platformContext; + void setupSharing(); #elif defined(Q_WS_X11) || defined(Q_WS_MAC) void* cx; #endif diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp index 52eb57f..0f4b305 100644 --- a/src/opengl/qgl_qpa.cpp +++ b/src/opengl/qgl_qpa.cpp @@ -115,6 +115,16 @@ QPlatformWindowFormat QGLFormat::toPlatformWindowFormat(const QGLFormat &format) return retFormat; } +void QGLContextPrivate::setupSharing() { + Q_Q(QGLContext); + QPlatformGLContext *sharedPlatformGLContext = platformContext->platformWindowFormat().sharedGLContext(); + if (sharedPlatformGLContext) { + QGLContext *actualSharedContext = QGLContext::fromPlatformGLContext(sharedPlatformGLContext); + sharing = true; + QGLContextGroup::addShare(q,actualSharedContext); + } +} + bool QGLFormat::hasOpenGL() { return QApplicationPrivate::platformIntegration()->hasOpenGL(); @@ -151,19 +161,9 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) if (d->valid) { d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); } + d->setupSharing(); } - if (d->valid) { - QPlatformGLContext *sharedPlatformGLContext = d->platformContext->platformWindowFormat().sharedGLContext(); - if (sharedPlatformGLContext) { - QGLContext *actualSharedContext = QGLContext::fromPlatformGLContext(sharedPlatformGLContext); - if (actualSharedContext == shareContext) { - d->sharing = true;//Will add combination in QGLContext::create - }else { - QGLContextGroup::addShare(this,actualSharedContext); - } - } - } return d->valid; } @@ -372,6 +372,9 @@ QGLContext::QGLContext(QPlatformGLContext *platformContext) Q_D(QGLContext); d->init(0,QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat())); d->platformContext = platformContext; + d->platformContext->setQGLContextHandle(this,qDeleteQGLContext); + d->valid = true; + d->setupSharing(); } QGLContext *QGLContext::fromPlatformGLContext(QPlatformGLContext *platformContext) @@ -384,11 +387,6 @@ QGLContext *QGLContext::fromPlatformGLContext(QPlatformGLContext *platformContex QGLContext *glContext = new QGLContext(platformContext); //Dont call create on context. This can cause the platformFormat to be set on the widget, which //will cause the platformWindow to be recreated. - glContext->d_func()->platformContext->setQGLContextHandle(glContext,qDeleteQGLContext); - QGLFormat format = QGLFormat::fromPlatformWindowFormat(platformContext->platformWindowFormat()); - glContext->d_func()->glFormat = format; - glContext->d_func()->valid = true; - return glContext; } -- cgit v0.12 From 9d5675645dfb4b527932e7090f503ede2cc21efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Wed, 5 Jan 2011 12:10:28 +0100 Subject: Fix Wayland plugin to work with Wayland after some interfaces changed such as wl_display_create -> wl_display_connect wl_surface_attach (attributes) wl_surface_map -> wl_surface_map_toplevel wl_shell_listener wl_output_listener --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 17 ++++++++--------- src/plugins/platforms/wayland/qwaylandintegration.h | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 82789c8..61f696c 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -259,7 +259,6 @@ const struct wl_drm_listener QWaylandDisplay::drmListener = { void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, uint32_t time, uint32_t edges, struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) { Q_UNUSED(data); @@ -268,7 +267,7 @@ void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, Q_UNUSED(edges); QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); - ww->configure(time, edges, x, y, width, height); + ww->configure(time, edges, 0, 0, width, height); } const struct wl_shell_listener QWaylandDisplay::shellListener = { @@ -277,14 +276,15 @@ const struct wl_shell_listener QWaylandDisplay::shellListener = { void QWaylandDisplay::outputHandleGeometry(void *data, struct wl_output *output, - int32_t width, int32_t height) + int32_t x, int32_t y, + int32_t width, int32_t height) { Q_UNUSED(output); QWaylandDisplay *qwd = (QWaylandDisplay *) data; QWaylandScreen *screen; screen = new QWaylandScreen(); - screen->mGeometry = QRect(0, 0, width, height); + screen->mGeometry = QRect(x, y, width, height); screen->mDepth = 32; screen->mFormat = QImage::Format_ARGB32_Premultiplied; screen->mOutput = output; @@ -344,7 +344,7 @@ static void forceRoundtrip(struct wl_display *display) wl_display_iterate(display, WL_DISPLAY_READABLE); } -static const char socket_name[] = "\0wayland"; +static const char *socket_name = NULL; void QWaylandDisplay::eventDispatcher(void) { @@ -376,7 +376,7 @@ void QWaylandDisplay::flushRequests(void) QWaylandDisplay::QWaylandDisplay(void) : mWriteNotifier(0) { - mDisplay = wl_display_create(socket_name, sizeof socket_name); + mDisplay = wl_display_connect(socket_name); if (mDisplay == NULL) { fprintf(stderr, "failed to create display: %m\n"); return; @@ -483,9 +483,8 @@ void QWaylandWindow::attach(QWaylandBuffer *buffer) mBuffer = buffer; if (mSurface) { - wl_surface_attach(mSurface, mBuffer->mBuffer); - wl_surface_map(mSurface, geometry.x(), geometry.y(), - geometry.width(), geometry.height()); + wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); + wl_surface_map_toplevel(mSurface); } } diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 611ce43..84afcb4 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -115,12 +115,12 @@ private: static void outputHandleGeometry(void *data, struct wl_output *output, + int32_t x, int32_t y, int32_t width, int32_t height); static void shellHandleConfigure(void *data, struct wl_shell *shell, uint32_t time, uint32_t edges, struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height); static int sourceUpdate(uint32_t mask, void *data); -- cgit v0.12 From af15d5e128c1216bafa4f9d0121bb4178354e35e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Mon, 10 Jan 2011 15:48:20 +0100 Subject: Lighthouse:Wayland Moving some logic into files --- config.tests/qpa/wayland/wayland.cpp | 40 ++ src/plugins/platforms/wayland/qwaylandcursor.cpp | 180 ++++++++ src/plugins/platforms/wayland/qwaylandcursor.h | 62 +++ src/plugins/platforms/wayland/qwaylanddisplay.cpp | 306 +++++++++++++ src/plugins/platforms/wayland/qwaylanddisplay.h | 125 ++++++ .../platforms/wayland/qwaylanddrmsurface.cpp | 4 +- .../platforms/wayland/qwaylandglcontext.cpp | 10 +- src/plugins/platforms/wayland/qwaylandglcontext.h | 72 +++ .../platforms/wayland/qwaylandinputdevice.cpp | 8 +- .../platforms/wayland/qwaylandintegration.cpp | 482 +-------------------- .../platforms/wayland/qwaylandintegration.h | 145 +------ src/plugins/platforms/wayland/qwaylandscreen.cpp | 43 ++ src/plugins/platforms/wayland/qwaylandscreen.h | 64 +++ .../platforms/wayland/qwaylandshmsurface.cpp | 3 +- src/plugins/platforms/wayland/qwaylandwindow.cpp | 113 +++++ src/plugins/platforms/wayland/qwaylandwindow.h | 80 ++++ .../platforms/wayland/qwaylandwindowsurface.h | 2 - src/plugins/platforms/wayland/wayland.pro | 13 +- 18 files changed, 1121 insertions(+), 631 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandcursor.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandcursor.h create mode 100644 src/plugins/platforms/wayland/qwaylanddisplay.cpp create mode 100644 src/plugins/platforms/wayland/qwaylanddisplay.h create mode 100644 src/plugins/platforms/wayland/qwaylandglcontext.h create mode 100644 src/plugins/platforms/wayland/qwaylandscreen.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandscreen.h create mode 100644 src/plugins/platforms/wayland/qwaylandwindow.cpp create mode 100644 src/plugins/platforms/wayland/qwaylandwindow.h diff --git a/config.tests/qpa/wayland/wayland.cpp b/config.tests/qpa/wayland/wayland.cpp index 28a904d..09f72c6 100644 --- a/config.tests/qpa/wayland/wayland.cpp +++ b/config.tests/qpa/wayland/wayland.cpp @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ #include <wayland-client.h> int main(int, char **) diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp new file mode 100644 index 0000000..2a1e9a9 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandcursor.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindowsurface.h" +#include "qwaylandinputdevice.h" + +#include <QtGui/QImageReader> + +#define DATADIR "/usr/share" + +static const struct pointer_image { + const char *filename; + int hotspot_x, hotspot_y; +} pointer_images[] = { + /* FIXME: Half of these are wrong... */ + /* Qt::ArrowCursor */ + { DATADIR "/wayland/left_ptr.png", 10, 5 }, + /* Qt::UpArrowCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::CrossCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::WaitCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::IBeamCursor */ + { DATADIR "/wayland/xterm.png", 15, 15 }, + /* Qt::SizeVerCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::SizeHorCursor */ + { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, + /* Qt::SizeBDiagCursor */ + { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, + /* Qt::SizeFDiagCursor */ + { DATADIR "/wayland/bottom_side.png", 16, 20 }, + /* Qt::SizeAllCursor */ + { DATADIR "/wayland/left_side.png", 10, 20 }, + /* Qt::BlankCursor */ + { DATADIR "/wayland/right_side.png", 30, 19 }, + /* Qt::SplitVCursor */ + { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, + /* Qt::SplitHCursor */ + { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, + /* Qt::PointingHandCursor */ + { DATADIR "/wayland/hand2.png", 14, 8 }, + /* Qt::ForbiddenCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::WhatsThisCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::BusyCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::OpenHandCursor */ + { DATADIR "/wayland/hand1.png", 18, 11 }, + /* Qt::ClosedHandCursor */ + { DATADIR "/wayland/grabbing.png", 20, 17 }, + /* Qt::DragCopyCursor */ + { DATADIR "/wayland/dnd-copy.png", 13, 13 }, + /* Qt::DragMoveCursor */ + { DATADIR "/wayland/dnd-move.png", 13, 13 }, + /* Qt::DragLinkCursor */ + { DATADIR "/wayland/dnd-link.png", 13, 13 }, +}; + +void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + const struct pointer_image *p; + + if (widget == NULL) + return; + + p = NULL; + + switch (cursor->shape()) { + case Qt::ArrowCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::UpArrowCursor: + case Qt::CrossCursor: + case Qt::WaitCursor: + break; + case Qt::IBeamCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::SizeVerCursor: /* 5 */ + case Qt::SizeHorCursor: + case Qt::SizeBDiagCursor: + case Qt::SizeFDiagCursor: + case Qt::SizeAllCursor: + case Qt::BlankCursor: /* 10 */ + break; + case Qt::SplitVCursor: + case Qt::SplitHCursor: + case Qt::PointingHandCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::ForbiddenCursor: + case Qt::WhatsThisCursor: /* 15 */ + case Qt::BusyCursor: + break; + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: /* 20 */ + case Qt::DragLinkCursor: + p = &pointer_images[cursor->shape()]; + break; + + default: + case Qt::BitmapCursor: + break; + } + + if (!p) { + p = &pointer_images[0]; + qWarning("unhandled cursor %d", cursor->shape()); + } + + QImageReader reader(p->filename); + + if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { + if (mBuffer) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), + QImage::Format_ARGB32); + } + + reader.read(&mBuffer->mImage); + + mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); +} + +void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) +{ + /* Qt doesn't tell us which input device we should set the cursor + * for, so set it for all devices. */ + for (int i = 0; i < mInputDevices.count(); i++) { + QWaylandInputDevice *inputDevice = mInputDevices.at(i); + inputDevice->attach(buffer, x, y); + } +} diff --git a/src/plugins/platforms/wayland/qwaylandcursor.h b/src/plugins/platforms/wayland/qwaylandcursor.h new file mode 100644 index 0000000..8c9d263 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDCURSOR_H +#define QWAYLANDCURSOR_H + +#include <QtGui/QPlatformCursor> + +class QWaylandShmBuffer; +class QWaylandDisplay; + +class QWaylandCursor : QPlatformCursor { +public: + QWaylandCursor(QWaylandDisplay *display, + QPlatformScreen *screen) + : QPlatformCursor(screen) + , mBuffer(0), mDisplay(display) { } + + void changeCursor(QCursor *cursor, QWidget *widget); + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +#endif // QWAYLANDCURSOR_H diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp new file mode 100644 index 0000000..8446777 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddisplay.h" + +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" +#include "qwaylandcursor.h" +#include "qwaylandinputdevice.h" + +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +extern "C" { +#include <xf86drm.h> +} + +struct wl_surface *QWaylandDisplay::createSurface() +{ + return wl_compositor_create_surface(mCompositor); +} + +struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); +} + +struct wl_buffer *QWaylandDisplay::createDrmBuffer(int name, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); +} + +struct wl_visual *QWaylandDisplay::rgbVisual() +{ + return wl_display_get_rgb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbVisual() +{ + return wl_display_get_argb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() +{ + return wl_display_get_premultiplied_argb_visual(mDisplay); +} + +void QWaylandDisplay::drmHandleDevice(void *data, + struct wl_drm *drm, const char *device) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + drm_magic_t magic; + + qwd->mDeviceName = strdup(device); + + qwd->mFd = open(qwd->mDeviceName, O_RDWR); + if (qwd->mFd < 0) { + qWarning("drm open failed: %m"); + return; + } + + if (drmGetMagic(qwd->mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + wl_drm_authenticate(qwd->mDrm, magic); +} + +void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) +{ + Q_UNUSED(drm); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + EGLint major, minor; + const char *extensions; + + qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); + if (qwd->mEglDisplay == NULL) { + qWarning("failed to create display"); + return; + } + + if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { + qWarning("failed to initialize display"); + qwd->mEglDisplay = NULL; + return; + } + + extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); + if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { + qWarning("EGL_KHR_surfaceless_opengles2 not available"); + eglTerminate(qwd->mEglDisplay); + qwd->mEglDisplay = NULL; + return; + } +} + +const struct wl_drm_listener QWaylandDisplay::drmListener = { + QWaylandDisplay::drmHandleDevice, + QWaylandDisplay::drmHandleAuthenticated +}; + +void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height) +{ + Q_UNUSED(data); + Q_UNUSED(shell); + Q_UNUSED(time); + Q_UNUSED(edges); + QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); + + ww->configure(time, edges, 0, 0, width, height); +} + +const struct wl_shell_listener QWaylandDisplay::shellListener = { + QWaylandDisplay::shellHandleConfigure, +}; + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(output); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + QWaylandScreen *screen; + + screen = new QWaylandScreen(); + screen->mGeometry = QRect(x, y, width, height); + screen->mDepth = 32; + screen->mFormat = QImage::Format_ARGB32_Premultiplied; + screen->mOutput = output; + + new QWaylandCursor(qwd, screen); + + qwd->mScreens.append(screen); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data) +{ + Q_UNUSED(version); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + if (strcmp(interface, "compositor") == 0) { + qwd->mCompositor = wl_compositor_create(display, id); + } else if (strcmp(interface, "drm") == 0) { + qwd->mDrm = wl_drm_create(display, id); + wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); + } else if (strcmp(interface, "shm") == 0) { + qwd->mShm = wl_shm_create(display, id); + } else if (strcmp(interface, "shell") == 0) { + qwd->mShell = wl_shell_create(display, id); + wl_shell_add_listener(qwd->mShell, &shellListener, qwd); + } else if (strcmp(interface, "output") == 0) { + struct wl_output *output = wl_output_create(display, id); + wl_output_add_listener(output, &outputListener, qwd); + } else if (strcmp(interface, "input_device") == 0) { + QWaylandInputDevice *inputDevice = + new QWaylandInputDevice(display, id); + qwd->mInputDevices.append(inputDevice); + } +} + +static void roundtripCallback(void *data) +{ + bool *done = (bool *) data; + + *done = true; +} + +static void forceRoundtrip(struct wl_display *display) +{ + bool done; + + wl_display_sync_callback(display, roundtripCallback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + +static const char *socket_name = NULL; + +void QWaylandDisplay::eventDispatcher(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int +QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + /* FIXME: We get a callback here when we ask wl_display for the + * fd, but at that point we don't have the socket notifier as we + * need the fd to create that. We'll probably need to split that + * API into get_fd and set_update_func functions. */ + if (qwd->mWriteNotifier == NULL) + return 0; + + qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); + + return 0; +} + +void QWaylandDisplay::flushRequests(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +QWaylandDisplay::QWaylandDisplay(void) + : mWriteNotifier(0) +{ + mDisplay = wl_display_connect(socket_name); + if (mDisplay == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return; + } + + wl_display_add_global_listener(mDisplay, + QWaylandDisplay::displayHandleGlobal, this); + + /* Process connection events. */ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + if (!mShm || !mDeviceName) + forceRoundtrip(mDisplay); + + /* Force a roundtrip to finish the drm authentication so we + * initialize EGL before proceeding */ + forceRoundtrip(mDisplay); + if (mEglDisplay == NULL) + qDebug("EGL not available"); + else + qDebug("EGL initialized"); + + int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); + mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(mReadNotifier, + SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(mWriteNotifier, + SIGNAL(activated(int)), this, SLOT(flushRequests())); + mWriteNotifier->setEnabled(false); +} + +QWaylandDisplay::~QWaylandDisplay(void) +{ + close(mFd); + wl_display_destroy(mDisplay); +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h new file mode 100644 index 0000000..7d989a9 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDISPLAY_H +#define QWAYLANDDISPLAY_H + +#include <QtCore/QObject> + +#include <wayland-client.h> + +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +class QWaylandInputDevice; +class QSocketNotifier; +class QWaylandBuffer; +class QPlatformScreen; + +class QWaylandDisplay : public QObject { + Q_OBJECT; + +public: + QWaylandDisplay(void); + ~QWaylandDisplay(void); + + QList<QPlatformScreen *> screens() const { return mScreens; } + struct wl_surface *createSurface(); + struct wl_buffer *createShmBuffer(int fd, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_buffer *createDrmBuffer(int name, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *rgbVisual(); + struct wl_visual *argbVisual(); + struct wl_visual *argbPremultipliedVisual(); + EGLDisplay eglDisplay() { return mEglDisplay; } + + void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + +public slots: + void eventDispatcher(void); + void flushRequests(void); + +private: + struct wl_display *mDisplay; + struct wl_compositor *mCompositor; + struct wl_drm *mDrm; + struct wl_shm *mShm; + struct wl_shell *mShell; + char *mDeviceName; + int mFd; + QList<QPlatformScreen *> mScreens; + QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + QSocketNotifier *mWriteNotifier; + EGLDisplay mEglDisplay; + + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + + static void drmHandleDevice(void *data, + struct wl_drm *drm, const char *device); + static void drmHandleAuthenticated(void *data, struct wl_drm *drm); + + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height); + + static void shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height); + + static int sourceUpdate(uint32_t mask, void *data); + + static const struct wl_drm_listener drmListener; + static const struct wl_output_listener outputListener; + static const struct wl_shell_listener shellListener; +}; + +#endif // QWAYLANDDISPLAY_H diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index cb4445c..1a7683e 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -49,8 +49,10 @@ #include <QtOpenGL/private/qgl_p.h> #include <QtOpenGL/private/qglpaintdevice_p.h> -#include "qwaylandintegration.h" +#include "qwaylanddisplay.h" #include "qwaylandwindowsurface.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" #include <wayland-client.h> #include <unistd.h> diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp index 264da2e..24abcf8 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.cpp +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -1,7 +1,8 @@ -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> +#include "qwaylandglcontext.h" +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandwindowsurface.h" #include "qfontconfigdatabase.h" #include <QImageReader> @@ -19,9 +20,6 @@ #include <private/qpixmapdata_gl_p.h> #include <private/qpaintengineex_opengl2_p.h> -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" - #include <unistd.h> #include <fcntl.h> diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/qwaylandglcontext.h new file mode 100644 index 0000000..6e3c108 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDGLCONTEXT_H +#define QWAYLANDGLCONTEXT_H + +#include <QtGui/QPlatformGLContext> + +class QWaylandDisplay; +class QWaylandWindow; + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + +private: + QPlatformWindowFormat mFormat; + QWaylandDisplay *mDisplay; + QWaylandWindow *mWindow; + GLuint parentFbo, parentRbo; +}; + + +#endif // QWAYLANDGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 6d489b6..77c5815 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -1,6 +1,10 @@ -#include <QWindowSystemInterface> +#include "qwaylandinputdevice.h" + #include "qwaylandintegration.h" #include "qwaylandwindowsurface.h" +#include "qwaylandwindow.h" + +#include <QWindowSystemInterface> #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/QPlatformWindow> @@ -51,7 +55,7 @@ void QWaylandInputDevice::inputHandleMotion(void *data, time, inputDevice->mSurfacePos, inputDevice->mGlobalPos, - inputDevice->mButtons); + inputDevice->mButtons); } void QWaylandInputDevice::inputHandleButton(void *data, diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 61f696c..a6fdc2e 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,419 +1,17 @@ -#include "qfontconfigdatabase.h" - -#include <QImageReader> -#include <QWindowSystemInterface> -#include <QPlatformCursor> -#include <QPaintEngine> - -#include <QtGui/QPlatformWindowFormat> - -#include <QtGui/private/qpixmap_raster_p.h> -#include <QtGui/QPlatformWindow> - #include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" - -#include <unistd.h> -#include <fcntl.h> - -extern "C" { -#include <xf86drm.h> -} - -class QWaylandCursor : QPlatformCursor { -public: - QWaylandCursor(QWaylandDisplay *display, - QPlatformScreen *screen) - : QPlatformCursor(screen) - , mBuffer(0), mDisplay(display) { } - - void changeCursor(QCursor *cursor, QWidget *widget); - QWaylandShmBuffer *mBuffer; - QWaylandDisplay *mDisplay; -}; - -#define DATADIR "/usr/share" - -static const struct pointer_image { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - /* FIXME: Half of these are wrong... */ - /* Qt::ArrowCursor */ - { DATADIR "/wayland/left_ptr.png", 10, 5 }, - /* Qt::UpArrowCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::CrossCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::WaitCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::IBeamCursor */ - { DATADIR "/wayland/xterm.png", 15, 15 }, - /* Qt::SizeVerCursor */ - { DATADIR "/wayland/top_side.png", 18, 8 }, - /* Qt::SizeHorCursor */ - { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, - /* Qt::SizeBDiagCursor */ - { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, - /* Qt::SizeFDiagCursor */ - { DATADIR "/wayland/bottom_side.png", 16, 20 }, - /* Qt::SizeAllCursor */ - { DATADIR "/wayland/left_side.png", 10, 20 }, - /* Qt::BlankCursor */ - { DATADIR "/wayland/right_side.png", 30, 19 }, - /* Qt::SplitVCursor */ - { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, - /* Qt::SplitHCursor */ - { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, - /* Qt::PointingHandCursor */ - { DATADIR "/wayland/hand2.png", 14, 8 }, - /* Qt::ForbiddenCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::WhatsThisCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::BusyCursor */ - { DATADIR "/wayland/top_right_corner.png", 26, 8 }, - /* Qt::OpenHandCursor */ - { DATADIR "/wayland/hand1.png", 18, 11 }, - /* Qt::ClosedHandCursor */ - { DATADIR "/wayland/grabbing.png", 20, 17 }, - /* Qt::DragCopyCursor */ - { DATADIR "/wayland/dnd-copy.png", 13, 13 }, - /* Qt::DragMoveCursor */ - { DATADIR "/wayland/dnd-move.png", 13, 13 }, - /* Qt::DragLinkCursor */ - { DATADIR "/wayland/dnd-link.png", 13, 13 }, -}; - -void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) -{ - const struct pointer_image *p; - - if (widget == NULL) - return; - - p = NULL; - - switch (cursor->shape()) { - case Qt::ArrowCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::UpArrowCursor: - case Qt::CrossCursor: - case Qt::WaitCursor: - break; - case Qt::IBeamCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::SizeVerCursor: /* 5 */ - case Qt::SizeHorCursor: - case Qt::SizeBDiagCursor: - case Qt::SizeFDiagCursor: - case Qt::SizeAllCursor: - case Qt::BlankCursor: /* 10 */ - break; - case Qt::SplitVCursor: - case Qt::SplitHCursor: - case Qt::PointingHandCursor: - p = &pointer_images[cursor->shape()]; - break; - case Qt::ForbiddenCursor: - case Qt::WhatsThisCursor: /* 15 */ - case Qt::BusyCursor: - break; - case Qt::OpenHandCursor: - case Qt::ClosedHandCursor: - case Qt::DragCopyCursor: - case Qt::DragMoveCursor: /* 20 */ - case Qt::DragLinkCursor: - p = &pointer_images[cursor->shape()]; - break; - - default: - case Qt::BitmapCursor: - break; - } - - if (!p) { - p = &pointer_images[0]; - qWarning("unhandled cursor %d", cursor->shape()); - } - - QImageReader reader(p->filename); - - if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { - if (mBuffer) - delete mBuffer; - - mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), - QImage::Format_ARGB32); - } - - reader.read(&mBuffer->mImage); - - mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); -} - -void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) -{ - /* Qt doesn't tell us which input device we should set the cursor - * for, so set it for all devices. */ - for (int i = 0; i < mInputDevices.count(); i++) { - QWaylandInputDevice *inputDevice = mInputDevices.at(i); - inputDevice->attach(buffer, x, y); - } -} - -struct wl_surface *QWaylandDisplay::createSurface() -{ - return wl_compositor_create_surface(mCompositor); -} - -struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, - int width, int height, - uint32_t stride, - struct wl_visual *visual) -{ - return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); -} - -struct wl_buffer *QWaylandDisplay::createDrmBuffer(int name, - int width, int height, - uint32_t stride, - struct wl_visual *visual) -{ - return wl_drm_create_buffer(mDrm, name, width, height, stride, visual); -} - -struct wl_visual *QWaylandDisplay::rgbVisual() -{ - return wl_display_get_rgb_visual(mDisplay); -} - -struct wl_visual *QWaylandDisplay::argbVisual() -{ - return wl_display_get_argb_visual(mDisplay); -} - -struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() -{ - return wl_display_get_premultiplied_argb_visual(mDisplay); -} - -void QWaylandDisplay::drmHandleDevice(void *data, - struct wl_drm *drm, const char *device) -{ - Q_UNUSED(drm); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - drm_magic_t magic; - - qwd->mDeviceName = strdup(device); - - qwd->mFd = open(qwd->mDeviceName, O_RDWR); - if (qwd->mFd < 0) { - qWarning("drm open failed: %m"); - return; - } - - if (drmGetMagic(qwd->mFd, &magic)) { - qWarning("DRI2: failed to get drm magic"); - return; - } - - wl_drm_authenticate(qwd->mDrm, magic); -} - -void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) -{ - Q_UNUSED(drm); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - EGLint major, minor; - const char *extensions; - - qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); - if (qwd->mEglDisplay == NULL) { - qWarning("failed to create display"); - return; - } - - if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { - qWarning("failed to initialize display"); - qwd->mEglDisplay = NULL; - return; - } - - extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); - if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { - qWarning("EGL_KHR_surfaceless_opengles2 not available"); - eglTerminate(qwd->mEglDisplay); - qwd->mEglDisplay = NULL; - return; - } -} - -const struct wl_drm_listener QWaylandDisplay::drmListener = { - QWaylandDisplay::drmHandleDevice, - QWaylandDisplay::drmHandleAuthenticated -}; - -void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, - int32_t width, int32_t height) -{ - Q_UNUSED(data); - Q_UNUSED(shell); - Q_UNUSED(time); - Q_UNUSED(edges); - QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); - - ww->configure(time, edges, 0, 0, width, height); -} -const struct wl_shell_listener QWaylandDisplay::shellListener = { - QWaylandDisplay::shellHandleConfigure, -}; - -void QWaylandDisplay::outputHandleGeometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - Q_UNUSED(output); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - QWaylandScreen *screen; - - screen = new QWaylandScreen(); - screen->mGeometry = QRect(x, y, width, height); - screen->mDepth = 32; - screen->mFormat = QImage::Format_ARGB32_Premultiplied; - screen->mOutput = output; - - new QWaylandCursor(qwd, screen); - - qwd->mScreens.append(screen); -} - -const struct wl_output_listener QWaylandDisplay::outputListener = { - QWaylandDisplay::outputHandleGeometry -}; - -void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, void *data) -{ - Q_UNUSED(version); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - - if (strcmp(interface, "compositor") == 0) { - qwd->mCompositor = wl_compositor_create(display, id); - } else if (strcmp(interface, "drm") == 0) { - qwd->mDrm = wl_drm_create(display, id); - wl_drm_add_listener(qwd->mDrm, &drmListener, qwd); - } else if (strcmp(interface, "shm") == 0) { - qwd->mShm = wl_shm_create(display, id); - } else if (strcmp(interface, "shell") == 0) { - qwd->mShell = wl_shell_create(display, id); - wl_shell_add_listener(qwd->mShell, &shellListener, qwd); - } else if (strcmp(interface, "output") == 0) { - struct wl_output *output = wl_output_create(display, id); - wl_output_add_listener(output, &outputListener, qwd); - } else if (strcmp(interface, "input_device") == 0) { - QWaylandInputDevice *inputDevice = - new QWaylandInputDevice(display, id); - qwd->mInputDevices.append(inputDevice); - } -} - -static void roundtripCallback(void *data) -{ - bool *done = (bool *) data; - - *done = true; -} - -static void forceRoundtrip(struct wl_display *display) -{ - bool done; - - wl_display_sync_callback(display, roundtripCallback, &done); - wl_display_iterate(display, WL_DISPLAY_WRITABLE); - done = false; - while (!done) - wl_display_iterate(display, WL_DISPLAY_READABLE); -} - -static const char *socket_name = NULL; - -void QWaylandDisplay::eventDispatcher(void) -{ - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); -} - -int -QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) -{ - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - - /* FIXME: We get a callback here when we ask wl_display for the - * fd, but at that point we don't have the socket notifier as we - * need the fd to create that. We'll probably need to split that - * API into get_fd and set_update_func functions. */ - if (qwd->mWriteNotifier == NULL) - return 0; - - qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); - - return 0; -} - -void QWaylandDisplay::flushRequests(void) -{ - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); -} - -QWaylandDisplay::QWaylandDisplay(void) - : mWriteNotifier(0) -{ - mDisplay = wl_display_connect(socket_name); - if (mDisplay == NULL) { - fprintf(stderr, "failed to create display: %m\n"); - return; - } - - wl_display_add_global_listener(mDisplay, - QWaylandDisplay::displayHandleGlobal, this); - - /* Process connection events. */ - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); - if (!mShm || !mDeviceName) - forceRoundtrip(mDisplay); - - /* Force a roundtrip to finish the drm authentication so we - * initialize EGL before proceeding */ - forceRoundtrip(mDisplay); - if (mEglDisplay == NULL) - qDebug("EGL not available"); - else - qDebug("EGL initialized"); +#include "qwaylanddisplay.h" +#include "qwaylandwindowsurface.h" +#include "qwaylandwindow.h" - int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); - mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); - connect(mReadNotifier, - SIGNAL(activated(int)), this, SLOT(eventDispatcher())); +#include "qfontconfigdatabase.h" - mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); - connect(mWriteNotifier, - SIGNAL(activated(int)), this, SLOT(flushRequests())); - mWriteNotifier->setEnabled(false); -} +#include <QtGui/QWindowSystemInterface> +#include <QtGui/QPlatformCursor> +#include <QtGui/QPlatformWindowFormat> -QWaylandDisplay::~QWaylandDisplay(void) -{ - close(mFd); - wl_display_destroy(mDisplay); -} +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtOpenGL/private/qpixmapdata_gl_p.h> QWaylandIntegration::QWaylandIntegration(bool useOpenGL) : mFontDb(new QFontconfigDatabase()) @@ -435,69 +33,7 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) return new QRasterPixmapData(type); } -QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) - : QPlatformWindow(window) - , mSurface(0) - , mDisplay(display) - , mGLContext(0) - , mBuffer(0) -{ - static WId id = 1; - - mWindowId = id++; -} - -QWaylandWindow::~QWaylandWindow() -{ - if (mGLContext) - delete mGLContext; -} -WId QWaylandWindow::winId() const -{ - return mWindowId; -} - -void QWaylandWindow::setParent(const QPlatformWindow *parent) -{ - QWaylandWindow *wParent = (QWaylandWindow *)parent; - - mParentWindow = wParent; -} - -void QWaylandWindow::setVisible(bool visible) -{ - if (visible) { - mSurface = mDisplay->createSurface(); - wl_surface_set_user_data(mSurface, this); - attach(mBuffer); - } else { - wl_surface_destroy(mSurface); - mSurface = NULL; - } -} - -void QWaylandWindow::attach(QWaylandBuffer *buffer) -{ - QRect geometry = widget()->geometry(); - - mBuffer = buffer; - if (mSurface) { - wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); - wl_surface_map_toplevel(mSurface); - } -} - -void QWaylandWindow::configure(uint32_t time, uint32_t edges, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - Q_UNUSED(time); - Q_UNUSED(edges); - QRect geometry = QRect(x, y, width, height); - - QWindowSystemInterface::handleGeometryChange(widget(), geometry); -} QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 84afcb4..d707612 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -42,138 +42,12 @@ #ifndef QPLATFORMINTEGRATION_WAYLAND_H #define QPLATFORMINTEGRATION_WAYLAND_H -#include <QSocketNotifier> -#include <QObject> #include <QtGui/QPlatformIntegration> -#include <QtGui/QPlatformScreen> -#include <QtGui/QPlatformGLContext> -#include <QtGui/QPlatformWindowFormat> -#include "qgl.h" - -#include <private/qpixmapdata_gl_p.h> - -#include <wayland-client.h> -#include "qwaylandinputdevice.h" - -#define MESA_EGL_NO_X11_HEADERS -#define EGL_EGLEXT_PROTOTYPES -#include <EGL/egl.h> -#include <EGL/eglext.h> QT_BEGIN_NAMESPACE class QWaylandBuffer; - -class QWaylandDisplay : public QObject { - Q_OBJECT; - -public: - QWaylandDisplay(void); - ~QWaylandDisplay(void); - - QList<QPlatformScreen *> screens() const { return mScreens; } - struct wl_surface *createSurface(); - struct wl_buffer *createShmBuffer(int fd, int width, int height, - uint32_t stride, - struct wl_visual *visual); - struct wl_buffer *createDrmBuffer(int name, int width, int height, - uint32_t stride, - struct wl_visual *visual); - struct wl_visual *rgbVisual(); - struct wl_visual *argbVisual(); - struct wl_visual *argbPremultipliedVisual(); - EGLDisplay eglDisplay() { return mEglDisplay; } - - void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); - -public slots: - void eventDispatcher(void); - void flushRequests(void); - -private: - struct wl_display *mDisplay; - struct wl_compositor *mCompositor; - struct wl_drm *mDrm; - struct wl_shm *mShm; - struct wl_shell *mShell; - char *mDeviceName; - int mFd; - QList<QPlatformScreen *> mScreens; - QList<QWaylandInputDevice *> mInputDevices; - QSocketNotifier *mReadNotifier; - QSocketNotifier *mWriteNotifier; - EGLDisplay mEglDisplay; - - static void displayHandleGlobal(struct wl_display *display, - uint32_t id, - const char *interface, - uint32_t version, void *data); - - static void drmHandleDevice(void *data, - struct wl_drm *drm, const char *device); - static void drmHandleAuthenticated(void *data, struct wl_drm *drm); - - static void outputHandleGeometry(void *data, - struct wl_output *output, - int32_t x, int32_t y, - int32_t width, int32_t height); - - static void shellHandleConfigure(void *data, struct wl_shell *shell, - uint32_t time, uint32_t edges, - struct wl_surface *surface, - int32_t width, int32_t height); - - static int sourceUpdate(uint32_t mask, void *data); - - static const struct wl_drm_listener drmListener; - static const struct wl_output_listener outputListener; - static const struct wl_shell_listener shellListener; -}; - -class QWaylandScreen : public QPlatformScreen -{ -public: - QWaylandScreen() {} - - QRect geometry() const { return mGeometry; } - int depth() const { return mDepth; } - QImage::Format format() const { return mFormat; } - -public: - QRect mGeometry; - int mDepth; - QImage::Format mFormat; - QSize mPhysicalSize; - struct wl_output *mOutput; -}; - - -class QWaylandWindow : public QPlatformWindow -{ -public: - QWaylandWindow(QWidget *window, QWaylandDisplay *display); - ~QWaylandWindow(); - struct wl_surface *surface() { return mSurface; } - - void setVisible(bool visible); - void configure(uint32_t time, uint32_t edges, - int32_t x, int32_t y, int32_t width, int32_t height); - WId winId() const; - void setParent(const QPlatformWindow *parent); - QPlatformGLContext *glContext() const; - void attach(QWaylandBuffer *buffer); - QWaylandBuffer *getBuffer(void) { return mBuffer; } - QWaylandWindow *getParentWindow(void) { return mParentWindow; } - -private: - struct wl_surface *mSurface; - QWaylandDisplay *mDisplay; - QPlatformGLContext *mGLContext; - WId mWindowId; - - QWaylandBuffer *mBuffer; - QWaylandWindow *mParentWindow; -}; +class QWaylandDisplay; class QWaylandIntegration : public QPlatformIntegration { @@ -194,23 +68,6 @@ private: bool mUseOpenGL; }; -class QWaylandGLContext : public QPlatformGLContext { -public: - QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); - ~QWaylandGLContext(); - void makeCurrent(); - void doneCurrent(); - void swapBuffers(); - void* getProcAddress(const QString&); - QPlatformWindowFormat platformWindowFormat() const { return mFormat; } - -private: - QPlatformWindowFormat mFormat; - QWaylandDisplay *mDisplay; - QWaylandWindow *mWindow; - GLuint parentFbo, parentRbo; -}; - QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp new file mode 100644 index 0000000..4a7e727 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandscreen.h" + diff --git a/src/plugins/platforms/wayland/qwaylandscreen.h b/src/plugins/platforms/wayland/qwaylandscreen.h new file mode 100644 index 0000000..808266e --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSCREEN_H +#define QWAYLANDSCREEN_H + +#include <QtGui/QPlatformScreen> + +class QWaylandScreen : public QPlatformScreen +{ +public: + QWaylandScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + struct wl_output *mOutput; +}; + +#endif // QWAYLANDSCREEN_H diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp index 004b93a..1c3a26c 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -42,8 +42,9 @@ #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> -#include "qwaylandintegration.h" +#include "qwaylanddisplay.h" #include "qwaylandwindowsurface.h" +#include "qwaylandwindow.h" #include <wayland-client.h> #include <unistd.h> diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp new file mode 100644 index 0000000..4f696b0 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandwindow.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindowsurface.h" +#include "qwaylandglcontext.h" + +#include <QtGui/QWidget> +#include <QtGui/QWindowSystemInterface> + +QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) + : QPlatformWindow(window) + , mSurface(0) + , mDisplay(display) + , mGLContext(0) + , mBuffer(0) +{ + static WId id = 1; + + mWindowId = id++; +} + +QWaylandWindow::~QWaylandWindow() +{ + if (mGLContext) + delete mGLContext; +} + +WId QWaylandWindow::winId() const +{ + return mWindowId; +} + +void QWaylandWindow::setParent(const QPlatformWindow *parent) +{ + QWaylandWindow *wParent = (QWaylandWindow *)parent; + + mParentWindow = wParent; +} + +void QWaylandWindow::setVisible(bool visible) +{ + if (visible) { + mSurface = mDisplay->createSurface(); + wl_surface_set_user_data(mSurface, this); + attach(mBuffer); + } else { + wl_surface_destroy(mSurface); + mSurface = NULL; + } +} + +void QWaylandWindow::attach(QWaylandBuffer *buffer) +{ + QRect geometry = widget()->geometry(); + + mBuffer = buffer; + if (mSurface) { + wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); + wl_surface_map_toplevel(mSurface); + } +} + +void QWaylandWindow::configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(time); + Q_UNUSED(edges); + QRect geometry = QRect(x, y, width, height); + + QWindowSystemInterface::handleGeometryChange(widget(), geometry); +} diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h new file mode 100644 index 0000000..d5cc923 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDWINDOW_H +#define QWAYLANDWINDOW_H + +#include <QtGui/QPlatformWindow> + +#include <stdint.h> + +class QWaylandDisplay; +class QWaylandBuffer; + +class QWaylandWindow : public QPlatformWindow +{ +public: + QWaylandWindow(QWidget *window, QWaylandDisplay *display); + ~QWaylandWindow(); + struct wl_surface *surface() { return mSurface; } + + void setVisible(bool visible); + void configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, int32_t width, int32_t height); + WId winId() const; + void setParent(const QPlatformWindow *parent); + QPlatformGLContext *glContext() const; + void attach(QWaylandBuffer *buffer); + QWaylandBuffer *getBuffer(void) { return mBuffer; } + QWaylandWindow *getParentWindow(void) { return mParentWindow; } + +private: + struct wl_surface *mSurface; + QWaylandDisplay *mDisplay; + QPlatformGLContext *mGLContext; + WId mWindowId; + + QWaylandBuffer *mBuffer; + QWaylandWindow *mParentWindow; +}; + + +#endif // QWAYLANDWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h index 21c48f9..db57619 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ b/src/plugins/platforms/wayland/qwaylandwindowsurface.h @@ -52,8 +52,6 @@ #include <EGL/egl.h> #include <EGL/eglext.h> -#include <QtOpenGL/qgl.h> - QT_BEGIN_NAMESPACE class QWaylandDisplay; diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 4c01fa2..784a248 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -8,10 +8,19 @@ SOURCES = main.cpp \ qwaylandshmsurface.cpp \ qwaylanddrmsurface.cpp \ qwaylandinputdevice.cpp \ - qwaylandglcontext.cpp + qwaylandglcontext.cpp \ + qwaylandcursor.cpp \ + qwaylanddisplay.cpp \ + qwaylandwindow.cpp \ + qwaylandscreen.cpp HEADERS = qwaylandintegration.h \ - qwaylandwindowsurface.h + qwaylandwindowsurface.h \ + qwaylandcursor.h \ + qwaylanddisplay.h \ + qwaylandwindow.h \ + qwaylandscreen.h \ + qwaylandglcontext.h contains(QT_CONFIG, opengl) { QT += opengl -- cgit v0.12 From d39662822785484ec8e76066f4f2b65ef8778b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Tue, 18 Jan 2011 15:15:05 +0100 Subject: Make it possible to vertically mirror gl painting The GLPaintDevice gets a flip property. If this is set, the pvr matrix is altered to paint "upside down" Reviewed-by: sroedal --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 21 ++++++++++++++++++--- src/opengl/qglpaintdevice.cpp | 6 ++++-- src/opengl/qglpaintdevice_p.h | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index cf63626..d07fc54 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -337,7 +337,13 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms() matrix.translate(brushOrigin.x(), brushOrigin.y()); QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y()); - QTransform gl_to_qt(1, 0, 0, -1, 0, height); + qreal m22 = -1; + qreal dy = height; + if (device->isFlipped()) { + m22 = 1; + dy = 0; + } + QTransform gl_to_qt(1, 0, 0, m22, 0, dy); QTransform inv_matrix; if (style == Qt::TexturePattern && textureInvertedY == -1) inv_matrix = gl_to_qt * (QTransform(1, 0, 0, -1, 0, currentBrush.texture().height()) * brushQTransform * matrix).inverted() * translate; @@ -376,10 +382,16 @@ void QGL2PaintEngineExPrivate::updateMatrix() // NOTE: The resultant matrix is also transposed, as GL expects column-major matracies const GLfloat wfactor = 2.0f / width; - const GLfloat hfactor = -2.0f / height; + GLfloat hfactor = -2.0f / height; + GLfloat dx = transform.dx(); GLfloat dy = transform.dy(); + if (device->isFlipped()) { + hfactor *= -1; + dy -= height; + } + // Non-integer translates can have strange effects for some rendering operations such as // anti-aliased text rendering. In such cases, we snap the translate to the pixel grid. if (snapToPixelGrid && transform.type() == QTransform::TxTranslate) { @@ -2059,7 +2071,10 @@ void QGL2PaintEngineExPrivate::setScissor(const QRect &rect) { const int left = rect.left(); const int width = rect.width(); - const int bottom = height - (rect.top() + rect.height()); + int bottom = height - (rect.top() + rect.height()); + if (device->isFlipped()) { + bottom = rect.top(); + } const int height = rect.height(); glScissor(left, bottom, width, height); diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp index e1dcbfd..c2b2adf 100644 --- a/src/opengl/qglpaintdevice.cpp +++ b/src/opengl/qglpaintdevice.cpp @@ -145,8 +145,10 @@ bool QGLPaintDevice::alphaRequested() const return context()->d_func()->reqFormat.alpha(); } - - +bool QGLPaintDevice::isFlipped() const +{ + return false; +} ////////////////// QGLWidgetGLPaintDevice ////////////////// diff --git a/src/opengl/qglpaintdevice_p.h b/src/opengl/qglpaintdevice_p.h index 04f9c3c..39b91c9 100644 --- a/src/opengl/qglpaintdevice_p.h +++ b/src/opengl/qglpaintdevice_p.h @@ -76,6 +76,7 @@ public: virtual QGLFormat format() const; virtual QSize size() const = 0; virtual bool alphaRequested() const; + virtual bool isFlipped() const; // returns the QGLPaintDevice for the given QPaintDevice static QGLPaintDevice* getDevice(QPaintDevice*); -- cgit v0.12 From 0bf84a428ab6199ae1bb98460b6a8ffb842cba88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Fri, 21 Jan 2011 15:52:02 +0100 Subject: Making clearer separation between responsibility of different classes Ie. Moving code into different files and refactoring some of the classes. The Drmbuffer was most affected. It has a depth and stencil buffer. QWaylandGLContext contain the context. The drm buffer class has to be bound to the context before used. --- src/plugins/platforms/wayland/qwaylandbuffer.h | 60 +++++ src/plugins/platforms/wayland/qwaylandcursor.cpp | 8 +- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 10 + src/plugins/platforms/wayland/qwaylanddisplay.h | 3 + .../platforms/wayland/qwaylanddrmsurface.cpp | 188 ++++++++------- src/plugins/platforms/wayland/qwaylanddrmsurface.h | 106 +++++++++ .../platforms/wayland/qwaylandglcontext.cpp | 262 ++++++++------------- src/plugins/platforms/wayland/qwaylandglcontext.h | 20 +- .../platforms/wayland/qwaylandinputdevice.cpp | 55 ++++- .../platforms/wayland/qwaylandinputdevice.h | 44 +++- .../platforms/wayland/qwaylandintegration.cpp | 46 +++- .../platforms/wayland/qwaylandshmsurface.cpp | 6 +- src/plugins/platforms/wayland/qwaylandshmsurface.h | 82 +++++++ src/plugins/platforms/wayland/qwaylandwindow.cpp | 27 ++- .../platforms/wayland/qwaylandwindowsurface.h | 121 ---------- src/plugins/platforms/wayland/wayland.pro | 8 +- 16 files changed, 641 insertions(+), 405 deletions(-) create mode 100644 src/plugins/platforms/wayland/qwaylandbuffer.h create mode 100644 src/plugins/platforms/wayland/qwaylanddrmsurface.h create mode 100644 src/plugins/platforms/wayland/qwaylandshmsurface.h delete mode 100644 src/plugins/platforms/wayland/qwaylandwindowsurface.h diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h new file mode 100644 index 0000000..643e89c --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandbuffer.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDBUFFER_H +#define QWAYLANDBUFFER_H + +#include <QtCore/QSize> + +#include <wayland-client-protocol.h> + +class QWaylandBuffer { +public: + QWaylandBuffer() { } + virtual ~QWaylandBuffer() { } + wl_buffer *buffer() {return mBuffer;} + virtual QSize size() const = 0; + +protected: + struct wl_buffer *mBuffer; +}; + +#endif // QWAYLANDBUFFER_H diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 2a1e9a9..f4bae88 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -42,12 +42,12 @@ #include "qwaylandcursor.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandinputdevice.h" +#include "qwaylandshmsurface.h" #include <QtGui/QImageReader> -#define DATADIR "/usr/share" +#define DATADIR "/home/jlind/install/share" static const struct pointer_image { const char *filename; @@ -156,7 +156,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) QImageReader reader(p->filename); - if (mBuffer == NULL || mBuffer->mImage.size() != reader.size()) { + if (mBuffer == NULL || mBuffer->size() != reader.size()) { if (mBuffer) delete mBuffer; @@ -164,7 +164,7 @@ void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) QImage::Format_ARGB32); } - reader.read(&mBuffer->mImage); + reader.read(mBuffer->image()); mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); } diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 8446777..e5adb499 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -304,3 +304,13 @@ QWaylandDisplay::~QWaylandDisplay(void) close(mFd); wl_display_destroy(mDisplay); } + +void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) +{ + wl_display_sync_callback(mDisplay, func, data); +} + +void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) +{ + wl_display_frame_callback(mDisplay, func, data); +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index 7d989a9..a95e9c0 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -78,6 +78,9 @@ public: void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + void syncCallback(wl_display_sync_func_t func, void *data); + void frameCallback(wl_display_frame_func_t func, void *data); + public slots: void eventDispatcher(void); void flushRequests(void); diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index 1a7683e..5803abf 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -38,21 +38,17 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qwaylanddrmsurface.h" -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" -#include <QGLFramebufferObject> #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> #include <QtOpenGL/private/qgl_p.h> #include <QtOpenGL/private/qglpaintdevice_p.h> - -#include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" -#include "qwaylandwindow.h" -#include "qwaylandscreen.h" +#include <QtGui/private/qpaintengine_p.h> #include <wayland-client.h> #include <unistd.h> @@ -65,46 +61,29 @@ QT_BEGIN_NAMESPACE class QWaylandPaintDevice : public QGLPaintDevice { public: - QWaylandPaintDevice(QWaylandDisplay *display, QWidget *widget) - : QGLPaintDevice(), mDisplay(display), mWidget(widget) - { - QGLFormat format; - mContext = new QGLContext(format, widget); - mContext->create(); - } - - QSize size() const { return mWidget->size(); } - QGLContext *context() const { return mContext; } + QWaylandPaintDevice(QWaylandDisplay *display, QWaylandDrmWindowSurface *windowSurface, QPlatformGLContext *context) + : QGLPaintDevice() + , mDisplay(display) + , mPlatformGLContext(context) + , mWindowSurface(windowSurface) + { + } + + QSize size() const { return mWindowSurface->size(); } + QGLContext *context() const { return QGLContext::fromPlatformGLContext(mPlatformGLContext); } + void beginPaint() { mWindowSurface->currentPaintBuffer()->bindToCurrentContext(); } + void ensureActiveTarget() { } + void endPaint() { } QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + bool isFlipped()const {return true;} + - void beginPaint(); - void endPaint(); private: QWaylandDisplay *mDisplay; - QWidget *mWidget; - QGLContext *mContext; -}; - -void QWaylandPaintDevice::beginPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); + QPlatformGLContext *mPlatformGLContext; + QWaylandDrmWindowSurface *mWindowSurface; - QGLPaintDevice::beginPaint(); - - ctx->makeCurrent(); -} - -void QWaylandPaintDevice::endPaint(void) -{ - QWaylandWindow *mWindow = (QWaylandWindow *)mWidget->platformWindow(); - QPlatformGLContext *ctx = mWindow->glContext(); - QRect geometry = mWidget->geometry(); - - ctx->doneCurrent(); - - QGLPaintDevice::endPaint(); -} +}; /* * Shared DRM surface for GL based drawing @@ -117,33 +96,36 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, struct wl_visual *visual; EGLint name, stride; - static const EGLint contextAttribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; + EGLint imageAttribs[] = { - EGL_WIDTH, 0, - EGL_HEIGHT, 0, + EGL_WIDTH, size.width(), + EGL_HEIGHT, size.height(), EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, - EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; - eglBindAPI(EGL_OPENGL_ES_API); - mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, - EGL_NO_CONTEXT, contextAttribs); - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mContext); - - imageAttribs[1] = size.width(); - imageAttribs[3] = size.height(); mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); + glGenFramebuffers(1, &mFbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); + glGenRenderbuffers(1,&mDepthStencil); + glBindRenderbuffer(GL_RENDERBUFFER_EXT,mDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER_EXT, + GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + eglExportDRMImageMESA(mDisplay->eglDisplay(), - mImage, &name, NULL, &stride); + mImage, &name, NULL, &stride); switch (format) { case QImage::Format_ARGB32: @@ -160,6 +142,20 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, mBuffer = display->createDrmBuffer(name, size.width(), size.height(), stride, visual); + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); + + switch(status) { + case GL_NO_ERROR: + case GL_FRAMEBUFFER_COMPLETE_EXT: + qDebug() << "fbo ok"; + break; + default: + qDebug() <<"QWaylandDrmBuffer error: "<< status; + break; + } + QT_CHECK_GLERROR(); + } QWaylandDrmBuffer::~QWaylandDrmBuffer(void) @@ -168,22 +164,31 @@ QWaylandDrmBuffer::~QWaylandDrmBuffer(void) glDeleteTextures(1, &mTexture); eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); wl_buffer_destroy(mBuffer); - eglDestroyContext(mDisplay->eglDisplay(), mContext); } +void QWaylandDrmBuffer::bindToCurrentContext() +{ + Q_ASSERT(QPlatformGLContext::currentContext()); + glViewport(0, 0, size().width(), size().height()); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); + glBindTexture(GL_TEXTURE_2D, mTexture); + glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mTexture, 0); + QT_CHECK_GLERROR(); + +} QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display) : QWindowSurface(window) - , mBuffer(0) + , mBufferList(1) // there is something wrong with the buffer flush. keeping it single buffered for now. + , mCurrentPaintBuffer(0) , mDisplay(display) + , mPaintDevice(new QWaylandPaintDevice(mDisplay, this,window->platformWindow()->glContext())) { - QWaylandWindow *ww = (QWaylandWindow *) window->platformWindow(); - QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - - mPaintDevice = new QWaylandPaintDevice(display, window); - mBuffer = new QWaylandDrmBuffer(mDisplay, window->size(), format); - ww->attach(mBuffer); + for (int i = 0; i < mBufferList.size(); i++) { + mBufferList[i] = 0; + } } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() @@ -191,6 +196,11 @@ QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() delete mPaintDevice; } +void QWaylandDrmWindowSurface::beginPaint(const QRegion &) +{ + window()->platformWindow()->glContext()->makeCurrent(); +} + QPaintDevice *QWaylandDrmWindowSurface::paintDevice() { return mPaintDevice; @@ -200,42 +210,40 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con { Q_UNUSED(offset); QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); - QVector<QRect> rects = region.rects(); - const QRect *r; - int i; - for (i = 0; i < rects.size(); i++) { - r = &rects.at(i); - wl_surface_damage(ww->surface(), - r->x(), r->y(), r->width(), r->height()); + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); i++) { + QRect r = rects.at(i); + wl_surface_damage(ww->surface(), + r.x(), r.y(), r.width(), r.height()); } + + mCurrentPaintBuffer = ++mCurrentPaintBuffer % mBufferList.size(); + ww->attach(currentPaintBuffer()); } void QWaylandDrmWindowSurface::resize(const QSize &requestedSize) { + QWindowSurface::resize(requestedSize); QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); QWaylandScreen *screen = (QWaylandScreen *)QApplicationPrivate::platformIntegration()->screens().first(); QImage::Format format = screen->format(); - QSize screenSize = screen->geometry().size(); - QSize size = requestedSize; - - if (mBuffer != NULL && mBuffer->mSize == size) - return; - - if (mBuffer != NULL) - delete mBuffer; - /* Clamp to screen size */ - if (size.width() > screenSize.width()) - size.setWidth(screenSize.width()); - if (size.height() > screenSize.height()) - size.setHeight(screenSize.height()); + ww->glContext()->makeCurrent(); - QWindowSurface::resize(size); + for (int i = 0; i < mBufferList.size(); i++) { + if (!mBufferList.at(i) || mBufferList.at(i)->size() != requestedSize) { + delete mBufferList[i]; + mBufferList[i] = new QWaylandDrmBuffer(mDisplay, requestedSize, format); + } + } - mBuffer = new QWaylandDrmBuffer(mDisplay, size, format); + ww->attach(currentPaintBuffer()); +} - ww->attach(mBuffer); +QWaylandDrmBuffer * QWaylandDrmWindowSurface::currentPaintBuffer() const +{ + return mBufferList[mCurrentPaintBuffer]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h new file mode 100644 index 0000000..c67f16f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDRMSURFACE_H +#define QWAYLANDDRMSURFACE_H + +#include "qwaylanddisplay.h" +#include "qwaylandbuffer.h" + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtCore/QVarLengthArray> + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#define QT_RESET_GLERROR() \ +{ \ + while (glGetError() != GL_NO_ERROR) {} \ +} +#define QT_CHECK_GLERROR() \ +{ \ + GLenum err = glGetError(); \ + if (err != GL_NO_ERROR) { \ + qDebug("[%s line %d] GL Error: 0x%x", \ + __FILE__, __LINE__, (int)err); \ + } \ +} + +class QWaylandDrmBuffer : public QWaylandBuffer { +public: + QWaylandDrmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandDrmBuffer(); + + void bindToCurrentContext(); + QSize size() const { return mSize; } + +private: + EGLImageKHR mImage; + QWaylandDisplay *mDisplay; + QSize mSize; + GLuint mFbo; + GLuint mTexture; + GLuint mDepthStencil; +}; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandDrmWindowSurface(); + + void beginPaint(const QRegion &); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + + QWaylandDrmBuffer *currentPaintBuffer() const; +private: + QVarLengthArray<QWaylandDrmBuffer *> mBufferList; + int mCurrentPaintBuffer; + QWaylandDisplay *mDisplay; + QPaintDevice *mPaintDevice; +}; + +#endif // QWAYLANDDRMSURFACE_H diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp index 24abcf8..4bf68c4 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.cpp +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -1,25 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandglcontext.h" #include "qwaylanddisplay.h" #include "qwaylandwindow.h" -#include "qwaylandwindowsurface.h" -#include "qfontconfigdatabase.h" - -#include <QImageReader> -#include <QWindowSystemInterface> -#include <QPlatformCursor> -#include <QPaintEngine> +#include "qwaylanddrmsurface.h" #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> -#include <QtGui/private/qpixmap_raster_p.h> -#include <QtGui/QPlatformWindow> - -#include <private/qwindowsurface_gl_p.h> -#include <private/qpixmapdata_gl_p.h> -#include <private/qpaintengineex_opengl2_p.h> - #include <unistd.h> #include <fcntl.h> @@ -27,165 +55,80 @@ extern "C" { #include <xf86drm.h> } -QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format) +Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex); + +EGLint QWaylandGLContext::contextAttibutes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE +}; + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) : QPlatformGLContext() , mFormat(format) , mDisplay(wd) - , mWindow(window) - , parentFbo(0) - , parentRbo(0) { + QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (qt_defaultSharedContextMutex()->tryLock()){ + createDefaultSharedContex(wd); + qt_defaultSharedContextMutex()->unlock(); + } else { + qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created + qt_defaultSharedContextMutex()->unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + mFormat.setSharedContext(sharePlatformContext); + EGLContext shareEGLContext = EGL_NO_CONTEXT; + if (sharePlatformContext) + shareEGLContext = static_cast<const QWaylandGLContext*>(sharePlatformContext)->mContext; + + eglBindAPI(EGL_OPENGL_ES_API); + mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + shareEGLContext, contextAttibutes); + + mFormat.setAccum(false); + mFormat.setAlphaBufferSize(8); + mFormat.setRedBufferSize(8); + mFormat.setGreenBufferSize(8); + mFormat.setBlueBufferSize(8); + mFormat.setDepth(false); +// mFormat.setDepthBufferSize(8); + mFormat.setStencil(false); +// mFormat.setStencilBufferSize(24); +// mFormat.setSampleBuffers(false); + } +QWaylandGLContext::QWaylandGLContext() + : QPlatformGLContext() + , mDisplay(0) + , mContext(EGL_NO_CONTEXT) +{ } + QWaylandGLContext::~QWaylandGLContext() { - glDeleteRenderbuffers(1, &parentRbo); - glDeleteFramebuffers(1, &parentFbo); + eglDestroyContext(mDisplay->eglDisplay(),mContext); } void QWaylandGLContext::makeCurrent() { - QWaylandDrmBuffer *mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - QRect geometry = mWindow->geometry(); - - if (!mBuffer) - return; - - eglMakeCurrent(mDisplay->eglDisplay(), 0, 0, mBuffer->mContext); - - glViewport(0, 0, geometry.width(), geometry.height()); - glBindFramebuffer(GL_FRAMEBUFFER, mBuffer->mFbo); - glBindTexture(GL_TEXTURE_2D, mBuffer->mTexture); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, mBuffer->mTexture, 0); + QPlatformGLContext::makeCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, mContext); } void QWaylandGLContext::doneCurrent() { -} - -/* drawTexture - Draw from a texture into a the current framebuffer - * @rect: GL normalized coords for drawing (between -1.0f and 1.0f) - * @tex_id: texture source - * @texSize: size of source rectangle in Qt coords - * @br: bounding rect for drawing - */ -static void drawTexture(const QRectF &rect, GLuint tex_id, - const QSize &texSize, const QRectF &br) -{ - QRectF src = br.isEmpty() - ? QRectF(QPointF(), texSize) - : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); - qreal width = texSize.width(); - qreal height = texSize.height(); - - src.setLeft(src.left() / width); - src.setRight(src.right() / width); - src.setTop(src.top() / height); - src.setBottom(src.bottom() / height); - - const GLfloat tx1 = src.left(); - const GLfloat tx2 = src.right(); - const GLfloat ty1 = src.top(); - const GLfloat ty2 = src.bottom(); - - GLfloat texCoordArray[4*2] = { - tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 - }; - - GLfloat vertexArray[4*2]; - extern void qt_add_rect_to_array(const QRectF &r, GLfloat *array); - qt_add_rect_to_array(rect, vertexArray); - - glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); - glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); - - glBindTexture(GL_TEXTURE_2D, tex_id); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); - glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); - - glBindTexture(GL_TEXTURE_2D, 0); + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } void QWaylandGLContext::swapBuffers() { - QWaylandWindow *mParentWindow = mWindow->getParentWindow(); - QWaylandDrmBuffer *mBuffer, *mParentBuffer; - QRect geometry = mWindow->geometry(), parentGeometry; - QGLShaderProgram *blitProgram; - QRectF r; - qreal w; - qreal h; - - if (!mParentWindow) { - qDebug("swap without parent widget?\n"); - return; - } - - if (!mParentWindow->surface()) { - qDebug("parent has no surface??\n"); - return; - } - - parentGeometry = mParentWindow->geometry(); - mBuffer = (QWaylandDrmBuffer *)mWindow->getBuffer(); - mParentBuffer = (QWaylandDrmBuffer *)mParentWindow->getBuffer(); - - glDisable(GL_DEPTH_TEST); - - /* These need to be generated against the src context */ - if (!parentFbo) - glGenFramebuffers(1, &parentFbo); - if (!parentRbo) - glGenRenderbuffers(1, &parentRbo); - - glBindFramebuffer(GL_FRAMEBUFFER, parentFbo); - glBindRenderbuffer(GL_RENDERBUFFER, parentRbo); - glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - mParentBuffer->mImage); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, parentRbo); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mBuffer->mImage); - glViewport(0, 0, parentGeometry.width(), parentGeometry.height()); - - blitProgram = QGLEngineSharedShaders::shadersForContext(QGLContext::currentContext())->blitProgram(); - blitProgram->bind(); - blitProgram->setUniformValue("imageTexture", 0); - - /* Transform the target rect to the appropriate coords on the parent */ - w = parentGeometry.width(); - h = parentGeometry.height(); - - r.setLeft((geometry.left() / w) * 2.0f - 1.0f); - if (geometry.right() == (parentGeometry.width() - 1)) - r.setRight(1.0f); - else - r.setRight((geometry.right() / w) * 2.0f - 1.0f); - - r.setTop((geometry.top() / h) * 2.0f - 1.0f); - if (geometry.bottom() == (parentGeometry.height() - 1)) - r.setBottom(-1.0f); - else - r.setBottom((geometry.bottom() / h) * 2.0f - 1.0f); - - drawTexture(r, mBuffer->mTexture, mParentWindow->widget()->size(), parentGeometry); - - wl_surface_damage(mParentWindow->surface(), geometry.left(), geometry.top(), - geometry.right(), geometry.bottom()); - /* restore things to the last valid GL state */ - makeCurrent(); - /* hack: avoid tight swapBuffers loops */ - usleep(20000); } void *QWaylandGLContext::getProcAddress(const QString &string) @@ -193,13 +136,12 @@ void *QWaylandGLContext::getProcAddress(const QString &string) return (void *) eglGetProcAddress(string.toLatin1().data()); } -QPlatformGLContext *QWaylandWindow::glContext() const +void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display) { - if (!mGLContext) { - QWaylandWindow *that = const_cast<QWaylandWindow *>(this); - that->mGLContext = new QWaylandGLContext(mDisplay, that, widget()->platformWindowFormat()); - } - - return mGLContext; + QWaylandGLContext *defaultSharedContext = new QWaylandGLContext; + defaultSharedContext->mDisplay = display; + defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(), NULL, + EGL_NO_CONTEXT, contextAttibutes); + QPlatformGLContext::setDefaultSharedContext(defaultSharedContext); } diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/qwaylandglcontext.h index 6e3c108..d9ba323 100644 --- a/src/plugins/platforms/wayland/qwaylandglcontext.h +++ b/src/plugins/platforms/wayland/qwaylandglcontext.h @@ -44,16 +44,19 @@ #include <QtGui/QPlatformGLContext> +#include <QtCore/QMutex> class QWaylandDisplay; class QWaylandWindow; +class QWaylandDrmWindowSurface; -#define GL_GLEXT_PROTOTYPES -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> class QWaylandGLContext : public QPlatformGLContext { public: - QWaylandGLContext(QWaylandDisplay *wd, QWaylandWindow *window, const QPlatformWindowFormat &format); + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); ~QWaylandGLContext(); void makeCurrent(); void doneCurrent(); @@ -64,8 +67,13 @@ public: private: QPlatformWindowFormat mFormat; QWaylandDisplay *mDisplay; - QWaylandWindow *mWindow; - GLuint parentFbo, parentRbo; + + static EGLint contextAttibutes[]; + EGLContext mContext; + + void createDefaultSharedContex(QWaylandDisplay *display); + QWaylandGLContext(); + }; diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 77c5815..03edc07 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -1,8 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandinputdevice.h" #include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" #include "qwaylandwindow.h" +#include "qwaylandbuffer.h" #include <QWindowSystemInterface> @@ -197,10 +238,12 @@ void QWaylandInputDevice::inputHandleKey(void *data, qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", code, sym, s[0], (int) inputDevice->mModifiers); - QWindowSystemInterface::handleKeyEvent(window->widget(), - time, type, sym, - inputDevice->mModifiers, - QString::fromLatin1(s)); + if (window) { + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); + } } void QWaylandInputDevice::inputHandlePointerFocus(void *data, @@ -264,5 +307,5 @@ const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) { - wl_input_device_attach(mInputDevice, mTime, buffer->mBuffer, x, y); + wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y); } diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h index 749ef70..2328db8 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.h +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -1,13 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QWAYLANDINPUTDEVICE_H #define QWAYLANDINPUTDEVICE_H +#include "qwaylandwindow.h" + #include <QSocketNotifier> #include <QObject> #include <QtGui/QPlatformIntegration> #include <QtGui/QPlatformScreen> #include <wayland-client.h> -#include "qwaylandwindowsurface.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index a6fdc2e..e647880 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,7 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qwaylandintegration.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" +#include "qwaylandshmsurface.h" +#include "qwaylanddrmsurface.h" #include "qwaylandwindow.h" #include "qfontconfigdatabase.h" @@ -29,7 +71,7 @@ QWaylandIntegration::screens() const QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const { if (mUseOpenGL) - return new QGLPixmapData(type); + return new QGLPixmapData(type); return new QRasterPixmapData(type); } diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp index 1c3a26c..7112424 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -38,12 +38,12 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include "qwaylandshmsurface.h" #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandwindow.h" #include <wayland-client.h> @@ -104,7 +104,7 @@ QWaylandShmWindowSurface::~QWaylandShmWindowSurface() QPaintDevice *QWaylandShmWindowSurface::paintDevice() { - return &mBuffer->mImage; + return mBuffer->image(); } void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) @@ -129,7 +129,7 @@ void QWaylandShmWindowSurface::resize(const QSize &size) QWindowSurface::resize(size); QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); - if (mBuffer != NULL && mBuffer->mImage.size() == size) + if (mBuffer != NULL && mBuffer->size() == size) return; if (mBuffer != NULL) diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h new file mode 100644 index 0000000..8c24e9f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_WAYLAND_H +#define QWINDOWSURFACE_WAYLAND_H + +#include "qwaylandbuffer.h" +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QWaylandDisplay; + +class QWaylandShmBuffer : public QWaylandBuffer { +public: + QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandShmBuffer(); + QSize size() const { return mImage.size(); } + QImage *image() { return &mImage; } +private: + QImage mImage; +}; + +class QWaylandShmWindowSurface : public QWindowSurface +{ +public: + QWaylandShmWindowSurface(QWidget *window, QWaylandDisplay *display); + ~QWaylandShmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 4f696b0..fa62330 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -42,15 +42,19 @@ #include "qwaylandwindow.h" #include "qwaylanddisplay.h" -#include "qwaylandwindowsurface.h" #include "qwaylandglcontext.h" +#include "qwaylandbuffer.h" + +#include "qwaylanddrmsurface.h" #include <QtGui/QWidget> #include <QtGui/QWindowSystemInterface> +#include <QDebug> + QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) : QPlatformWindow(window) - , mSurface(0) + , mSurface(display->createSurface()) , mDisplay(display) , mGLContext(0) , mBuffer(0) @@ -81,9 +85,8 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent) void QWaylandWindow::setVisible(bool visible) { if (visible) { - mSurface = mDisplay->createSurface(); wl_surface_set_user_data(mSurface, this); - attach(mBuffer); + wl_surface_map_toplevel(mSurface); } else { wl_surface_destroy(mSurface); mSurface = NULL; @@ -92,12 +95,8 @@ void QWaylandWindow::setVisible(bool visible) void QWaylandWindow::attach(QWaylandBuffer *buffer) { - QRect geometry = widget()->geometry(); - - mBuffer = buffer; if (mSurface) { - wl_surface_attach(mSurface, mBuffer->mBuffer,geometry.x(),geometry.y()); - wl_surface_map_toplevel(mSurface); + wl_surface_attach(mSurface, buffer->buffer(),0,0); } } @@ -111,3 +110,13 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast<QWaylandWindow *>(this); + that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + } + + return mGLContext; +} diff --git a/src/plugins/platforms/wayland/qwaylandwindowsurface.h b/src/plugins/platforms/wayland/qwaylandwindowsurface.h deleted file mode 100644 index db57619..0000000 --- a/src/plugins/platforms/wayland/qwaylandwindowsurface.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenVG module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** 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, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QWINDOWSURFACE_WAYLAND_H -#define QWINDOWSURFACE_WAYLAND_H - -#include <QGLFramebufferObject> -#include <QtGui/private/qwindowsurface_p.h> - -#include <QtGui/QPlatformWindow> - -#define MESA_EGL_NO_X11_HEADERS -#define EGL_EGLEXT_PROTOTYPES -#include <EGL/egl.h> -#include <EGL/eglext.h> - -QT_BEGIN_NAMESPACE - -class QWaylandDisplay; - -class QWaylandBuffer { -public: - QWaylandBuffer() { } - virtual ~QWaylandBuffer() { } - struct wl_buffer *mBuffer; -}; - -class QWaylandShmBuffer : public QWaylandBuffer { -public: - QWaylandShmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format); - ~QWaylandShmBuffer(); - QImage mImage; -}; - -class QWaylandShmWindowSurface : public QWindowSurface -{ -public: - QWaylandShmWindowSurface(QWidget *window, QWaylandDisplay *display); - ~QWaylandShmWindowSurface(); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size); - -private: - QWaylandShmBuffer *mBuffer; - QWaylandDisplay *mDisplay; -}; - -class QWaylandDrmBuffer : public QWaylandBuffer { -public: - QWaylandDrmBuffer(QWaylandDisplay *display, - const QSize &size, QImage::Format format); - ~QWaylandDrmBuffer(); - EGLContext mContext; - EGLImageKHR mImage; - GLuint mTexture; - QWaylandDisplay *mDisplay; - QSize mSize; - GLuint mFbo; -}; - -class QWaylandDrmWindowSurface : public QWindowSurface -{ -public: - QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); - ~QWaylandDrmWindowSurface(); - - QPaintDevice *paintDevice(); - void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size); - -private: - QWaylandDrmBuffer *mBuffer; - QWaylandDisplay *mDisplay; - QPaintDevice *mPaintDevice; -}; - - -QT_END_NAMESPACE - -#endif diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index 784a248..8ba1408 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -15,17 +15,19 @@ SOURCES = main.cpp \ qwaylandscreen.cpp HEADERS = qwaylandintegration.h \ - qwaylandwindowsurface.h \ qwaylandcursor.h \ qwaylanddisplay.h \ qwaylandwindow.h \ qwaylandscreen.h \ - qwaylandglcontext.h + qwaylandglcontext.h \ + qwaylandshmsurface.h \ + qwaylanddrmsurface.h \ + qwaylandbuffer.h contains(QT_CONFIG, opengl) { QT += opengl } -LIBS += -lwayland-client -lxkbcommon -lEGL -lGLESv2 +LIBS += -lwayland-client -lxkbcommon -lEGL unix { CONFIG += link_pkgconfig PKGCONFIG += libdrm -- cgit v0.12 From 2d65cd502fb5508426748d9ef7af4697051f1c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Tue, 25 Jan 2011 14:48:25 +0100 Subject: Lighthouse: Wayland, only make one fbo for the WaylandPaintDevice Actually the fbo belongs to the QWaylandPaintDevice, which also holds n QWaylandDrmBuffers. Then the QWaylandDrmWindowSurface gets the current drmbuffer used on flush and attaches it to the window and calls wl_surface_damage --- .../platforms/wayland/qwaylanddrmsurface.cpp | 185 ++++++++++++--------- src/plugins/platforms/wayland/qwaylanddrmsurface.h | 40 ++++- 2 files changed, 138 insertions(+), 87 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index 5803abf..0725919 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -47,7 +47,6 @@ #include <QtCore/qdebug.h> #include <QtGui/private/qapplication_p.h> #include <QtOpenGL/private/qgl_p.h> -#include <QtOpenGL/private/qglpaintdevice_p.h> #include <QtGui/private/qpaintengine_p.h> #include <wayland-client.h> @@ -58,33 +57,6 @@ QT_BEGIN_NAMESPACE -class QWaylandPaintDevice : public QGLPaintDevice -{ -public: - QWaylandPaintDevice(QWaylandDisplay *display, QWaylandDrmWindowSurface *windowSurface, QPlatformGLContext *context) - : QGLPaintDevice() - , mDisplay(display) - , mPlatformGLContext(context) - , mWindowSurface(windowSurface) - { - } - - QSize size() const { return mWindowSurface->size(); } - QGLContext *context() const { return QGLContext::fromPlatformGLContext(mPlatformGLContext); } - void beginPaint() { mWindowSurface->currentPaintBuffer()->bindToCurrentContext(); } - void ensureActiveTarget() { } - void endPaint() { } - QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } - bool isFlipped()const {return true;} - - -private: - QWaylandDisplay *mDisplay; - QPlatformGLContext *mPlatformGLContext; - QWaylandDrmWindowSurface *mWindowSurface; - -}; - /* * Shared DRM surface for GL based drawing */ @@ -94,9 +66,7 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, , mSize(size) { struct wl_visual *visual; - EGLint name, stride; - EGLint imageAttribs[] = { EGL_WIDTH, size.width(), EGL_HEIGHT, size.height(), @@ -107,23 +77,11 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, mImage = eglCreateDRMImageMESA(mDisplay->eglDisplay(), imageAttribs); - glGenFramebuffers(1, &mFbo); - glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); glGenTextures(1, &mTexture); glBindTexture(GL_TEXTURE_2D, mTexture); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mImage); - glGenRenderbuffers(1,&mDepthStencil); - glBindRenderbuffer(GL_RENDERBUFFER_EXT,mDepthStencil); - glRenderbufferStorage(GL_RENDERBUFFER_EXT, - GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); - glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, mDepthStencil); - glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, mDepthStencil); - eglExportDRMImageMESA(mDisplay->eglDisplay(), mImage, &name, NULL, &stride); @@ -142,6 +100,99 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, mBuffer = display->createDrmBuffer(name, size.width(), size.height(), stride, visual); +} + +QWaylandDrmBuffer::~QWaylandDrmBuffer(void) +{ + glDeleteTextures(1, &mTexture); + eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); + wl_buffer_destroy(mBuffer); +} + +void QWaylandDrmBuffer::bindToCurrentFbo() +{ + Q_ASSERT(QPlatformGLContext::currentContext()); + glBindTexture(GL_TEXTURE_2D, mTexture); + glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, mTexture, 0); + QT_CHECK_GLERROR(); +} + +QWaylandPaintDevice::QWaylandPaintDevice(QWaylandDisplay *display, QWindowSurface *windowSurface, QPlatformGLContext *context) + : QGLPaintDevice() + , mDisplay(display) + , mPlatformGLContext(context) + , mWindowSurface(windowSurface) + , mBufferList(1) + , mCurrentPaintBuffer(0) + , mDepthStencil(0) +{ + for (int i = 0; i < mBufferList.size(); i++) { + mBufferList[i] = 0; + } + + mPlatformGLContext->makeCurrent(); + glGenFramebuffers(1, &m_thisFBO); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO); + + if (windowSurface->size().isValid()) + resize(windowSurface->size()); +} + +QWaylandPaintDevice::~QWaylandPaintDevice() +{ + for(int i = 0; i < mBufferList.size(); i++) { + delete mBufferList[i]; + } + glDeleteRenderbuffers(1,&mDepthStencil); + glDeleteFramebuffers(1,&m_thisFBO); +} + +QSize QWaylandPaintDevice::size() const +{ + return mSize; +} +QGLContext *QWaylandPaintDevice::context() const +{ + return QGLContext::fromPlatformGLContext(mPlatformGLContext); +} +QPaintEngine *QWaylandPaintDevice::paintEngine() const +{ + return qt_qgl_paint_engine(); +} + +void QWaylandPaintDevice::beginPaint() +{ + QGLPaintDevice::beginPaint(); + currentDrmBuffer()->bindToCurrentFbo(); +} + +bool QWaylandPaintDevice::isFlipped()const +{ + return true; +} + +void QWaylandPaintDevice::resize(const QSize &size) +{ + QImage::Format format = QPlatformScreen::platformScreenForWidget(mWindowSurface->window())->format(); + mPlatformGLContext->makeCurrent(); + mSize = size; + for (int i = 0; i < mBufferList.size(); i++) { + if (!mBufferList.at(i) || mBufferList.at(i)->size() != size) { + delete mBufferList[i]; + mBufferList[i] = new QWaylandDrmBuffer(mDisplay, size, format); + } + } + + glDeleteRenderbuffers(1,&mDepthStencil); + glGenRenderbuffers(1,&mDepthStencil); + glBindRenderbuffer(GL_RENDERBUFFER_EXT,mDepthStencil); + glRenderbufferStorage(GL_RENDERBUFFER_EXT, + GL_DEPTH24_STENCIL8_EXT, size.width(), size.height()); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); + glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, mDepthStencil); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); @@ -155,40 +206,26 @@ QWaylandDrmBuffer::QWaylandDrmBuffer(QWaylandDisplay *display, break; } QT_CHECK_GLERROR(); - } -QWaylandDrmBuffer::~QWaylandDrmBuffer(void) +QWaylandDrmBuffer *QWaylandPaintDevice::currentDrmBuffer() const { - glDeleteFramebuffers(1, &mFbo); - glDeleteTextures(1, &mTexture); - eglDestroyImageKHR(mDisplay->eglDisplay(), mImage); - wl_buffer_destroy(mBuffer); + return mBufferList[mCurrentPaintBuffer]; } - -void QWaylandDrmBuffer::bindToCurrentContext() +QWaylandDrmBuffer *QWaylandPaintDevice::currentDrmBufferAndSwap() { - Q_ASSERT(QPlatformGLContext::currentContext()); - glViewport(0, 0, size().width(), size().height()); - glBindFramebuffer(GL_FRAMEBUFFER_EXT, mFbo); - glBindTexture(GL_TEXTURE_2D, mTexture); - glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, mTexture, 0); - QT_CHECK_GLERROR(); - + QWaylandDrmBuffer *currentDrmBuffer = mBufferList[mCurrentPaintBuffer]; + mCurrentPaintBuffer = (mCurrentPaintBuffer +1) % mBufferList.size(); + return currentDrmBuffer; } QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display) : QWindowSurface(window) - , mBufferList(1) // there is something wrong with the buffer flush. keeping it single buffered for now. - , mCurrentPaintBuffer(0) , mDisplay(display) , mPaintDevice(new QWaylandPaintDevice(mDisplay, this,window->platformWindow()->glContext())) { - for (int i = 0; i < mBufferList.size(); i++) { - mBufferList[i] = 0; - } + } QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() @@ -211,39 +248,25 @@ void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, con Q_UNUSED(offset); QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); + ww->attach(mPaintDevice->currentDrmBufferAndSwap()); + QVector<QRect> rects = region.rects(); for (int i = 0; i < rects.size(); i++) { QRect r = rects.at(i); wl_surface_damage(ww->surface(), r.x(), r.y(), r.width(), r.height()); } - - mCurrentPaintBuffer = ++mCurrentPaintBuffer % mBufferList.size(); - ww->attach(currentPaintBuffer()); } void QWaylandDrmWindowSurface::resize(const QSize &requestedSize) { QWindowSurface::resize(requestedSize); QWaylandWindow *ww = (QWaylandWindow *) window()->platformWindow(); - QWaylandScreen *screen = (QWaylandScreen *)QApplicationPrivate::platformIntegration()->screens().first(); - QImage::Format format = screen->format(); ww->glContext()->makeCurrent(); - for (int i = 0; i < mBufferList.size(); i++) { - if (!mBufferList.at(i) || mBufferList.at(i)->size() != requestedSize) { - delete mBufferList[i]; - mBufferList[i] = new QWaylandDrmBuffer(mDisplay, requestedSize, format); - } - } - - ww->attach(currentPaintBuffer()); -} - -QWaylandDrmBuffer * QWaylandDrmWindowSurface::currentPaintBuffer() const -{ - return mBufferList[mCurrentPaintBuffer]; + mPaintDevice->resize(requestedSize); + ww->attach(mPaintDevice->currentDrmBuffer()); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h index c67f16f..aa3dbe7 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.h +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -47,6 +47,7 @@ #include <QtGui/private/qwindowsurface_p.h> #include <QtCore/QVarLengthArray> +#include <QtOpenGL/private/qglpaintdevice_p.h> #define GL_GLEXT_PROTOTYPES #include <GLES2/gl2.h> @@ -71,16 +72,45 @@ public: const QSize &size, QImage::Format format); ~QWaylandDrmBuffer(); - void bindToCurrentContext(); + void bindToCurrentFbo(); QSize size() const { return mSize; } private: EGLImageKHR mImage; QWaylandDisplay *mDisplay; QSize mSize; - GLuint mFbo; GLuint mTexture; + +}; + +class QWaylandPaintDevice : public QGLPaintDevice +{ +public: + QWaylandPaintDevice(QWaylandDisplay *display, QWindowSurface *windowSurface, QPlatformGLContext *context); + ~QWaylandPaintDevice(); + + QSize size() const; + QGLContext *context() const; + QPaintEngine *paintEngine() const; + + void beginPaint(); + + bool isFlipped()const; + + void resize(const QSize &size); + + QWaylandDrmBuffer *currentDrmBuffer() const; + QWaylandDrmBuffer *currentDrmBufferAndSwap(); + +private: + QWaylandDisplay *mDisplay; + QPlatformGLContext *mPlatformGLContext; + QWindowSurface *mWindowSurface; + QVarLengthArray<QWaylandDrmBuffer *> mBufferList; + int mCurrentPaintBuffer; GLuint mDepthStencil; + QSize mSize; + }; class QWaylandDrmWindowSurface : public QWindowSurface @@ -95,12 +125,10 @@ public: void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size); - QWaylandDrmBuffer *currentPaintBuffer() const; private: - QVarLengthArray<QWaylandDrmBuffer *> mBufferList; - int mCurrentPaintBuffer; + QWaylandDisplay *mDisplay; - QPaintDevice *mPaintDevice; + QWaylandPaintDevice *mPaintDevice; }; #endif // QWAYLANDDRMSURFACE_H -- cgit v0.12 From d36a3a6ebc17935371cfca2a9f22dcd683205b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Tue, 25 Jan 2011 17:01:21 +0100 Subject: Lighthouse: Wayland. Make the wayland integration closer to Lighthosue Today there is a connection between QWidget and QPlatformScreen. So I added a accessor in QWaylandScreen to get the corresponding QWaylandDisplay. So now it should be possible to have different QWaylandDisplays. But also its possible to use the internal Lighthouse api closer in the wayland plugin if that should be of interest ;) --- src/plugins/platforms/wayland/qwaylandcursor.cpp | 8 ++++ src/plugins/platforms/wayland/qwaylandcursor.h | 6 +-- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 21 +++++------ src/plugins/platforms/wayland/qwaylanddisplay.h | 5 ++- .../platforms/wayland/qwaylanddrmsurface.cpp | 5 +-- src/plugins/platforms/wayland/qwaylanddrmsurface.h | 2 +- .../platforms/wayland/qwaylandintegration.cpp | 6 +-- src/plugins/platforms/wayland/qwaylandscreen.cpp | 44 ++++++++++++++++++++++ src/plugins/platforms/wayland/qwaylandscreen.h | 22 ++++++++--- .../platforms/wayland/qwaylandshmsurface.cpp | 6 +-- src/plugins/platforms/wayland/qwaylandshmsurface.h | 2 +- src/plugins/platforms/wayland/qwaylandwindow.cpp | 9 +++-- src/plugins/platforms/wayland/qwaylandwindow.h | 2 +- 13 files changed, 99 insertions(+), 39 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index f4bae88..29c6abd 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -44,6 +44,7 @@ #include "qwaylanddisplay.h" #include "qwaylandinputdevice.h" #include "qwaylandshmsurface.h" +#include "qwaylandscreen.h" #include <QtGui/QImageReader> @@ -100,6 +101,13 @@ static const struct pointer_image { { DATADIR "/wayland/dnd-link.png", 13, 13 }, }; +QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) + : QPlatformCursor(screen) + , mBuffer(0) + , mDisplay(screen->display()) +{ +} + void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) { const struct pointer_image *p; diff --git a/src/plugins/platforms/wayland/qwaylandcursor.h b/src/plugins/platforms/wayland/qwaylandcursor.h index 8c9d263..19e6047 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.h +++ b/src/plugins/platforms/wayland/qwaylandcursor.h @@ -46,13 +46,11 @@ class QWaylandShmBuffer; class QWaylandDisplay; +class QWaylandScreen; class QWaylandCursor : QPlatformCursor { public: - QWaylandCursor(QWaylandDisplay *display, - QPlatformScreen *screen) - : QPlatformCursor(screen) - , mBuffer(0), mDisplay(display) { } + QWaylandCursor(QWaylandScreen *screen); void changeCursor(QCursor *cursor, QWidget *widget); QWaylandShmBuffer *mBuffer; diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index e5adb499..70713ec 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -169,19 +169,10 @@ void QWaylandDisplay::outputHandleGeometry(void *data, int32_t x, int32_t y, int32_t width, int32_t height) { - Q_UNUSED(output); - QWaylandDisplay *qwd = (QWaylandDisplay *) data; - QWaylandScreen *screen; - - screen = new QWaylandScreen(); - screen->mGeometry = QRect(x, y, width, height); - screen->mDepth = 32; - screen->mFormat = QImage::Format_ARGB32_Premultiplied; - screen->mOutput = output; - - new QWaylandCursor(qwd, screen); + QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data; - qwd->mScreens.append(screen); + QRect outputRect = QRect(x, y, width, height); + waylandDisplay->createNewScreen(output, outputRect); } const struct wl_output_listener QWaylandDisplay::outputListener = { @@ -305,6 +296,12 @@ QWaylandDisplay::~QWaylandDisplay(void) wl_display_destroy(mDisplay); } +void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry) +{ + QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry); + mScreens.append(waylandScreen); +} + void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) { wl_display_sync_callback(mDisplay, func, data); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h index a95e9c0..f179713 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -43,6 +43,7 @@ #define QWAYLANDDISPLAY_H #include <QtCore/QObject> +#include <QtCore/QRect> #include <wayland-client.h> @@ -55,14 +56,16 @@ class QWaylandInputDevice; class QSocketNotifier; class QWaylandBuffer; class QPlatformScreen; +class QWaylandScreen; class QWaylandDisplay : public QObject { - Q_OBJECT; + Q_OBJECT public: QWaylandDisplay(void); ~QWaylandDisplay(void); + void createNewScreen(struct wl_output *output, QRect geometry); QList<QPlatformScreen *> screens() const { return mScreens; } struct wl_surface *createSurface(); struct wl_buffer *createShmBuffer(int fd, int width, int height, diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp index 0725919..76c8c33 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -219,10 +219,9 @@ QWaylandDrmBuffer *QWaylandPaintDevice::currentDrmBufferAndSwap() return currentDrmBuffer; } -QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window, - QWaylandDisplay *display) +QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window) : QWindowSurface(window) - , mDisplay(display) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) , mPaintDevice(new QWaylandPaintDevice(mDisplay, this,window->platformWindow()->glContext())) { diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h index aa3dbe7..eafea13 100644 --- a/src/plugins/platforms/wayland/qwaylanddrmsurface.h +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -116,7 +116,7 @@ private: class QWaylandDrmWindowSurface : public QWindowSurface { public: - QWaylandDrmWindowSurface(QWidget *window, QWaylandDisplay *display); + QWaylandDrmWindowSurface(QWidget *window); ~QWaylandDrmWindowSurface(); void beginPaint(const QRegion &); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index e647880..02bc680 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -80,7 +80,7 @@ QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); - return new QWaylandWindow(widget, mDisplay); + return new QWaylandWindow(widget); } QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const @@ -89,8 +89,8 @@ QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId wi Q_UNUSED(winId); if (mUseOpenGL) - return new QWaylandDrmWindowSurface(widget, mDisplay); - return new QWaylandShmWindowSurface(widget, mDisplay); + return new QWaylandDrmWindowSurface(widget); + return new QWaylandShmWindowSurface(widget); } QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 4a7e727..aa1083f 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -41,3 +41,47 @@ #include "qwaylandscreen.h" +#include "qwaylanddisplay.h" +#include "qwaylandcursor.h" + +QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry) + : QPlatformScreen() + , mWaylandDisplay(waylandDisplay) + , mOutput(output) + , mGeometry(geometry) + , mDepth(32) + , mFormat(QImage::Format_ARGB32_Premultiplied) + , mWaylandCursor(new QWaylandCursor(this)) +{ +} + +QWaylandScreen::~QWaylandScreen() +{ + delete mWaylandCursor; +} + +QWaylandDisplay * QWaylandScreen::display() const +{ + return mWaylandDisplay; +} + +QRect QWaylandScreen::geometry() const +{ + return mGeometry; +} + +int QWaylandScreen::depth() const +{ + return mDepth; +} + +QImage::Format QWaylandScreen::format() const +{ + return mFormat; +} + +QWaylandScreen * QWaylandScreen::waylandScreenFromWidget(QWidget *widget) +{ + QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWidget(widget); + return static_cast<QWaylandScreen *>(platformScreen); +} diff --git a/src/plugins/platforms/wayland/qwaylandscreen.h b/src/plugins/platforms/wayland/qwaylandscreen.h index 808266e..368859f 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.h +++ b/src/plugins/platforms/wayland/qwaylandscreen.h @@ -44,21 +44,31 @@ #include <QtGui/QPlatformScreen> +class QWaylandDisplay; +class QWaylandCursor; + class QWaylandScreen : public QPlatformScreen { public: - QWaylandScreen() {} + QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry); + ~QWaylandScreen(); - QRect geometry() const { return mGeometry; } - int depth() const { return mDepth; } - QImage::Format format() const { return mFormat; } + QWaylandDisplay *display() const; -public: + QRect geometry() const; + int depth() const; + QImage::Format format() const; + + static QWaylandScreen *waylandScreenFromWidget(QWidget *widget); + +private: + QWaylandDisplay *mWaylandDisplay; + struct wl_output *mOutput; QRect mGeometry; int mDepth; QImage::Format mFormat; QSize mPhysicalSize; - struct wl_output *mOutput; + QWaylandCursor *mWaylandCursor; }; #endif // QWAYLANDSCREEN_H diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp index 7112424..83bb993 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -45,6 +45,7 @@ #include "qwaylanddisplay.h" #include "qwaylandwindow.h" +#include "qwaylandscreen.h" #include <wayland-client.h> #include <unistd.h> @@ -90,11 +91,10 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void) wl_buffer_destroy(mBuffer); } -QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window, - QWaylandDisplay *display) +QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window) : QWindowSurface(window) , mBuffer(0) - , mDisplay(display) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) { } diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h index 8c24e9f..266b290 100644 --- a/src/plugins/platforms/wayland/qwaylandshmsurface.h +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -65,7 +65,7 @@ private: class QWaylandShmWindowSurface : public QWindowSurface { public: - QWaylandShmWindowSurface(QWidget *window, QWaylandDisplay *display); + QWaylandShmWindowSurface(QWidget *window); ~QWaylandShmWindowSurface(); QPaintDevice *paintDevice(); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index fa62330..a28bdfe 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -42,6 +42,7 @@ #include "qwaylandwindow.h" #include "qwaylanddisplay.h" +#include "qwaylandscreen.h" #include "qwaylandglcontext.h" #include "qwaylandbuffer.h" @@ -52,16 +53,16 @@ #include <QDebug> -QWaylandWindow::QWaylandWindow(QWidget *window, QWaylandDisplay *display) +QWaylandWindow::QWaylandWindow(QWidget *window) : QPlatformWindow(window) - , mSurface(display->createSurface()) - , mDisplay(display) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) , mGLContext(0) , mBuffer(0) { static WId id = 1; - mWindowId = id++; + + mSurface = mDisplay->createSurface(); } QWaylandWindow::~QWaylandWindow() diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h index d5cc923..8b047d7 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.h +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -52,7 +52,7 @@ class QWaylandBuffer; class QWaylandWindow : public QPlatformWindow { public: - QWaylandWindow(QWidget *window, QWaylandDisplay *display); + QWaylandWindow(QWidget *window); ~QWaylandWindow(); struct wl_surface *surface() { return mSurface; } -- cgit v0.12 From de5b07606c1fbc2330efc6915ad7d1ac866752f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Wed, 26 Jan 2011 13:03:27 +0100 Subject: Make sure we blit the fbo on flush in QGLWindowSurface Reviewed-by: sroedal --- src/opengl/qwindowsurface_gl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index ea5e9a7..04cc358 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -473,6 +473,8 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, void QGLWindowSurface::beginPaint(const QRegion &) { + d_ptr->did_paint = true; + if (!context()) return; @@ -487,8 +489,6 @@ void QGLWindowSurface::beginPaint(const QRegion &) glClearColor(0.0, 0.0, 0.0, 0.0); glClear(clearFlags); } - - d_ptr->did_paint = true; } void QGLWindowSurface::endPaint(const QRegion &rgn) -- cgit v0.12 From 537312d5dea24bd404666789119a5ad1bab04396 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= <jorgen.lind@nokia.com> Date: Wed, 26 Jan 2011 14:11:40 +0100 Subject: Lighthouse: License headers to new files in testlite --- .../platforms/testlite/qtestliteclipboard.cpp | 41 ++++++++++++++++++++++ .../platforms/testlite/qtestliteclipboard.h | 41 ++++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitecursor.cpp | 2 +- .../platforms/testlite/qtestliteeglintegration.cpp | 41 ++++++++++++++++++++++ .../platforms/testlite/qtestliteeglintegration.h | 41 ++++++++++++++++++++++ .../platforms/testlite/qtestlitekeyboard.cpp | 41 ++++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitekeyboard.h | 41 ++++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitemime.cpp | 41 ++++++++++++++++++++++ src/plugins/platforms/testlite/qtestlitemime.h | 41 ++++++++++++++++++++++ .../platforms/testlite/qtestlitestaticinfo.cpp | 41 ++++++++++++++++++++++ .../platforms/testlite/qtestlitestaticinfo.h | 41 ++++++++++++++++++++++ 11 files changed, 411 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.cpp b/src/plugins/platforms/testlite/qtestliteclipboard.cpp index d77d45a..9bab7f9 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.cpp +++ b/src/plugins/platforms/testlite/qtestliteclipboard.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qtestliteclipboard.h" #include "qtestlitescreen.h" diff --git a/src/plugins/platforms/testlite/qtestliteclipboard.h b/src/plugins/platforms/testlite/qtestliteclipboard.h index 22d3734..76065a2 100644 --- a/src/plugins/platforms/testlite/qtestliteclipboard.h +++ b/src/plugins/platforms/testlite/qtestliteclipboard.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QTESTLITECLIPBOARD_H #define QTESTLITECLIPBOARD_H diff --git a/src/plugins/platforms/testlite/qtestlitecursor.cpp b/src/plugins/platforms/testlite/qtestlitecursor.cpp index e9e6eb7..e7ef673 100644 --- a/src/plugins/platforms/testlite/qtestlitecursor.cpp +++ b/src/plugins/platforms/testlite/qtestlitecursor.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/testlite/qtestliteeglintegration.cpp b/src/plugins/platforms/testlite/qtestliteeglintegration.cpp index 3cbcc05..532c63d 100644 --- a/src/plugins/platforms/testlite/qtestliteeglintegration.cpp +++ b/src/plugins/platforms/testlite/qtestliteeglintegration.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qtestliteeglintegration.h" static int countBits(unsigned long mask) diff --git a/src/plugins/platforms/testlite/qtestliteeglintegration.h b/src/plugins/platforms/testlite/qtestliteeglintegration.h index 3717976..99e9018 100644 --- a/src/plugins/platforms/testlite/qtestliteeglintegration.h +++ b/src/plugins/platforms/testlite/qtestliteeglintegration.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QTESTLITEEGLINTEGRATION_H #define QTESTLITEEGLINTEGRATION_H diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp index 72e6d50..5b4ebd7 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.cpp +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qtestlitekeyboard.h" #include "qtestlitescreen.h" diff --git a/src/plugins/platforms/testlite/qtestlitekeyboard.h b/src/plugins/platforms/testlite/qtestlitekeyboard.h index 65ead16..6873a09 100644 --- a/src/plugins/platforms/testlite/qtestlitekeyboard.h +++ b/src/plugins/platforms/testlite/qtestlitekeyboard.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QTESTLITEKEYBOARD_H #define QTESTLITEKEYBOARD_H diff --git a/src/plugins/platforms/testlite/qtestlitemime.cpp b/src/plugins/platforms/testlite/qtestlitemime.cpp index 32cacce..c509991 100644 --- a/src/plugins/platforms/testlite/qtestlitemime.cpp +++ b/src/plugins/platforms/testlite/qtestlitemime.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qtestlitemime.h" #include "qtestlitestaticinfo.h" diff --git a/src/plugins/platforms/testlite/qtestlitemime.h b/src/plugins/platforms/testlite/qtestlitemime.h index 449bbf3..f11070f 100644 --- a/src/plugins/platforms/testlite/qtestlitemime.h +++ b/src/plugins/platforms/testlite/qtestlitemime.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QTESTLITEMIME_H #define QTESTLITEMIME_H diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp index 875ac9e..2c6404d 100644 --- a/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "qtestlitestaticinfo.h" #include "qtestlitescreen.h" diff --git a/src/plugins/platforms/testlite/qtestlitestaticinfo.h b/src/plugins/platforms/testlite/qtestlitestaticinfo.h index 328de60..0876768 100644 --- a/src/plugins/platforms/testlite/qtestlitestaticinfo.h +++ b/src/plugins/platforms/testlite/qtestlitestaticinfo.h @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenVG module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** 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, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + #ifndef QTESTLITESTATICINFO_H #define QTESTLITESTATICINFO_H -- cgit v0.12