From f64b87a5df8870be138dbf3febad950e1fc4ed8c Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 18 Mar 2015 10:03:36 +0100 Subject: Fallback to malloc for insanely large windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If shmget() does not work (probably because the backingstore size is bigger than SHMMAX), don't create a QImage with the previous buffer and the new size. That does not end well when we try to draw to the image later. Instead, fall back to the malloc path, like we do when the system doesn't support shared memory. [ChangeLog][X11] Don't crash when resizing windows to bigger than 3840x2160 Task-number: QTBUG-45071 Change-Id: I009de7c2179ffde28e252593067756877cad1b1c Reviewed-by: Laszlo Agocs Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index f4382c7b50..42a868d997 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -122,7 +122,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI xcb_generic_error_t *error = NULL; if (shm_present) error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); - if (!shm_present || error) { + if (!shm_present || error || id == -1) { free(error); shmdt(m_shm_info.shmaddr); -- cgit v1.2.3 From 9f1f8aaa92cdd0a1a655bb7dc4fae200c805489d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 6 Feb 2015 07:34:43 +0100 Subject: Handle SelectionWindowDestroy in QXcbClipboard This change is related to 6a7ee92b3958e3a3ebc16be15f8bd34217ec7bd2 which added handling for SelectionClientClose. Further testing showed that with e.g. Qt 4 applications the SelectionClientClose is not emitted, but the selection window seems to be destroyed before the client is destroyed. Fur a destroyed selection window the same applies: the clipboard content is no longer valid and we should emit the changed signal. Change-Id: Id3778a28b9f5601bf2c6e0106981316e0efa6e7c Reviewed-by: Gatis Paeglis Reviewed-by: Uli Schlachter --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index f56a29d985..4b6caa9620 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -742,7 +742,8 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve m_xClipboard[mode]->reset(); } emitChanged(mode); - } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE) + } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE || + event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_WINDOW_DESTROY) emitChanged(mode); } -- cgit v1.2.3 From c0e4f24336cb0f0c21ad6c79e3da898d974ac1ad Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 5 Mar 2015 16:18:02 +0300 Subject: xcb: Determine the window gravity just before the window is shown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It may change after the window has been created. Change-Id: Ib81a7ad7353b1909cc42684fc70d6b7d2556106f Reviewed-by: Uli Schlachter Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbwindow.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 233514a181..c0076a9977 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -308,11 +308,6 @@ void QXcbWindow::create() return; } - // Determine gravity from initial position. Do not change - // later as it will cause the window to move uncontrollably. - m_gravity = positionIncludesFrame(window()) ? - XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; - const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_BACK_PIXMAP @@ -732,6 +727,9 @@ void QXcbWindow::show() xcb_set_wm_hints(xcb_connection(), m_window, &hints); + m_gravity = positionIncludesFrame(window()) ? + XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; + // update WM_NORMAL_HINTS propagateSizeHints(); -- cgit v1.2.3 From 738c07542a0bbf867661520559fed9feda985935 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 19 Mar 2015 14:51:53 +0300 Subject: Don't replay mouse press event which closes a popup on X11 Add a new style hint to QPlatformIntegration: ReplayMousePressOutsidePopup. Return false for it in the xcb plugin. This commit restores the behavior which was in Qt 4. Task-number: QTBUG-34814 Change-Id: I19fee762395a51475cc67b52b368c70679ca736b Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbintegration.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 258359d20f..04c527c687 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -374,6 +374,8 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const // X11 always has support for windows, but the // window manager could prevent it (e.g. matchbox) return false; + case QPlatformIntegration::ReplayMousePressOutsidePopup: + return false; default: break; } -- cgit v1.2.3 From 667f3abc50082b4f8c68bc6ddd3c896dcd2635bc Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 25 Feb 2015 15:42:03 +0100 Subject: Proper geometry conversion for devicePixelRatio > 1 Rounding the bottom right corner position means that the size can change when the window moves. For windows we need to round the size up in order to have a stable geometry. Task-number: QTBUG-45076 Change-Id: I9a85a5915bfec55b0a7295be137b6fbfd7b53095 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 78ccf8a3e9..45245a1454 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -155,6 +155,11 @@ static inline QPoint dpr_ceil(const QPoint &p, int dpr) return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr); } +static inline QSize dpr_ceil(const QSize &s, int dpr) +{ + return QSize((s.width() + dpr - 1) / dpr, (s.height() + dpr - 1) / dpr); +} + static inline QRect mapExposeFromNative(const QRect &xRect, int dpr) { return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr)); @@ -162,7 +167,7 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr) static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr) { - return QRect(xRect.topLeft() / dpr, xRect.bottomRight() / dpr); + return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr)); } // Returns \c true if we should set WM_TRANSIENT_FOR on \a w -- cgit v1.2.3 From dc62f15d799440f57954bea61e14669ff2990149 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Wed, 18 Mar 2015 16:35:07 +0100 Subject: Resize backingstore properly on devicePixelRatio changes Task-number: QTBUG-45076 Change-Id: Ib2f2408abf7bd0b6d1c8a05fbbdc665e77ea6392 Reviewed-by: Friedemann Kleint Reviewed-by: Laszlo Agocs Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index ce2329724a..5c9293c03d 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -310,7 +310,13 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) { if (!m_image) return; - const int dpr = int(m_image->image()->devicePixelRatio()); + int dpr = int(m_image->image()->devicePixelRatio()); + const int windowDpr = int(window()->devicePixelRatio()); + if (windowDpr != dpr) { + resize(window()->size(), QRegion()); + dpr = int(m_image->image()->devicePixelRatio()); + } + QRegion xRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region); m_image->preparePaint(xRegion); @@ -342,7 +348,15 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin if (!m_image || m_image->size().isEmpty()) return; - QSize imageSize = m_image->size(); + const int dpr = int(window->devicePixelRatio()); + +#ifndef QT_NO_DEBUG + const int imageDpr = int(m_image->image()->devicePixelRatio()); + if (dpr != imageDpr) + qWarning() << "QXcbBackingStore::flush() wrong devicePixelRatio for backingstore image" << dpr << imageDpr; +#endif + + QSize imageSize = m_image->size() / dpr; //because we multiply with the DPR later QRegion clipped = region; clipped &= QRect(0, 0, window->width(), window->height()); @@ -361,8 +375,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin return; } - const int dpr = int(window->devicePixelRatio()); - QVector rects = clipped.rects(); for (int i = 0; i < rects.size(); ++i) { QRect rect = QRect(rects.at(i).topLeft() * dpr, rects.at(i).size() * dpr); @@ -399,8 +411,7 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) { const int dpr = int(window()->devicePixelRatio()); const QSize xSize = size * dpr; - - if (m_image && xSize == m_image->size()) + if (m_image && xSize == m_image->size() && dpr == m_image->image()->devicePixelRatio()) return; Q_XCB_NOOP(connection()); -- cgit v1.2.3 From f381ad63a2d51033272c72f3a816fcfe9de000e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Fri, 6 Feb 2015 07:34:43 +0100 Subject: Handle SelectionWindowDestroy in QXcbClipboard This change is related to 6a7ee92b3958e3a3ebc16be15f8bd34217ec7bd2 which added handling for SelectionClientClose. Further testing showed that with e.g. Qt 4 applications the SelectionClientClose is not emitted, but the selection window seems to be destroyed before the client is destroyed. Fur a destroyed selection window the same applies: the clipboard content is no longer valid and we should emit the changed signal. Change-Id: I173e272dbe912084deed5342d7a4adb55ea1974f Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 2c0a7a11cc..248d1b4bbb 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -749,7 +749,8 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve m_xClipboard[mode]->reset(); } emitChanged(mode); - } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE) + } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE || + event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_WINDOW_DESTROY) emitChanged(mode); } -- cgit v1.2.3 From a73cead0e0ffe674d0c873a726d2535ba60d9614 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 18 Mar 2015 18:42:01 +0300 Subject: xcb: Speed up screens' initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use RRGetScreenResourcesCurrent to get the screen's outputs. It is fast but it may return nothing if the configuration is not initialized wrt to the hardware. Call RRGetScreenResources in this case to get the up-to-date configuration. Task-number: QTBUG-40207 Change-Id: I84dc8a45b89d0bf8881a72b02e81f701637cdb6a Reviewed-by: Uli Schlachter Reviewed-by: Daniel Vrátil Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 137 +++++++++++++++------------ 1 file changed, 77 insertions(+), 60 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 3b3fcd0b49..5b101e66bb 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -306,71 +306,88 @@ void QXcbConnection::initializeScreens() int connectedOutputCount = 0; if (has_randr_extension) { xcb_generic_error_t *error = NULL; - xcb_randr_get_output_primary_cookie_t primaryCookie = - xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); - // TODO: RRGetScreenResources has to be called on each X display at least once before - // RRGetScreenResourcesCurrent can be used - we can't know if we are the first application - // to do so or not, so we always call the slower version here. Ideally we should share some - // global flag (an atom on root window maybe) that at least other Qt apps would understand - // and could call RRGetScreenResourcesCurrent here, speeding up start. - xcb_randr_get_screen_resources_cookie_t resourcesCookie = - xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); - QScopedPointer primary( - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); - if (!primary || error) { - qWarning("failed to get the primary output of the screen"); + // RRGetScreenResourcesCurrent is fast but it may return nothing if the + // configuration is not initialized wrt to the hardware. We should call + // RRGetScreenResources in this case. + QScopedPointer resources; + xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = + xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root); + QScopedPointer resources_current( + xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error)); + if (!resources_current || error) { + qWarning("failed to get the current screen resources"); free(error); } else { - QScopedPointer resources( - xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); - if (!resources || error) { - qWarning("failed to get the screen resources"); - free(error); + xcb_timestamp_t timestamp; + xcb_randr_output_t *outputs = Q_NULLPTR; + outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data()); + if (outputCount) { + timestamp = resources_current->config_timestamp; + outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data()); } else { - xcb_timestamp_t timestamp = resources->config_timestamp; - outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); - xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data()); - - for (int i = 0; i < outputCount; i++) { - QScopedPointer output( - xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); - - // Invalid, disconnected or disabled output - if (output == NULL) - continue; - - if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { - qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); - continue; - } + xcb_randr_get_screen_resources_cookie_t resourcesCookie = + xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); + resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); + if (!resources || error) { + qWarning("failed to get the screen resources"); + free(error); + } else { + timestamp = resources->config_timestamp; + outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); + outputs = xcb_randr_get_screen_resources_outputs(resources.data()); + } + } - if (output->crtc == XCB_NONE) { - qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), - xcb_randr_get_output_info_name_length(output.data())))); - continue; - } + if (outputCount) { + xcb_randr_get_output_primary_cookie_t primaryCookie = + xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); + QScopedPointer primary( + xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); + if (!primary || error) { + qWarning("failed to get the primary output of the screen"); + free(error); + } else { + for (int i = 0; i < outputCount; i++) { + QScopedPointer output( + xcb_randr_get_output_info_reply(xcb_connection(), + xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); + + // Invalid, disconnected or disabled output + if (output == NULL) + continue; + + if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { + qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); + continue; + } + + if (output->crtc == XCB_NONE) { + qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); + continue; + } - QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); - siblings << screen; - ++connectedOutputCount; - hasOutputs = true; - m_screens << screen; - - // There can be multiple outputs per screen, use either - // the first or an exact match. An exact match isn't - // always available if primary->output is XCB_NONE - // or currently disconnected output. - if (m_primaryScreenNumber == xcbScreenNumber) { - if (!primaryScreen || (primary && outputs[i] == primary->output)) { - if (primaryScreen) - primaryScreen->setPrimary(false); - primaryScreen = screen; - primaryScreen->setPrimary(true); - siblings.prepend(siblings.takeLast()); + QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); + siblings << screen; + ++connectedOutputCount; + hasOutputs = true; + m_screens << screen; + + // There can be multiple outputs per screen, use either + // the first or an exact match. An exact match isn't + // always available if primary->output is XCB_NONE + // or currently disconnected output. + if (m_primaryScreenNumber == xcbScreenNumber) { + if (!primaryScreen || (primary && outputs[i] == primary->output)) { + if (primaryScreen) + primaryScreen->setPrimary(false); + primaryScreen = screen; + primaryScreen->setPrimary(true); + siblings.prepend(siblings.takeLast()); + } } } } -- cgit v1.2.3 From bc6e92bd2ed7e39dcb856c3e275886e1e69df4c3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 26 Mar 2015 16:52:09 +0100 Subject: xcb: Do not crash with VNC When having a vnc server with pixel format bgr888, we may not have a working GL integration. (we may not have one regardless of the pixel format in fact) We should still keep on attempting to create a regular SHM window for RasterGLSurface windows too, to keep regular widgets apps working. Task-number: QTBUG-42776 Change-Id: Idbf8de29694613b240bd27affcc3d80810ce1460 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 +- src/plugins/platforms/xcb/qxcbintegration.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5b101e66bb..2084d7ea5d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1137,7 +1137,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) } } - if (!handled) + if (!handled && m_glIntegration) handled = m_glIntegration->handleXcbEvent(event, response_type); if (handled) diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 04c527c687..2547e537a7 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -186,9 +186,9 @@ QXcbIntegration::~QXcbIntegration() QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const { + QXcbScreen *screen = static_cast(window->screen()->handle()); + QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); if (window->type() != Qt::Desktop) { - QXcbScreen *screen = static_cast(window->screen()->handle()); - QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); if (glIntegration) { QXcbWindow *xcbWindow = glIntegration->createWindow(window); xcbWindow->create(); @@ -196,7 +196,8 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const } } - Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL()); + Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL() + || (!glIntegration && window->surfaceType() == QSurface::RasterGLSurface)); // for VNC QXcbWindow *xcbWindow = new QXcbWindow(window); xcbWindow->create(); return xcbWindow; -- cgit v1.2.3 From 6fe60cd9f2966b141f70b0a223b93173505b2ecb Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 26 Mar 2015 17:59:39 +0100 Subject: xcb: Fix bgr888 VNC sessions Introduce a slow path for 24 and 32 bit BGR. We don't care about performance here but it has to show the correct colors. Task-number: QTBUG-42776 Change-Id: Ic73e8ca3950b2b956f06643165dcfac51e7540f3 Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 37 ++++++++++++++++++++++---- src/plugins/platforms/xcb/qxcbbackingstore.h | 3 +++ src/plugins/platforms/xcb/qxcbwindow.cpp | 20 +++++++++++--- src/plugins/platforms/xcb/qxcbwindow.h | 2 ++ 4 files changed, 53 insertions(+), 9 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 5c9293c03d..06db4d83ac 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -303,13 +303,16 @@ QXcbBackingStore::~QXcbBackingStore() QPaintDevice *QXcbBackingStore::paintDevice() { - return m_image ? m_image->image() : 0; + if (!m_image) + return 0; + return m_rgbImage.isNull() ? m_image->image() : &m_rgbImage; } void QXcbBackingStore::beginPaint(const QRegion ®ion) { if (!m_image) return; + int dpr = int(m_image->image()->devicePixelRatio()); const int windowDpr = int(window()->devicePixelRatio()); if (windowDpr != dpr) { @@ -317,13 +320,13 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) dpr = int(m_image->image()->devicePixelRatio()); } - QRegion xRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region); - m_image->preparePaint(xRegion); + m_paintRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region); + m_image->preparePaint(m_paintRegion); if (m_image->image()->hasAlphaChannel()) { - QPainter p(m_image->image()); + QPainter p(paintDevice()); p.setCompositionMode(QPainter::CompositionMode_Source); - const QVector rects = xRegion.rects(); + const QVector rects = m_paintRegion.rects(); const QColor blank = Qt::transparent; for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) { p.fillRect(*it, blank); @@ -331,6 +334,24 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) } } +void QXcbBackingStore::endPaint() +{ + QXcbWindow *platformWindow = static_cast(window()->handle()); + if (!platformWindow || !platformWindow->imageNeedsRgbSwap()) + return; + + // Slow path: the paint device was m_rgbImage. Now copy with swapping red + // and blue into m_image. + const QVector rects = m_paintRegion.rects(); + if (rects.isEmpty()) + return; + QPainter p(m_image->image()); + for (QVector::const_iterator it = rects.begin(); it != rects.end(); ++it) { + const QRect rect = *it; + p.drawImage(rect.topLeft(), m_rgbImage.copy(rect).rgbSwapped()); + } +} + #ifndef QT_NO_OPENGL QImage QXcbBackingStore::toImage() const { @@ -426,6 +447,12 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) delete m_image; m_image = new QXcbShmImage(screen, xSize, win->depth(), win->imageFormat()); m_image->image()->setDevicePixelRatio(dpr); + // Slow path for bgr888 VNC: Create an additional image, paint into that and + // swap R and B while copying to m_image after each paint. + if (win->imageNeedsRgbSwap()) { + m_rgbImage = QImage(xSize, win->imageFormat()); + m_rgbImage.setDevicePixelRatio(dpr); + } Q_XCB_NOOP(connection()); } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 248542719b..b58a32d313 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -65,9 +65,12 @@ public: bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + void endPaint() Q_DECL_OVERRIDE; private: QXcbShmImage *m_image; + QRegion m_paintRegion; + QImage m_rgbImage; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 45245a1454..1406270994 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -182,8 +182,10 @@ static inline bool isTransient(const QWindow *w) || w->type() == Qt::Popup; } -static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask) +static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask, bool *rgbSwap) { + if (rgbSwap) + *rgbSwap = false; switch (depth) { case 32: if (blue_mask == 0xff) @@ -192,6 +194,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q return QImage::Format_A2BGR30_Premultiplied; if (blue_mask == 0x3ff) return QImage::Format_A2RGB30_Premultiplied; + if (red_mask == 0xff) { + if (rgbSwap) + *rgbSwap = true; + return QImage::Format_ARGB32_Premultiplied; + } break; case 30: if (red_mask == 0x3ff) @@ -202,6 +209,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q case 24: if (blue_mask == 0xff) return QImage::Format_RGB32; + if (red_mask == 0xff) { + if (rgbSwap) + *rgbSwap = true; + return QImage::Format_RGB32; + } break; case 16: if (blue_mask == 0x1f) @@ -296,7 +308,7 @@ void QXcbWindow::create() m_depth = platformScreen->screen()->root_depth; m_visualId = platformScreen->screen()->root_visual; const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); - m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); connection()->addWindowEventListener(m_window, this); return; } @@ -368,7 +380,7 @@ void QXcbWindow::create() if (visualInfo) { m_depth = visualInfo->depth; - m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask); + m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask, &m_imageRgbSwap); Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone); XSetWindowAttributes a; @@ -421,7 +433,7 @@ void QXcbWindow::create() } const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId); - m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask); + m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap); Q_XCB_CALL(xcb_create_window(xcb_connection(), m_depth, diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 8f78be573c..c08408a1ca 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -113,6 +113,7 @@ public: xcb_window_t xcb_window() const { return m_window; } uint depth() const { return m_depth; } QImage::Format imageFormat() const { return m_imageFormat; } + bool imageNeedsRgbSwap() const { return m_imageRgbSwap; } bool handleGenericEvent(xcb_generic_event_t *event, long *result) Q_DECL_OVERRIDE; @@ -193,6 +194,7 @@ protected: uint m_depth; QImage::Format m_imageFormat; + bool m_imageRgbSwap; xcb_sync_int64_t m_syncValue; xcb_sync_counter_t m_syncCounter; -- cgit v1.2.3 From c7b003ea3b8b4b7124d4971df7d910f2bc3fc4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Mon, 30 Mar 2015 12:03:30 +0200 Subject: Use Xlib to resolve font cursor if possible before fallingback to uploading a bitmap cursor Task-number: QTBUG-30016 Change-Id: I53eeda6bb5f6cab66e3bc10a2e5382ce55cc1bab Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbcursor.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index e3a04c1d7b..8dd27ec9c5 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -53,6 +53,12 @@ typedef int (*PtrXcursorLibrarySetTheme)(void *, const char *); typedef int (*PtrXcursorLibraryGetDefaultSize)(void *); #ifdef XCB_USE_XLIB +#include +enum { + XCursorShape = CursorShape +}; +#undef CursorShape + static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0; static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = 0; static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = 0; @@ -552,6 +558,12 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape) } if (cursor) return cursor; + if (!cursor && cursorId) { + cursor = XCreateFontCursor(DISPLAY_FROM_XCB(this), cursorId); + if (cursor) + return cursor; + } + #endif // Non-standard X11 cursors are created from bitmaps -- cgit v1.2.3 From 641b8d2b84896e277678307a3e7bbac9f64cff76 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 5 Mar 2015 13:37:34 +0100 Subject: xcb: set WM_NAME window property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some older window managers and utilities still ignore _NET_WM_NAME. Task-number: QTBUG-42209 Change-Id: Iff93c8188a0a73b04cdf361add153cd818ac670f Reviewed-by: Uli Schlachter Reviewed-by: Martin Gräßlin Reviewed-by: Jørgen Lind --- src/plugins/platforms/xcb/qxcbconnection.cpp | 1 + src/plugins/platforms/xcb/qxcbconnection.h | 1 + src/plugins/platforms/xcb/qxcbwindow.cpp | 49 ++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 2084d7ea5d..f4c633e2d7 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1480,6 +1480,7 @@ static const char * xcb_atomnames = { "WM_STATE\0" "WM_CHANGE_STATE\0" "WM_CLASS\0" + "WM_NAME\0" // Session management "WM_CLIENT_LEADER\0" diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index de454b5eae..f479c1bc80 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -107,6 +107,7 @@ namespace QXcbAtom { WM_STATE, WM_CHANGE_STATE, WM_CLASS, + WM_NAME, // Session management WM_CLIENT_LEADER, diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1406270994..34179a70a4 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -86,6 +86,7 @@ #include #include +#include #include #ifdef XCB_USE_XLIB @@ -243,6 +244,48 @@ static inline bool positionIncludesFrame(QWindow *w) return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive; } +#ifdef XCB_USE_XLIB +static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s) +{ + #include + + static XTextProperty tp = { 0, 0, 0, 0 }; + static bool free_prop = true; // we can't free tp.value in case it references + // the data of the static QByteArray below. + if (tp.value) { + if (free_prop) + XFree(tp.value); + tp.value = 0; + free_prop = true; + } + + static const QTextCodec* mapper = QTextCodec::codecForLocale(); + int errCode = 0; + if (mapper) { + QByteArray mapped = mapper->fromUnicode(s); + char* tl[2]; + tl[0] = mapped.data(); + tl[1] = 0; + errCode = XmbTextListToTextProperty(dpy, tl, 1, XStdICCTextStyle, &tp); + if (errCode < 0) + qDebug("XmbTextListToTextProperty result code %d", errCode); + } + if (!mapper || errCode < 0) { + mapper = QTextCodec::codecForName("latin1"); + if (!mapper || !mapper->canEncode(s)) + return Q_NULLPTR; + static QByteArray qcs; + qcs = s.toLatin1(); + tp.value = (uchar*)qcs.data(); + tp.encoding = XA_STRING; + tp.format = 8; + tp.nitems = qcs.length(); + free_prop = false; + } + return &tp; +} +#endif // XCB_USE_XLIB + static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; QXcbWindow::QXcbWindow(QWindow *window) @@ -1423,6 +1466,12 @@ void QXcbWindow::setWindowTitle(const QString &title) 8, ba.length(), ba.constData())); + +#ifdef XCB_USE_XLIB + XTextProperty *text = qstringToXTP(DISPLAY_FROM_XCB(this), title); + if (text) + XSetWMName(DISPLAY_FROM_XCB(this), m_window, text); +#endif xcb_flush(xcb_connection()); } -- cgit v1.2.3