From cf034b2fd7fd5647ef510dcda501eac6f2bed59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 24 Mar 2026 13:00:52 +0100 Subject: [PATCH 1/8] macOS: Fix ability to choose type when adding properties (#4459) On macOS, clicking the type combo box would immediately cause the property to get added or canceled due to the loss of focus. This was fixed in two ways: - Override ComboBox::showPopup() to ensure the combo box has focus before opening the popup, so that focus returns to it when the popup closes. - Use a delayed check in the focus-out handler, skipping action when a popup is active (QApplication::activePopupWidget) or when focus has returned to the property row. Closes #4445 (cherry picked from commit da4153bacf5177b91bb86cf1df1687d86d73535b) --- src/tiled/propertyeditorwidgets.cpp | 8 ++++++++ src/tiled/propertyeditorwidgets.h | 1 + src/tiled/variantmapproperty.cpp | 29 +++++++++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/tiled/propertyeditorwidgets.cpp b/src/tiled/propertyeditorwidgets.cpp index d18f210c62..414a145d35 100644 --- a/src/tiled/propertyeditorwidgets.cpp +++ b/src/tiled/propertyeditorwidgets.cpp @@ -287,6 +287,14 @@ bool ComboBox::event(QEvent *event) return QComboBox::event(event); } +void ComboBox::showPopup() +{ + // Ensure the combo box has focus before opening the popup, so that focus + // returns to it when the popup closes (fails without this on macOS). + setFocus(); + QComboBox::showPopup(); +} + void ComboBox::keyPressEvent(QKeyEvent *event) { switch (event->key()) { diff --git a/src/tiled/propertyeditorwidgets.h b/src/tiled/propertyeditorwidgets.h index 74e0e38413..17f1656fc0 100644 --- a/src/tiled/propertyeditorwidgets.h +++ b/src/tiled/propertyeditorwidgets.h @@ -79,6 +79,7 @@ class ComboBox : public QComboBox protected: bool event(QEvent *event) override; + void showPopup() override; void keyPressEvent(QKeyEvent *event) override; void wheelEvent(QWheelEvent *event) override; }; diff --git a/src/tiled/variantmapproperty.cpp b/src/tiled/variantmapproperty.cpp index 95ca502f99..73dfa7d102 100644 --- a/src/tiled/variantmapproperty.cpp +++ b/src/tiled/variantmapproperty.cpp @@ -37,6 +37,7 @@ #include #include #include +#include namespace Tiled { @@ -767,18 +768,26 @@ QWidget *AddValueProperty::createLabel(int level, QWidget *parent) nameEdit->installEventFilter(this); - connect(qApp, &QApplication::focusChanged, this, [=](QWidget *, QWidget *focusWidget) { - // Ignore focus in different windows (popups, dialogs, etc.) - if (!focusWidget || focusWidget->window() != parent->window()) - return; + QPointer self = this; + + // Request add or removal if focus moved elsewhere. Use a delayed check + // to allow for transient focus changes (necessary on macOS). + connect(qApp, &QApplication::focusChanged, parent, [self, parent] { + QTimer::singleShot(0, parent, [self, parent] { + if (!self || QApplication::activePopupWidget()) + return; + + auto currentFocus = QApplication::focusWidget(); + if (!currentFocus || currentFocus->window() != parent->window()) + return; + if (parent->isAncestorOf(currentFocus)) + return; - // Request add or removal if focus moved elsewhere - if (!parent->isAncestorOf(focusWidget)) { - if (!name().isEmpty()) - emit addRequested(false); // add without focusing, in response to focus out + if (!self->name().isEmpty()) + emit self->addRequested(false); // add without focusing, in response to focus out else - emit removeRequested(); - } + emit self->removeRequested(); + }); }); return nameEdit; From b988b72368ea88a1fd2958d24a0464516fecd9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Tue, 24 Mar 2026 16:20:55 +0100 Subject: [PATCH 2/8] Fix Properties view flicker when switching between objects (#4460) Suppress updates on the scroll widget during the properties rebuild and re-enable them with a double deferred QTimer::singleShot(0) call. This ensures that all scheduled layout requests are fully processed before the next paint. (cherry picked from commit 17a47f40107e3354b7103592e3261e55d22bc6df) --- src/tiled/propertieswidget.cpp | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/tiled/propertieswidget.cpp b/src/tiled/propertieswidget.cpp index cbb8510af7..155a25d7f8 100644 --- a/src/tiled/propertieswidget.cpp +++ b/src/tiled/propertieswidget.cpp @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,41 @@ namespace Tiled { +/** + * Suppresses widget updates for the duration of a scope. Updates are + * re-enabled with a double-deferred timer to ensure all cascading layout + * requests have been processed before the next paint. + */ +class ScopedUpdatesDisabler +{ +public: + explicit ScopedUpdatesDisabler(QWidget *widget) + : mWidget(widget) + , mHadUpdatesEnabled(widget->updatesEnabled()) + { + widget->setUpdatesEnabled(false); + } + + ~ScopedUpdatesDisabler() + { + if (!mHadUpdatesEnabled) + return; + + QTimer::singleShot(0, mWidget, [w = mWidget] { + QTimer::singleShot(0, w, [w] { + w->setUpdatesEnabled(true); + }); + }); + } + + Q_DISABLE_COPY_MOVE(ScopedUpdatesDisabler) + +private: + QWidget *mWidget; + bool mHadUpdatesEnabled; +}; + + template<> EnumData enumData() { return {{ @@ -2390,6 +2426,8 @@ void PropertiesWidget::selectCustomProperty(const QString &name, bool focus) void PropertiesWidget::currentObjectChanged(Object *object) { + const ScopedUpdatesDisabler updatesDisabler(mPropertiesView); + if (mPropertiesObject) { // Remember the expanded states const auto &subProperties = mPropertiesObject->subProperties(); From c852233d5c4d6a4630ea6ffdba5f8d6902aaebbc Mon Sep 17 00:00:00 2001 From: whatever_kunaal <143793407+kunal649@users.noreply.github.com> Date: Wed, 25 Mar 2026 01:14:02 +0530 Subject: [PATCH 3/8] Don't update selection mode indicator when Alt would move objects (#4434) Fixes #3719 (cherry picked from commit 57dc9e4654f837f0308939499d45a1d43eea13a9) --- src/tiled/objectselectiontool.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tiled/objectselectiontool.cpp b/src/tiled/objectselectiontool.cpp index 6d9da38475..d2d53dbb67 100644 --- a/src/tiled/objectselectiontool.cpp +++ b/src/tiled/objectselectiontool.cpp @@ -741,11 +741,15 @@ void ObjectSelectionTool::modifiersChanged(Qt::KeyboardModifiers modifiers) { mModifiers = modifiers; - if ((mSelectionMode == Qt::IntersectsItemShape) ^ modifiers.testFlag(Qt::AltModifier)) - mSelectIntersected->setChecked(true); - else - mSelectContained->setChecked(true); + const bool hasSelection = mapDocument() && !mapDocument()->selectedObjects().isEmpty(); + const bool altWillMove = !mMousePressed && hasSelection; + if (!altWillMove) { + if ((mSelectionMode == Qt::IntersectsItemShape) ^ modifiers.testFlag(Qt::AltModifier)) + mSelectIntersected->setChecked(true); + else + mSelectContained->setChecked(true); + } refreshCursor(); } From 7309931ade646693857b6de0d0e7043abad5d647 Mon Sep 17 00:00:00 2001 From: whatever_kunaal <143793407+kunal649@users.noreply.github.com> Date: Wed, 25 Mar 2026 01:21:20 +0530 Subject: [PATCH 4/8] Fix status bar pixel coords being rounded instead of floored (#4426) Fixes #3833 (cherry picked from commit 640ba2bf2265cf7f019dfb3905f16d634b0c1679) --- src/tiled/abstractobjecttool.cpp | 2 +- src/tiled/abstractworldtool.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tiled/abstractobjecttool.cpp b/src/tiled/abstractobjecttool.cpp index a65b004e1d..4fa39ef0ae 100644 --- a/src/tiled/abstractobjecttool.cpp +++ b/src/tiled/abstractobjecttool.cpp @@ -181,7 +181,7 @@ void AbstractObjectTool::mouseMoved(const QPointF &pos, if (Layer *layer = currentLayer()) offsetPos -= mapScene()->absolutePositionForLayer(*layer); - const QPoint pixelPos = offsetPos.toPoint(); + const QPoint pixelPos(qFloor(offsetPos.x()), qFloor(offsetPos.y())); const QPointF tilePosF = mapDocument()->renderer()->screenToTileCoords(offsetPos); const int x = qFloor(tilePosF.x()); diff --git a/src/tiled/abstractworldtool.cpp b/src/tiled/abstractworldtool.cpp index 4bd55b91cc..775f20205d 100644 --- a/src/tiled/abstractworldtool.cpp +++ b/src/tiled/abstractworldtool.cpp @@ -112,7 +112,7 @@ void AbstractWorldTool::mouseMoved(const QPointF &pos, if (Layer *layer = currentLayer()) offsetPos -= mapScene()->absolutePositionForLayer(*layer); - const QPoint pixelPos = offsetPos.toPoint(); + const QPoint pixelPos(qFloor(offsetPos.x()), qFloor(offsetPos.y())); const QPointF tilePosF = mapDocument()->renderer()->screenToTileCoords(offsetPos); const int x = qFloor(tilePosF.x()); const int y = qFloor(tilePosF.y()); From 2d2feea40aecf22545b960789c70d41b372df5eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 25 Mar 2026 09:52:13 +0100 Subject: [PATCH 5/8] Prepare for Tiled 1.12.1 release --- NEWS.md | 7 +++++++ docs/conf.py | 2 +- org.mapeditor.Tiled.appdata.xml | 11 +++++++++++ tiled.qbs | 2 +- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7edb4e0f79..0f95cff709 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +### Tiled 1.12.1 (25 March 2026) + +* Fixed Properties view flicker when switching between objects or files (#4460) +* Fixed selection mode indicator to not toggle on Alt when it would move objects (by kunal649, #4434) +* Fixed status bar pixel coords being rounded instead of floored (by kunal649, #4426) +* macOS: Fix ability to choose type when adding properties (#4459) + ### Tiled 1.12.0 (13 March 2026) * Rewritten Properties view to enable direct widget interaction (#4045) diff --git a/docs/conf.py b/docs/conf.py index 20602f1231..00bb2c0ef2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -69,7 +69,7 @@ # The short X.Y version. version = '1.12' # The full version, including alpha/beta/rc tags. -release = '1.12.0' +release = '1.12.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/org.mapeditor.Tiled.appdata.xml b/org.mapeditor.Tiled.appdata.xml index 1d2e1f2b80..f991a3fe08 100644 --- a/org.mapeditor.Tiled.appdata.xml +++ b/org.mapeditor.Tiled.appdata.xml @@ -19,6 +19,17 @@ + + https://www.mapeditor.org/2026/03/25/tiled-1-12-1-released.html + +
    +
  • Fixed Properties view flicker when switching between objects or files (#4460)
  • +
  • Fixed selection mode indicator to not toggle on Alt when it would move objects (by kunal649, #4434)
  • +
  • Fixed status bar pixel coords being rounded instead of floored (by kunal649, #4426)
  • +
  • macOS: Fix ability to choose type when adding properties (#4459)
  • +
+
+
https://www.mapeditor.org/2026/03/12/tiled-1-12-released.html diff --git a/tiled.qbs b/tiled.qbs index 10c464ce2d..b197e9840a 100644 --- a/tiled.qbs +++ b/tiled.qbs @@ -6,7 +6,7 @@ Project { qbsSearchPaths: "qbs" minimumQbsVersion: "1.18" - property string version: Environment.getEnv("TILED_VERSION") || "1.12.0"; + property string version: Environment.getEnv("TILED_VERSION") || "1.12.1"; property bool snapshot: Environment.getEnv("TILED_SNAPSHOT") == "true" property bool release: Environment.getEnv("TILED_RELEASE") == "true" property string libDir: "lib" From 44981305857c2860b3d113c68e183defad42cc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 25 Mar 2026 15:09:21 +0100 Subject: [PATCH 6/8] GitHub Actions: Updated supported macOS versions (#4468) Since the update to Qt 6.10, the minimum supported macOS version is 13, so the Qt 5 build now applies to macOS 10.13 till macOS 12. I forgot to update this for the Tiled 1.11.1 and 1.11.2 releases, which due to the upgrade to Qt 6.8 at the time had a minimum supported version of macOS 12. --- .github/workflows/packages.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/packages.yml b/.github/workflows/packages.yml index fe413131b3..3f835f4986 100644 --- a/.github/workflows/packages.yml +++ b/.github/workflows/packages.yml @@ -196,12 +196,12 @@ jobs: include: - qt_version: 5.15.2 qt_modules: "" - version_suffix: "10.13-10.15" + version_suffix: "10.13-12" architectures: x86_64 cmake_architectures: x86_64 - qt_version: 6.10.2 qt_modules: "qtimageformats" - version_suffix: "11+" + version_suffix: "13+" architectures: x86_64,arm64 cmake_architectures: x86_64;arm64 From db0d1c47f5ad33bc71f35dfeb1cd870dfd6bf531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thorbj=C3=B8rn=20Lindeijer?= Date: Wed, 25 Mar 2026 16:39:20 +0100 Subject: [PATCH 7/8] Fix ability to change properties after deselecting current object (#4440) When deselecting the current object, its properties generally remain visible in the Properties view. But when changing any of the properties, the changes were only applied to "selected objects". Now, when there is still a MapObject set as the current object, changing its properties will apply to it regardless of whether it is still selected. --- NEWS.md | 1 + src/tiled/propertieswidget.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4efa98d001..4dce08ba01 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ ### Unreleased * Added 'Collapse All' action and 'Only Expand to Current' mode to Project view (with rhythmcache, #4346) +* Fixed ability to change properties after deselecting the current object (#4440) ### Tiled 1.12.1 (25 March 2026) diff --git a/src/tiled/propertieswidget.cpp b/src/tiled/propertieswidget.cpp index 155a25d7f8..5f03cde9fc 100644 --- a/src/tiled/propertieswidget.cpp +++ b/src/tiled/propertieswidget.cpp @@ -1946,7 +1946,7 @@ class MapObjectProperties : public ObjectProperties QUndoCommand *command = new ChangeMapObject(mapDocument(), mapObject(), property, value); - if (mapDocument()->selectedObjects().size() == 1) { + if (mapDocument()->selectedObjects().size() <= 1) { push(command); return; } From ac6461c66885aaaa107b0fa26bc53a4e48e44298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Huy=20V=C5=A9=20=28Josh=29?= Date: Wed, 25 Mar 2026 23:07:38 +0700 Subject: [PATCH 8/8] Reduce animated tile marker opacity during Wang editing (#4449) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Thorbjørn Lindeijer --- NEWS.md | 1 + src/tiled/tilesetview.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/NEWS.md b/NEWS.md index 4dce08ba01..9e0a67d0e4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,7 @@ ### Unreleased * Added 'Collapse All' action and 'Only Expand to Current' mode to Project view (with rhythmcache, #4346) +* Reduced animated tile marker opacity during terrain editing (by Huy Vũ, #4449) * Fixed ability to change properties after deselecting the current object (#4440) ### Tiled 1.12.1 (25 March 2026) diff --git a/src/tiled/tilesetview.cpp b/src/tiled/tilesetview.cpp index 41907c7543..a6cb444361 100644 --- a/src/tiled/tilesetview.cpp +++ b/src/tiled/tilesetview.cpp @@ -53,8 +53,6 @@ using namespace Tiled; -namespace { - static void setupTilesetGridTransform(const Tileset &tileset, QTransform &transform, QRect &targetRect) { if (tileset.orientation() == Tileset::Isometric) { @@ -77,6 +75,8 @@ static void setupTilesetGridTransform(const Tileset &tileset, QTransform &transf } } +namespace { + /** * The delegate for drawing tile items in the tileset view. */ @@ -95,7 +95,7 @@ class TileDelegate : public QAbstractItemDelegate const QModelIndex &index) const override; private: - static void drawFilmStrip(QPainter *painter, QRect targetRect); + static void drawFilmStrip(QPainter *painter, QRect targetRect, bool wangEditingActive); void drawWangOverlay(QPainter *painter, const Tile *tile, @@ -105,6 +105,8 @@ class TileDelegate : public QAbstractItemDelegate TilesetView *mTilesetView; }; +} // anonymous namespace + void TileDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const @@ -161,7 +163,7 @@ void TileDelegate::paint(QPainter *painter, // Overlay with film strip when animated if (mTilesetView->markAnimatedTiles() && tile->isAnimated()) - drawFilmStrip(painter, targetRect); + drawFilmStrip(painter, targetRect, mTilesetView->isEditWangSet()); const auto highlight = option.palette.highlight(); @@ -211,7 +213,7 @@ QSize TileDelegate::sizeHint(const QStyleOptionViewItem & /* option */, return QSize(extra, extra); } -void TileDelegate::drawFilmStrip(QPainter *painter, QRect targetRect) +void TileDelegate::drawFilmStrip(QPainter *painter, QRect targetRect, bool wangEditingActive) { painter->save(); @@ -224,7 +226,7 @@ void TileDelegate::drawFilmStrip(QPainter *painter, QRect targetRect) painter->scale(scale, scale); painter->translate(-18, 3); painter->rotate(-45); - painter->setOpacity(0.8); + painter->setOpacity(wangEditingActive ? 0.3 : 0.8); QRectF strip(0, 0, 32, 6); painter->fillRect(strip, Qt::black); @@ -278,8 +280,6 @@ void TileDelegate::drawWangOverlay(QPainter *painter, painter->restore(); } -} // anonymous namespace - TilesetView::TilesetView(QWidget *parent) : QTableView(parent) , mZoomable(new Zoomable(this)) @@ -504,7 +504,7 @@ void TilesetView::keyPressEvent(QKeyEvent *event) return; } - return QTableView::keyPressEvent(event); + QTableView::keyPressEvent(event); } void TilesetView::setRelocateTiles(bool enabled)