From 4dc3fb05a77e5ffbedec6e0ab9b2b578470ed1be Mon Sep 17 00:00:00 2001 From: Christian Stenger Date: Tue, 12 Dec 2023 10:30:57 +0100 Subject: [PATCH] Core: Explicitly provide image for minisplitter cursors On Linux we fail to get the system cursor for resizing splitters on several platforms which makes it hard to grab them to move their position. Provide a setting which enables the user to use some cursors explicitly provided by QC instead. Task-number: QTBUG-119875 Fixes: QTCREATORBUG-29980 Change-Id: I02f031883ddd5cfd33075868ae6766ff78ee6882 Reviewed-by: Eike Ziller Reviewed-by: Reviewed-by: Leena Miettinen --- src/plugins/coreplugin/generalsettings.cpp | 13 ++++ src/plugins/coreplugin/generalsettings.h | 1 + src/plugins/coreplugin/minisplitter.cpp | 70 ++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/src/plugins/coreplugin/generalsettings.cpp b/src/plugins/coreplugin/generalsettings.cpp index 4b75c15a7e0..0689adea522 100644 --- a/src/plugins/coreplugin/generalsettings.cpp +++ b/src/plugins/coreplugin/generalsettings.cpp @@ -61,6 +61,14 @@ GeneralSettings::GeneralSettings() Tr::tr("Show keyboard shortcuts in context menus (default: %1)") .arg(defaultShowShortcutsInContextMenu() ? Tr::tr("on") : Tr::tr("off"))); + provideSplitterCursors.setSettingsKey("General/OverrideSplitterCursors"); + provideSplitterCursors.setDefaultValue(false); + provideSplitterCursors.setLabelText(Tr::tr("Override cursors for views")); + provideSplitterCursors.setToolTip( + Tr::tr("Provide cursors for resizing views.\nIf the system cursors for resizing views are " + "not displayed properly, you can use the cursors provided by %1.") + .arg(QGuiApplication::applicationDisplayName())); + connect(&showShortcutsInContextMenus, &BaseAspect::changed, this, [this] { QCoreApplication::setAttribute(Qt::AA_DontShowShortcutsInContextMenus, !showShortcutsInContextMenus()); @@ -179,6 +187,7 @@ GeneralSettingsWidget::GeneralSettingsWidget() } form.addRow({empty, generalSettings().showShortcutsInContextMenus}); + form.addRow({empty, generalSettings().provideSplitterCursors}); form.addRow({Row{m_resetWarningsButton, st}}); form.addRow({Tr::tr("Text codec for tools:"), m_codecBox, st}); Column{Group{title(Tr::tr("User Interface")), form}}.attachTo(this); @@ -241,8 +250,12 @@ void GeneralSettingsWidget::fillLanguageBox() const void GeneralSettingsWidget::apply() { + bool showRestart = generalSettings().provideSplitterCursors.volatileValue() + != generalSettings().provideSplitterCursors.value(); generalSettings().apply(); generalSettings().writeSettings(); + if (showRestart) + ICore::askForRestart(Tr::tr("The cursors for resizing views will change after restart.")); int currentIndex = m_languageBox->currentIndex(); setLanguage(m_languageBox->itemData(currentIndex, Qt::UserRole).toString()); diff --git a/src/plugins/coreplugin/generalsettings.h b/src/plugins/coreplugin/generalsettings.h index 498e243b2a4..202bed45954 100644 --- a/src/plugins/coreplugin/generalsettings.h +++ b/src/plugins/coreplugin/generalsettings.h @@ -13,6 +13,7 @@ public: GeneralSettings(); Utils::BoolAspect showShortcutsInContextMenus{this}; + Utils::BoolAspect provideSplitterCursors{this}; static void applyToolbarStyleFromSettings(); }; diff --git a/src/plugins/coreplugin/minisplitter.cpp b/src/plugins/coreplugin/minisplitter.cpp index e4e9db129bb..8fdec456b0b 100644 --- a/src/plugins/coreplugin/minisplitter.cpp +++ b/src/plugins/coreplugin/minisplitter.cpp @@ -3,6 +3,8 @@ #include "minisplitter.h" +#include "generalsettings.h" + #include #include @@ -13,6 +15,72 @@ namespace Core { namespace Internal { +// cursor images / masks taken from qplatformcursor.cpp +static QCursor hsplitCursor() +{ + static const uchar hsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03, + 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const uchar hsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00, + 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, + 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00, + 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + static QBitmap cursorImg = QBitmap::fromData({32, 32}, hsplit_bits); + static QBitmap mask = QBitmap::fromData({32, 32}, hsplitm_bits); + static QCursor cursor(cursorImg, mask, 15, 15); + return cursor; +} + +static QCursor vsplitCursor() +{ + static const uchar vsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static const uchar vsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + static QBitmap cursorImg = QBitmap::fromData({32, 32}, vsplit_bits); + static QBitmap mask = QBitmap::fromData({32, 32}, vsplitm_bits); + static QCursor cursor(cursorImg, mask, 15, 15); + return cursor; +} + class MiniSplitterHandle : public QSplitterHandle { public: @@ -22,6 +90,8 @@ public: { setMask(QRegion(contentsRect())); setAttribute(Qt::WA_MouseNoMask, true); + if (generalSettings().provideSplitterCursors()) + setCursor(orientation == Qt::Horizontal ? hsplitCursor() : vsplitCursor()); } protected: void resizeEvent(QResizeEvent *event) override;