diff options
Diffstat (limited to 'src/client')
-rw-r--r-- | src/client/CMakeLists.txt | 3 | ||||
-rw-r--r-- | src/client/qwaylandbuffer.cpp | 7 | ||||
-rw-r--r-- | src/client/qwaylandbuffer_p.h | 3 | ||||
-rw-r--r-- | src/client/qwaylanddatadevice.cpp | 8 | ||||
-rw-r--r-- | src/client/qwaylanddisplay.cpp | 5 | ||||
-rw-r--r-- | src/client/qwaylanddisplay_p.h | 6 | ||||
-rw-r--r-- | src/client/qwaylandextendedsurface.cpp | 92 | ||||
-rw-r--r-- | src/client/qwaylandextendedsurface_p.h | 59 | ||||
-rw-r--r-- | src/client/qwaylandnativeinterface.cpp | 1 | ||||
-rw-r--r-- | src/client/qwaylandshellsurface.cpp | 1 | ||||
-rw-r--r-- | src/client/qwaylandsurface.cpp | 10 | ||||
-rw-r--r-- | src/client/qwaylandtextinputv3.cpp | 97 | ||||
-rw-r--r-- | src/client/qwaylandtextinputv3_p.h | 7 | ||||
-rw-r--r-- | src/client/qwaylandwindow.cpp | 29 | ||||
-rw-r--r-- | src/client/qwaylandwindow_p.h | 3 |
15 files changed, 100 insertions, 231 deletions
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 300fd4ffa..4d0a106f6 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -9,7 +9,6 @@ qt_internal_add_module(WaylandClient PLUGIN_TYPES wayland-graphics-integration-client wayland-inputdevice-integration wayland-decoration-client wayland-shell-integration - GENERATE_CPP_EXPORTS SOURCES ../shared/qwaylandinputmethodeventbuilder.cpp ../shared/qwaylandinputmethodeventbuilder_p.h ../shared/qwaylandmimehelper.cpp ../shared/qwaylandmimehelper_p.h @@ -31,7 +30,6 @@ qt_internal_add_module(WaylandClient qwaylanddecorationfactory.cpp qwaylanddecorationfactory_p.h qwaylanddecorationplugin.cpp qwaylanddecorationplugin_p.h qwaylanddisplay.cpp qwaylanddisplay_p.h - qwaylandextendedsurface.cpp qwaylandextendedsurface_p.h qwaylandfractionalscale.cpp qwaylandfractionalscale_p.h qwaylandinputcontext.cpp qwaylandinputcontext_p.h qwaylandtextinputv1.cpp qwaylandtextinputv1_p.h @@ -100,7 +98,6 @@ qt6_generate_wayland_protocol_client_sources(WaylandClient ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-key-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-text-input-method-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/qt-windowmanager.xml - ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/surface-extension.xml ${CMAKE_CURRENT_SOURCE_DIR}/../extensions/touch-extension.xml ${CMAKE_CURRENT_SOURCE_DIR}/hardwareintegration/../../extensions/hardware-integration.xml ${CMAKE_CURRENT_SOURCE_DIR}/hardwareintegration/../../extensions/server-buffer-extension.xml diff --git a/src/client/qwaylandbuffer.cpp b/src/client/qwaylandbuffer.cpp index 1907d5864..dd99b702b 100644 --- a/src/client/qwaylandbuffer.cpp +++ b/src/client/qwaylandbuffer.cpp @@ -31,6 +31,13 @@ void QWaylandBuffer::release(void *data, wl_buffer *) QWaylandBuffer *self = static_cast<QWaylandBuffer *>(data); self->mBusy = false; self->mCommitted = false; + if (self->mDeleteOnRelease) + delete self; +} + +void QWaylandBuffer::setDeleteOnRelease(bool deleteOnRelease) +{ + mDeleteOnRelease = deleteOnRelease; } const wl_buffer_listener QWaylandBuffer::listener = { diff --git a/src/client/qwaylandbuffer_p.h b/src/client/qwaylandbuffer_p.h index 3798ef3eb..c96f213b9 100644 --- a/src/client/qwaylandbuffer_p.h +++ b/src/client/qwaylandbuffer_p.h @@ -43,12 +43,15 @@ public: void setCommitted() { mCommitted = true; } bool committed() const { return mCommitted; } + void setDeleteOnRelease(bool deleteOnRelease); + protected: struct wl_buffer *mBuffer = nullptr; private: bool mBusy = false; bool mCommitted = false; + bool mDeleteOnRelease = false; static void release(void *data, wl_buffer *); static const wl_buffer_listener listener; diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index a59b201f6..30bfb86c5 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -195,7 +195,7 @@ void QWaylandDataDevice::data_device_drop() QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(m_dragWindow, dragData, m_dragPoint, supportedActions, QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); + m_inputDevice->modifiers()); if (drag) { auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag()); drag->setDropResponse(response); @@ -230,7 +230,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag( m_dragWindow, dragData, m_dragPoint, supportedActions, QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); + m_inputDevice->modifiers()); if (drag) { static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response); } @@ -243,7 +243,7 @@ void QWaylandDataDevice::data_device_leave() if (m_dragWindow) QWindowSystemInterface::handleDrag(m_dragWindow, nullptr, QPoint(), Qt::IgnoreAction, QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); + m_inputDevice->modifiers()); QDrag *drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->currentDrag(); if (!drag) { @@ -274,7 +274,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions, QGuiApplication::mouseButtons(), - QGuiApplication::keyboardModifiers()); + m_inputDevice->modifiers()); if (drag) { static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response); diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index e6ed0772f..f78bf2dd2 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -34,7 +34,6 @@ #include "qwaylandshellintegration_p.h" #include "qwaylandclientbufferintegration_p.h" -#include "qwaylandextendedsurface_p.h" #include "qwaylandpointergestures_p.h" #include "qwaylandsubsurface_p.h" #include "qwaylandtouch_p.h" @@ -642,10 +641,6 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin } else if (interface == QLatin1String(QWaylandDataDeviceManager::interface()->name)) { mGlobals.dndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id)); #endif - } else if (interface == QLatin1String(QtWayland::qt_surface_extension::interface()->name)) { - mGlobals.surfaceExtension.reset( - new WithDestructor<QtWayland::qt_surface_extension, qt_surface_extension_destroy>( - registry, id, 1)); } else if (interface == QLatin1String(QtWayland::wl_subcompositor::interface()->name)) { mGlobals.subCompositor.reset( new WithDestructor<QtWayland::wl_subcompositor, wl_subcompositor_destroy>(registry, diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 2fd176d84..b93a2ecc0 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -48,7 +48,6 @@ class QPlatformScreen; class QPlatformPlaceholderScreen; namespace QtWayland { - class qt_surface_extension; class zwp_text_input_manager_v1; class zwp_text_input_manager_v2; class zwp_text_input_manager_v3; @@ -153,10 +152,6 @@ public: return mGlobals.primarySelectionManager.get(); } #endif - QtWayland::qt_surface_extension *windowExtension() const - { - return mGlobals.surfaceExtension.get(); - } #if QT_CONFIG(tabletevent) QWaylandTabletManagerV2 *tabletManager() const { @@ -323,7 +318,6 @@ private: #if QT_CONFIG(wayland_datadevice) std::unique_ptr<QWaylandDataDeviceManager> dndSelectionHandler; #endif - std::unique_ptr<QtWayland::qt_surface_extension> surfaceExtension; std::unique_ptr<QtWayland::wl_subcompositor> subCompositor; std::unique_ptr<QWaylandTouchExtension> touchExtension; std::unique_ptr<QWaylandQtKeyExtension> qtKeyExtension; diff --git a/src/client/qwaylandextendedsurface.cpp b/src/client/qwaylandextendedsurface.cpp deleted file mode 100644 index a61612ce8..000000000 --- a/src/client/qwaylandextendedsurface.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#include "qwaylandextendedsurface_p.h" - -#include "qwaylandwindow_p.h" - -#include "qwaylanddisplay_p.h" - -#include "qwaylandnativeinterface_p.h" - -#include <QtGui/QGuiApplication> -#include <qpa/qplatformnativeinterface.h> -#include <qpa/qwindowsysteminterface.h> - -QT_BEGIN_NAMESPACE - -namespace QtWaylandClient { - -QWaylandExtendedSurface::QWaylandExtendedSurface(QWaylandWindow *window) - : QtWayland::qt_extended_surface(window->display()->windowExtension()->get_extended_surface(window->wlSurface())) - , m_window(window) -{ -} - -QWaylandExtendedSurface::~QWaylandExtendedSurface() -{ - qt_extended_surface_destroy(object()); -} - -void QWaylandExtendedSurface::updateGenericProperty(const QString &name, const QVariant &value) -{ - QByteArray byteValue; - QDataStream ds(&byteValue, QIODevice::WriteOnly); - ds << value; - - update_generic_property(name, byteValue); -} - -void QWaylandExtendedSurface::setContentOrientationMask(Qt::ScreenOrientations mask) -{ - int32_t wlmask = 0; - if (mask & Qt::PrimaryOrientation) - wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION; - if (mask & Qt::PortraitOrientation) - wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION; - if (mask & Qt::LandscapeOrientation) - wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION; - if (mask & Qt::InvertedPortraitOrientation) - wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION; - if (mask & Qt::InvertedLandscapeOrientation) - wlmask |= QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION; - set_content_orientation_mask(wlmask); -} - -void QWaylandExtendedSurface::extended_surface_onscreen_visibility(int32_t visibility) -{ - m_window->window()->setVisibility(static_cast<QWindow::Visibility>(visibility)); -} - -void QWaylandExtendedSurface::extended_surface_set_generic_property(const QString &name, wl_array *value) -{ - QByteArray data = QByteArray::fromRawData(static_cast<char *>(value->data), value->size); - - QVariant variantValue; - QDataStream ds(data); - ds >> variantValue; - - m_window->setProperty(name, variantValue); -} - -void QWaylandExtendedSurface::extended_surface_close() -{ - QWindowSystemInterface::handleCloseEvent(m_window->window()); -} - -Qt::WindowFlags QWaylandExtendedSurface::setWindowFlags(Qt::WindowFlags flags) -{ - uint wlFlags = 0; - - if (flags & Qt::WindowStaysOnTopHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP; - if (flags & Qt::WindowOverridesSystemGestures) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES; - if (flags & Qt::BypassWindowManagerHint) wlFlags |= QT_EXTENDED_SURFACE_WINDOWFLAG_BYPASSWINDOWMANAGER; - - set_window_flags(wlFlags); - - return flags & (Qt::WindowStaysOnTopHint | Qt::WindowOverridesSystemGestures | Qt::BypassWindowManagerHint); -} - -} - -QT_END_NAMESPACE diff --git a/src/client/qwaylandextendedsurface_p.h b/src/client/qwaylandextendedsurface_p.h deleted file mode 100644 index 0a7c6e5ad..000000000 --- a/src/client/qwaylandextendedsurface_p.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (C) 2018 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#ifndef QWAYLANDEXTENDEDSURFACE_H -#define QWAYLANDEXTENDEDSURFACE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QString> -#include <QtCore/QVariant> -#include <QtCore/QMap> // for QVariantMap - -#include <QtWaylandClient/qtwaylandclientglobal.h> - -#include <QtWaylandClient/private/qwayland-surface-extension.h> -#include <QtCore/private/qglobal_p.h> - -QT_BEGIN_NAMESPACE - -namespace QtWaylandClient { - -class QWaylandDisplay; -class QWaylandWindow; - -class Q_WAYLANDCLIENT_EXPORT QWaylandExtendedSurface : public QtWayland::qt_extended_surface -{ -public: - QWaylandExtendedSurface(QWaylandWindow *window); - ~QWaylandExtendedSurface() override; - - void setContentOrientationMask(Qt::ScreenOrientations mask); - - void updateGenericProperty(const QString &name, const QVariant &value); - - Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); - -private: - void extended_surface_onscreen_visibility(int32_t visibility) override; - void extended_surface_set_generic_property(const QString &name, wl_array *value) override; - void extended_surface_close() override; - - QWaylandWindow *m_window = nullptr; - QVariantMap m_properties; -}; - -} - -QT_END_NAMESPACE - -#endif // QWAYLANDEXTENDEDSURFACE_H diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp index 601f833aa..e1586d244 100644 --- a/src/client/qwaylandnativeinterface.cpp +++ b/src/client/qwaylandnativeinterface.cpp @@ -6,7 +6,6 @@ #include "qwaylandwindow_p.h" #include "qwaylandshellintegration_p.h" #include "qwaylandsubsurface_p.h" -#include "qwaylandextendedsurface_p.h" #include "qwaylandintegration_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandwindowmanagerintegration_p.h" diff --git a/src/client/qwaylandshellsurface.cpp b/src/client/qwaylandshellsurface.cpp index 77d6b97a9..fde1e1d3f 100644 --- a/src/client/qwaylandshellsurface.cpp +++ b/src/client/qwaylandshellsurface.cpp @@ -3,7 +3,6 @@ #include "qwaylandshellsurface_p.h" #include "qwaylandwindow_p.h" -#include "qwaylandextendedsurface_p.h" #include "qwaylandinputdevice_p.h" QT_BEGIN_NAMESPACE diff --git a/src/client/qwaylandsurface.cpp b/src/client/qwaylandsurface.cpp index 949d7b160..274fdda82 100644 --- a/src/client/qwaylandsurface.cpp +++ b/src/client/qwaylandsurface.cpp @@ -15,6 +15,7 @@ QWaylandSurface::QWaylandSurface(QWaylandDisplay *display) : wl_surface(display->createSurface(this)) { connect(qApp, &QGuiApplication::screenRemoved, this, &QWaylandSurface::handleScreenRemoved); + connect(qApp, &QGuiApplication::screenAdded, this, &QWaylandSurface::screensChanged); } QWaylandSurface::~QWaylandSurface() @@ -24,7 +25,14 @@ QWaylandSurface::~QWaylandSurface() QWaylandScreen *QWaylandSurface::oldestEnteredScreen() { - return m_screens.value(0, nullptr); + for (auto *screen : std::as_const(m_screens)) { + // only report valid screens + // we can have some ouptuts waiting for xdg output information + // that are valid QPlatformScreens, but not valid QScreens + if (screen->screen()) + return screen; + } + return nullptr; } QWaylandSurface *QWaylandSurface::fromWlSurface(::wl_surface *surface) diff --git a/src/client/qwaylandtextinputv3.cpp b/src/client/qwaylandtextinputv3.cpp index 017456ac2..bb449c9d6 100644 --- a/src/client/qwaylandtextinputv3.cpp +++ b/src/client/qwaylandtextinputv3.cpp @@ -80,8 +80,8 @@ void QWaylandTextInputv3::zwp_text_input_v3_preedit_string(const QString &text, return; m_pendingPreeditString.text = text; - m_pendingPreeditString.cursorBegin = cursorBegin; - m_pendingPreeditString.cursorEnd = cursorEnd; + m_pendingPreeditString.cursorBegin = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursorBegin); + m_pendingPreeditString.cursorEnd = QWaylandInputMethodEventBuilder::indexFromWayland(text, cursorEnd); } void QWaylandTextInputv3::zwp_text_input_v3_commit_string(const QString &text) @@ -101,8 +101,8 @@ void QWaylandTextInputv3::zwp_text_input_v3_delete_surrounding_text(uint32_t bef if (!QGuiApplication::focusObject()) return; - m_pendingDeleteBeforeText = QWaylandInputMethodEventBuilder::indexFromWayland(m_surroundingText, beforeText); - m_pendingDeleteAfterText = QWaylandInputMethodEventBuilder::indexFromWayland(m_surroundingText, afterText); + m_pendingDeleteBeforeText = beforeText; + m_pendingDeleteAfterText = afterText; } void QWaylandTextInputv3::zwp_text_input_v3_done(uint32_t serial) @@ -157,14 +157,26 @@ void QWaylandTextInputv3::zwp_text_input_v3_done(uint32_t serial) qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "DELETE" << m_pendingDeleteBeforeText << m_pendingDeleteAfterText; qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "COMMIT" << m_pendingCommitString; - // A workaround for reselection - // It will disable redundant commit after reselection - if (m_pendingDeleteBeforeText != 0 || m_pendingDeleteAfterText != 0) + int replaceFrom = 0; + int replaceLength = 0; + if (m_pendingDeleteBeforeText != 0 || m_pendingDeleteAfterText != 0) { + // A workaround for reselection + // It will disable redundant commit after reselection m_condReselection = true; + const QByteArray &utf8 = QStringView{m_surroundingText}.toUtf8(); + if (m_cursorPos < int(m_pendingDeleteBeforeText)) { + replaceFrom = -QString::fromUtf8(QByteArrayView{utf8}.first(m_pendingDeleteBeforeText)).size(); + replaceLength = QString::fromUtf8(QByteArrayView{utf8}.first(m_pendingDeleteBeforeText + m_pendingDeleteAfterText)).size(); + } else { + replaceFrom = -QString::fromUtf8(QByteArrayView{utf8}.sliced(m_cursorPos - m_pendingDeleteBeforeText, m_pendingDeleteBeforeText)).size(); + replaceLength = QString::fromUtf8(QByteArrayView{utf8}.sliced(m_cursorPos - m_pendingDeleteBeforeText, m_pendingDeleteBeforeText + m_pendingDeleteAfterText)).size(); + } + } + qCDebug(qLcQpaWaylandTextInput) << Q_FUNC_INFO << "DELETE from " << replaceFrom << " length " << replaceLength; event.setCommitString(m_pendingCommitString, - -m_pendingDeleteBeforeText, - m_pendingDeleteBeforeText + m_pendingDeleteAfterText); + replaceFrom, + replaceLength); m_currentPreeditString = m_pendingPreeditString; m_pendingPreeditString.clear(); m_pendingCommitString.clear(); @@ -235,54 +247,63 @@ void QWaylandTextInputv3::updateState(Qt::InputMethodQueries queries, uint32_t f int cursor = event.value(Qt::ImCursorPosition).toInt(); int anchor = event.value(Qt::ImAnchorPosition).toInt(); - qCDebug(qLcQpaWaylandTextInput) << "Orginal surrounding_text from InputMethodQuery: " << text << cursor << anchor; + qCDebug(qLcQpaWaylandTextInput) << "Original surrounding_text from InputMethodQuery: " << text << cursor << anchor; // Make sure text is not too big // surround_text cannot exceed 4000byte in wayland protocol // The worst case will be supposed here. const int MAX_MESSAGE_SIZE = 4000; - if (text.toUtf8().size() > MAX_MESSAGE_SIZE) { - const int selectionStart = QWaylandInputMethodEventBuilder::indexToWayland(text, qMin(cursor, anchor)); - const int selectionEnd = QWaylandInputMethodEventBuilder::indexToWayland(text, qMax(cursor, anchor)); + const int textSize = text.toUtf8().size(); + if (textSize > MAX_MESSAGE_SIZE) { + qCDebug(qLcQpaWaylandTextInput) << "SurroundText size is over " + << MAX_MESSAGE_SIZE + << " byte, some text will be clipped."; + const int selectionStart = qMin(cursor, anchor); + const int selectionEnd = qMax(cursor, anchor); const int selectionLength = selectionEnd - selectionStart; + const int selectionSize = QStringView{text}.sliced(selectionStart, selectionLength).toUtf8().size(); // If selection is bigger than 4000 byte, it is fixed to 4000 byte. // anchor will be moved in the 4000 byte boundary. - if (selectionLength > MAX_MESSAGE_SIZE) { + if (selectionSize > MAX_MESSAGE_SIZE) { if (anchor > cursor) { - const int length = MAX_MESSAGE_SIZE; - anchor = QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(text, length, cursor); - anchor -= cursor; - text = text.mid(cursor, anchor); cursor = 0; + anchor = MAX_MESSAGE_SIZE; + text = text.sliced(selectionStart, selectionLength); } else { - const int length = -MAX_MESSAGE_SIZE; - anchor = QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(text, length, cursor); - cursor -= anchor; - text = text.mid(anchor, cursor); anchor = 0; + cursor = MAX_MESSAGE_SIZE; + text = text.sliced(selectionEnd - selectionLength, selectionLength); } } else { - const int offset = (MAX_MESSAGE_SIZE - selectionLength) / 2; - - int textStart = QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(text, -offset, qMin(cursor, anchor)); - int textEnd = QWaylandInputMethodEventBuilder::trimmedIndexFromWayland(text, MAX_MESSAGE_SIZE, textStart); - - anchor -= textStart; - cursor -= textStart; - text = text.mid(textStart, textEnd - textStart); + // This is not optimal in some cases. + // For examples, if the cursor position and + // the selectionEnd are close to the end of the surround text, + // the tail of the text might always be clipped. + // However all the cases of over 4000 byte are just exceptions. + int selEndSize = QStringView{text}.first(selectionEnd).toUtf8().size(); + cursor = QWaylandInputMethodEventBuilder::indexToWayland(text, cursor); + anchor = QWaylandInputMethodEventBuilder::indexToWayland(text, anchor); + if (selEndSize < MAX_MESSAGE_SIZE) { + text = QString::fromUtf8(QByteArrayView{text.toUtf8()}.first(MAX_MESSAGE_SIZE)); + } else { + const int startOffset = selEndSize - MAX_MESSAGE_SIZE; + text = QString::fromUtf8(QByteArrayView{text.toUtf8()}.sliced(startOffset, MAX_MESSAGE_SIZE)); + cursor -= startOffset; + anchor -= startOffset; + } } + } else { + cursor = QWaylandInputMethodEventBuilder::indexToWayland(text, cursor); + anchor = QWaylandInputMethodEventBuilder::indexToWayland(text, anchor); } qCDebug(qLcQpaWaylandTextInput) << "Modified surrounding_text: " << text << cursor << anchor; - const int cursorPos = QWaylandInputMethodEventBuilder::indexToWayland(text, cursor); - const int anchorPos = QWaylandInputMethodEventBuilder::indexToWayland(text, anchor); - - if (m_surroundingText != text || m_cursorPos != cursorPos || m_anchorPos != anchorPos) { + if (m_surroundingText != text || m_cursorPos != cursor || m_anchorPos != anchor) { qCDebug(qLcQpaWaylandTextInput) << "Current surrounding_text: " << m_surroundingText << m_cursorPos << m_anchorPos; - qCDebug(qLcQpaWaylandTextInput) << "New surrounding_text: " << text << cursorPos << anchorPos; + qCDebug(qLcQpaWaylandTextInput) << "New surrounding_text: " << text << cursor << anchor; - set_surrounding_text(text, cursorPos, anchorPos); + set_surrounding_text(text, cursor, anchor); // A workaround in the case of reselection // It will work when re-clicking a preedit text @@ -294,8 +315,8 @@ void QWaylandTextInputv3::updateState(Qt::InputMethodQueries queries, uint32_t f } m_surroundingText = text; - m_cursorPos = cursorPos; - m_anchorPos = anchorPos; + m_cursorPos = cursor; + m_anchorPos = anchor; m_cursor = cursor; } } diff --git a/src/client/qwaylandtextinputv3_p.h b/src/client/qwaylandtextinputv3_p.h index e8b7aa027..8e32e514d 100644 --- a/src/client/qwaylandtextinputv3_p.h +++ b/src/client/qwaylandtextinputv3_p.h @@ -17,7 +17,6 @@ #include "qwaylandtextinputinterface_p.h" #include <QtWaylandClient/private/qwayland-text-input-unstable-v3.h> -#include <qwaylandinputmethodeventbuilder_p.h> #include <QLoggingCategory> struct wl_callback; @@ -63,8 +62,6 @@ protected: void zwp_text_input_v3_done(uint32_t serial) override; private: - QWaylandInputMethodEventBuilder m_builder; - ::wl_surface *m_surface = nullptr; // ### Here for debugging purposes struct PreeditInfo { @@ -82,8 +79,8 @@ private: PreeditInfo m_pendingPreeditString; PreeditInfo m_currentPreeditString; QString m_pendingCommitString; - uint m_pendingDeleteBeforeText = 0; - uint m_pendingDeleteAfterText = 0; + uint m_pendingDeleteBeforeText = 0; // byte length + uint m_pendingDeleteAfterText = 0; // byte length QString m_surroundingText; int m_cursor; // cursor position in QString diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 73fb331eb..e311b2eb4 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -60,8 +60,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window, QWaylandDisplay *display) mFrameCallbackTimeout = frameCallbackTimeout; } - mScale = waylandScreen() ? waylandScreen()->scale() : 1; // fallback to 1 if we don't have a real screen - static WId id = 1; mWindowId = id++; initializeWlSurface(); @@ -327,6 +325,7 @@ void QWaylandWindow::reset() mWaitingToApplyConfigure = false; mCanResize = true; mResizeDirty = false; + mScale = std::nullopt; mOpaqueArea = QRegion(); mMask = QRegion(); @@ -463,7 +462,7 @@ void QWaylandWindow::setGeometry(const QRect &r) if (mShellSurface) { mShellSurface->setWindowGeometry(windowContentGeometry()); - if (!qt_window_private(window())->positionAutomatic) + if (!qt_window_private(window())->positionAutomatic && !mInResizeFromApplyConfigure) mShellSurface->setWindowPosition(windowGeometry().topLeft()); } @@ -558,7 +557,6 @@ QPlatformScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const if (auto *screen = mSurface->oldestEnteredScreen()) return screen; } - return QPlatformWindow::screen(); } @@ -891,6 +889,7 @@ QMargins QWaylandWindow::clientSideMargins() const void QWaylandWindow::setCustomMargins(const QMargins &margins) { const QMargins oldMargins = mCustomMargins; mCustomMargins = margins; + propagateSizeHints(); setGeometry(geometry().marginsRemoved(oldMargins).marginsAdded(margins)); } @@ -1185,8 +1184,13 @@ QWaylandWindow *QWaylandWindow::guessTransientParent() const if (auto transientParent = closestShellSurfaceWindow(window()->transientParent())) return transientParent; - if (QGuiApplication::focusWindow() && (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)) - return closestShellSurfaceWindow(QGuiApplication::focusWindow()); + if (window()->type() == Qt::Popup) { + if (mTopPopup) + return mTopPopup; + } + + if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup) + return display()->lastInputWindow(); return nullptr; } @@ -1433,14 +1437,11 @@ void QWaylandWindow::handleScreensChanged() { QPlatformScreen *newScreen = calculateScreenFromSurfaceEvents(); - if (newScreen == mLastReportedScreen) + if (newScreen->screen() == window()->screen()) return; - if (!newScreen->isPlaceholder() && !newScreen->QPlatformScreen::screen()) - mDisplay->forceRoundTrip(); QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); - mLastReportedScreen = newScreen; if (fixedToplevelPositions && !QPlatformWindow::parent() && window()->type() != Qt::Popup && window()->type() != Qt::ToolTip && geometry().topLeft() != newScreen->geometry().topLeft()) { @@ -1470,13 +1471,13 @@ void QWaylandWindow::updateScale() return; } - int scale = mLastReportedScreen->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(mLastReportedScreen)->scale(); + int scale = screen()->isPlaceholder() ? 1 : static_cast<QWaylandScreen *>(screen())->scale(); setScale(scale); } void QWaylandWindow::setScale(qreal newScale) { - if (qFuzzyCompare(mScale, newScale)) + if (mScale.has_value() && qFuzzyCompare(mScale.value(), newScale)) return; mScale = newScale; @@ -1485,7 +1486,7 @@ void QWaylandWindow::setScale(qreal newScale) if (mViewport) updateViewport(); else if (mSurface->version() >= 3) - mSurface->set_buffer_scale(std::ceil(mScale)); + mSurface->set_buffer_scale(std::ceil(newScale)); } ensureSize(); @@ -1547,7 +1548,7 @@ qreal QWaylandWindow::scale() const qreal QWaylandWindow::devicePixelRatio() const { - return qreal(mScale); + return mScale.value_or(waylandScreen() ? waylandScreen()->scale() : 1); } bool QWaylandWindow::setMouseGrabEnabled(bool grab) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index b78c8ce4e..c1b736c1e 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -310,8 +310,7 @@ protected: bool mSentInitialResize = false; QPoint mOffset; - qreal mScale = 1; - QPlatformScreen *mLastReportedScreen = nullptr; + std::optional<qreal> mScale = std::nullopt; QString mWindowTitle; QIcon mWindowIcon; |