[graphics/krita] /: swap, reset , choose foreground/background colour widgets

Dmitry Kazakov <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 9d2dd478eb1fff11a797f40fbc4c548adb8e0b7b by Dmitry Kazakov, on behalf of Arkady Flury.
Committed on 17/07/2026 at 08:13.
Pushed by dkazakov into branch 'master'.

swap, reset , choose foreground/background colour widgets

changes:
swap widget
reset widget
choose foreground colour widget
background colour widget
reset arrows to svg

A  +11   -0    krita/pics/svg/dark_background_colour.svg
A  +14   -0    krita/pics/svg/dark_dual_colour.svg
A  +11   -0    krita/pics/svg/dark_forgound_colour.svg
A  +5    -0    krita/pics/svg/dark_reset_colour.svg
A  +6    -0    krita/pics/svg/dark_swap_colour.svg
A  +11   -0    krita/pics/svg/light_background_colour.svg
A  +14   -0    krita/pics/svg/light_dual_colour.svg
A  +11   -0    krita/pics/svg/light_forgound_colour.svg
A  +5    -0    krita/pics/svg/light_reset_colour.svg
A  +6    -0    krita/pics/svg/light_swap_colour.svg
A  +35   -0    krita/pics/svg/reset_arrow.svg
M  +12   -0    krita/pics/svg/svg-icons.qrc
A  +37   -0    krita/pics/svg/swap_arrow.svg
M  +4    -0    libs/ui/CMakeLists.txt
M  +4    -4    libs/ui/KisViewManager.cpp
M  +96   -21   libs/ui/kis_control_frame.cpp
M  +9    -1    libs/ui/kis_control_frame.h
A  +54   -0    libs/ui/widgets/KoBackgroundColour.cpp     [License: LGPL(v2.0)]
A  +28   -0    libs/ui/widgets/KoBackgroundColour.h     [License: LGPL(v2.0)]
M  +113  -120  libs/ui/widgets/KoDualColorButton.cpp
M  +35   -9    libs/ui/widgets/KoDualColorButton.h
A  +53   -0    libs/ui/widgets/KoForegroundColour.cpp     [License: LGPL(v2.0)]
A  +28   -0    libs/ui/widgets/KoForegroundColour.h     [License: LGPL(v2.0)]
A  +51   -0    libs/ui/widgets/KoResetBgFgColours.cpp     [License: LGPL(v2.0)]
A  +31   -0    libs/ui/widgets/KoResetBgFgColours.h     [License: LGPL(v2.0)]
A  +50   -0    libs/ui/widgets/KoSwapBgFgColours.cpp     [License: LGPL(v2.0)]
A  +29   -0    libs/ui/widgets/KoSwapBgFgColours.h     [License: LGPL(v2.0)]
D  +0    -6    libs/widgets/dcolorarrow.xbm

https://invent.kde.org/graphics/krita/-/commit/9d2dd478eb1fff11a797f40fbc4c548adb8e0b7b

diff --git a/krita/pics/svg/dark_background_colour.svg b/krita/pics/svg/dark_background_colour.svg
new file mode 100644
index 00000000000..5b94d61ecc0
--- /dev/null
+++ b/krita/pics/svg/dark_background_colour.svg
@@ -0,0 +1,11 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_2)">
+<rect width="7" height="7" fill="#373737"/>
+<path d="M5 8H8V5H16V16H5V8Z" fill="#373737"/>
+</g>
+<defs>
+<clipPath id="clip0_560_2">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/dark_dual_colour.svg b/krita/pics/svg/dark_dual_colour.svg
new file mode 100644
index 00000000000..a1d09ede09a
--- /dev/null
+++ b/krita/pics/svg/dark_dual_colour.svg
@@ -0,0 +1,14 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_44)">
+<path d="M8 12V8H12H16V16H8V12Z" fill="#373737"/>
+<path d="M8 0V8H0L0 0L8 0Z" fill="#373737"/>
+<path d="M11.5 5L13.5 7.5L15.5 5H14V3H13V5H11.5Z" fill="#373737"/>
+<path d="M11 0.5L8.5 2.5L11 4.5L11 3H13V2H11V0.5Z" fill="#373737"/>
+<path d="M3 10C4.65685 10 6 11.3431 6 13C6 14.6569 4.65685 16 3 16C1.34315 16 0 14.6569 0 13H1C1 14.1046 1.89543 15 3 15C4.10457 15 5 14.1046 5 13C5 11.8954 4.10457 11 3 11V12.5L0.5 10.5L3 8.5V10Z" fill="#373737"/>
+</g>
+<defs>
+<clipPath id="clip0_560_44">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/dark_forgound_colour.svg b/krita/pics/svg/dark_forgound_colour.svg
new file mode 100644
index 00000000000..c35eaacefcf
--- /dev/null
+++ b/krita/pics/svg/dark_forgound_colour.svg
@@ -0,0 +1,11 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_39)">
+<path d="M9 12H12V9H16V16H9L9 12Z" fill="#373737"/>
+<path d="M11 0V11H0V0H11Z" fill="#373737"/>
+</g>
+<defs>
+<clipPath id="clip0_560_39">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/dark_reset_colour.svg b/krita/pics/svg/dark_reset_colour.svg
new file mode 100644
index 00000000000..355a88917e7
--- /dev/null
+++ b/krita/pics/svg/dark_reset_colour.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 13H8V9H11V16H4V13Z" fill="#373737"/>
+<path d="M7 5V12H0L0 5H7Z" fill="#373737"/>
+<path d="M11 2C12.6569 2 14 3.34315 14 5C14 6.65685 12.6569 8 11 8C9.34315 8 8 6.65685 8 5H9C9 6.10457 9.89543 7 11 7C12.1046 7 13 6.10457 13 5C13 3.89543 12.1046 3 11 3V4.5L8.5 2.5L11 0.5V2Z" fill="#373737"/>
+</svg>
diff --git a/krita/pics/svg/dark_swap_colour.svg b/krita/pics/svg/dark_swap_colour.svg
new file mode 100644
index 00000000000..a5ed0a07c62
--- /dev/null
+++ b/krita/pics/svg/dark_swap_colour.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 13H8V9H11V16H4V13Z" fill="#373737"/>
+<path d="M7 5V12H0L0 5H7Z" fill="#373737"/>
+<path d="M10.5 6L12.5 8.5L14.5 6H13V4H12V6H10.5Z" fill="#373737"/>
+<path d="M10 1.5L7.5 3.5L10 5.5L9.99996 4H12V3H10V1.5Z" fill="#373737"/>
+</svg>
diff --git a/krita/pics/svg/light_background_colour.svg b/krita/pics/svg/light_background_colour.svg
new file mode 100644
index 00000000000..b76d8c76460
--- /dev/null
+++ b/krita/pics/svg/light_background_colour.svg
@@ -0,0 +1,11 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_2)">
+<rect width="7" height="7" fill="#D2D2D2"/>
+<path d="M5 8H8V5H16V16H5V8Z" fill="#D2D2D2"/>
+</g>
+<defs>
+<clipPath id="clip0_560_2">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/light_dual_colour.svg b/krita/pics/svg/light_dual_colour.svg
new file mode 100644
index 00000000000..025b1bba676
--- /dev/null
+++ b/krita/pics/svg/light_dual_colour.svg
@@ -0,0 +1,14 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_44)">
+<path d="M8 12V8H12H16V16H8V12Z" fill="#D2D2D2"/>
+<path d="M8 0V8H0L0 0L8 0Z" fill="#D2D2D2"/>
+<path d="M11.5 5L13.5 7.5L15.5 5H14V3H13V5H11.5Z" fill="#D2D2D2"/>
+<path d="M11 0.5L8.5 2.5L11 4.5L11 3H13V2H11V0.5Z" fill="#D2D2D2"/>
+<path d="M3 10C4.65685 10 6 11.3431 6 13C6 14.6569 4.65685 16 3 16C1.34315 16 0 14.6569 0 13H1C1 14.1046 1.89543 15 3 15C4.10457 15 5 14.1046 5 13C5 11.8954 4.10457 11 3 11V12.5L0.5 10.5L3 8.5V10Z" fill="#D2D2D2"/>
+</g>
+<defs>
+<clipPath id="clip0_560_44">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/light_forgound_colour.svg b/krita/pics/svg/light_forgound_colour.svg
new file mode 100644
index 00000000000..d3e46c2c367
--- /dev/null
+++ b/krita/pics/svg/light_forgound_colour.svg
@@ -0,0 +1,11 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<g clip-path="url(#clip0_560_39)">
+<path d="M9 12H12V9H16V16H9L9 12Z" fill="#D2D2D2"/>
+<path d="M11 0V11H0V0H11Z" fill="#D2D2D2"/>
+</g>
+<defs>
+<clipPath id="clip0_560_39">
+<rect width="16" height="16" fill="white"/>
+</clipPath>
+</defs>
+</svg>
diff --git a/krita/pics/svg/light_reset_colour.svg b/krita/pics/svg/light_reset_colour.svg
new file mode 100644
index 00000000000..e2a83354a50
--- /dev/null
+++ b/krita/pics/svg/light_reset_colour.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 13H8V9H11V16H4V13Z" fill="#D2D2D2"/>
+<path d="M7 5V12H0L0 5H7Z" fill="#D2D2D2"/>
+<path d="M11 2C12.6569 2 14 3.34315 14 5C14 6.65685 12.6569 8 11 8C9.34315 8 8 6.65685 8 5H9C9 6.10457 9.89543 7 11 7C12.1046 7 13 6.10457 13 5C13 3.89543 12.1046 3 11 3V4.5L8.5 2.5L11 0.5V2Z" fill="#D2D2D2"/>
+</svg>
diff --git a/krita/pics/svg/light_swap_colour.svg b/krita/pics/svg/light_swap_colour.svg
new file mode 100644
index 00000000000..be06f289f05
--- /dev/null
+++ b/krita/pics/svg/light_swap_colour.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4 13H8V9H11V16H4V13Z" fill="#D2D2D2"/>
+<path d="M7 5V12H0L0 5H7Z" fill="#D2D2D2"/>
+<path d="M10.5 6L12.5 8.5L14.5 6H13V4H12V6H10.5Z" fill="#D2D2D2"/>
+<path d="M10 1.5L7.5 3.5L10 5.5L9.99996 4H12V3H10V1.5Z" fill="#D2D2D2"/>
+</svg>
diff --git a/krita/pics/svg/reset_arrow.svg b/krita/pics/svg/reset_arrow.svg
new file mode 100644
index 00000000000..570a65bd8c8
--- /dev/null
+++ b/krita/pics/svg/reset_arrow.svg
@@ -0,0 +1,35 @@
+<svg width="10" height="12" viewBox="0 0 10 12" fill="none" xmlns="http://www.w3.org/2000/svg"  xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<metadata id="metadata7">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:date>2026</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Arkady Flury</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+<path d="M5 2C7.76142 2.00001 10 4.23858 10 7C10 9.76142 7.76142 12 5 12C2.23858 12 0 9.76142 0 7H1C1 9.20914 2.79086 11 5 11C7.20913 11 9 9.20913 9 7C9 4.79087 7.20913 3.00001 5 3V5L2 2.5L5 0V2Z" fill="#EE0000"/>
+</svg>
diff --git a/krita/pics/svg/svg-icons.qrc b/krita/pics/svg/svg-icons.qrc
index 6add1305fde..ad8dd3c9128 100644
--- a/krita/pics/svg/svg-icons.qrc
+++ b/krita/pics/svg/svg-icons.qrc
@@ -4,6 +4,18 @@
 -->
 <RCC>
     <qresource prefix="/">
+        <file>dark_reset_colour.svg</file>
+        <file>light_reset_colour.svg</file>
+        <file>dark_dual_colour.svg</file>
+        <file>light_dual_colour.svg</file>
+        <file>dark_forgound_colour.svg</file>
+        <file>light_forgound_colour.svg</file>
+        <file>dark_background_colour.svg</file>
+        <file>light_background_colour.svg</file>
+        <file>dark_swap_colour.svg</file>
+        <file>light_swap_colour.svg</file>
+        <file>swap_arrow.svg</file>
+        <file>reset_arrow.svg</file>
         <file>dark_preferences-desktop-locale.svg</file>
         <file>light_preferences-desktop-locale.svg</file>
         <file>dark_get_started.svg</file>
diff --git a/krita/pics/svg/swap_arrow.svg b/krita/pics/svg/swap_arrow.svg
new file mode 100644
index 00000000000..d42c6999316
--- /dev/null
+++ b/krita/pics/svg/swap_arrow.svg
@@ -0,0 +1,37 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg"  xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+<metadata id="metadata7">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:date>2026</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>superfurryfrog</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+
+<path d="M4 0L0 3.5L4 7V4H8V3H4V0Z" fill="white"/>
+<path d="M5 8L8.5 12L12 8H9V4H8V8H5Z" fill="white"/>
+</svg>
diff --git a/libs/ui/CMakeLists.txt b/libs/ui/CMakeLists.txt
index f5cec959cf5..cf7eb79fe0d 100644
--- a/libs/ui/CMakeLists.txt
+++ b/libs/ui/CMakeLists.txt
@@ -299,6 +299,10 @@ set(kritaui_LIB_SRCS
     widgets/kis_preset_live_preview_view.cpp
     widgets/KisScreenColorSampler.cpp
     widgets/KoDualColorButton.cpp
+    widgets/KoForegroundColour.cpp
+    widgets/KoBackgroundColour.cpp
+    widgets/KoSwapBgFgColours.cpp
+    widgets/KoResetBgFgColours.cpp
     widgets/KoStrokeConfigWidget.cpp
     widgets/KoFillConfigWidget.cpp
     widgets/KisLayerStyleAngleSelector.cpp
diff --git a/libs/ui/KisViewManager.cpp b/libs/ui/KisViewManager.cpp
index dd412798cc9..1acdc7fe845 100644
--- a/libs/ui/KisViewManager.cpp
+++ b/libs/ui/KisViewManager.cpp
@@ -816,11 +816,11 @@ void KisViewManager::createActions()
     d->showPixelGrid = actionManager()->createAction("view_pixel_grid");
     slotUpdatePixelGridAction();
 
-    d->toggleFgBg = actionManager()->createAction("toggle_fg_bg");
-    connect(d->toggleFgBg, SIGNAL(triggered(bool)), this, SLOT(slotToggleFgBg()));
+    // d->toggleFgBg = actionManager()->createAction("toggle_fg_bg");
+    // connect(d->toggleFgBg, SIGNAL(triggered(bool)), this, SLOT(slotToggleFgBg()));
 
-    d->resetFgBg =  actionManager()->createAction("reset_fg_bg");
-    connect(d->resetFgBg, SIGNAL(triggered(bool)), this, SLOT(slotResetFgBg()));
+    // d->resetFgBg =  actionManager()->createAction("reset_fg_bg");
+    // connect(d->resetFgBg, SIGNAL(triggered(bool)), this, SLOT(slotResetFgBg()));
 
     d->toggleBrushOutline =  actionManager()->createAction("toggle_brush_outline");
     connect(d->toggleBrushOutline, SIGNAL(triggered(bool)), this, SLOT(slotToggleBrushOutline()));
diff --git a/libs/ui/kis_control_frame.cpp b/libs/ui/kis_control_frame.cpp
index 6120281b8c6..51c761dc07f 100644
--- a/libs/ui/kis_control_frame.cpp
+++ b/libs/ui/kis_control_frame.cpp
@@ -24,7 +24,13 @@
 #include <klocalizedstring.h>
 #include <QAction>
 #include <kactioncollection.h>
+
 #include <KoDualColorButton.h>
+#include <KoForegroundColour.h>
+#include <KoBackgroundColour.h>
+#include <KoSwapBgFgColours.h>
+#include <KoResetBgFgColours.h>
+
 #include <resources/KoAbstractGradient.h>
 #include <KoResourceServer.h>
 #include <KoResourceServerProvider.h>
@@ -83,28 +89,105 @@ void KisControlFrame::setup(QWidget *parent)
     m_viewManager->actionCollection()->addAction(ResourceType::Gradients, action);
     action->setDefaultWidget(m_gradientWidget);
     connect(action, SIGNAL(triggered()), m_gradientWidget, SLOT(showPopupWidget()));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_gradientWidget, SLOT(update()));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_gradientWidget, SLOT(update()));
     m_gradientChooserPopup->addAction(action);
 
 
     // XXX: KOMVC we don't have a canvas here yet, needs a setImageView
     const KoColorDisplayRendererInterface *displayRenderer = \
         KisDisplayColorConverter::dumbConverterInstance()->displayRendererInterface();
-    m_dual = new KoDualColorButton(m_viewManager->canvasResourceProvider()->fgColor(),
-                                                     m_viewManager->canvasResourceProvider()->bgColor(), displayRenderer,
-                                                     m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget());
+    m_dual = new KoDualColorButton(m_viewManager->canvasResourceProvider(), displayRenderer,
+                                                     m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget()); 
     m_dual->setPopDialog(true);
     action = new QWidgetAction(this);
     action->setText(i18n("&Choose foreground and background colors"));
+    action->setIcon(KisIconUtils::loadIcon("dual_colour"));
     m_viewManager->actionCollection()->addAction("dual", action);
     action->setDefaultWidget(m_dual);
     connect(m_dual, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor)));
     connect(m_dual, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetBGColor(KoColor)));
     connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_dual, SLOT(setBackgroundColor(KoColor)));
     connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_dual, SLOT(setForegroundColor(KoColor)));
-    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_gradientWidget, SLOT(update()));
-    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_gradientWidget, SLOT(update()));
     m_dual->setFixedSize(28, 28);
-    connect(m_viewManager, SIGNAL(viewChanged()), SLOT(slotUpdateDisplayRenderer()));
+    connect(m_viewManager, &KisViewManager::viewChanged, [this]() {
+        slotUpdateDisplayRenderer(m_dual);
+    });
+
+
+    m_foreground = new KoForegroundColour(m_viewManager->canvasResourceProvider(), displayRenderer,
+                                                    m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget());
+    m_foreground->setPopDialog(true);
+    action = new QWidgetAction(this);
+    action->setText(i18n("&Choose foreground colour"));
+    action->setIcon(KisIconUtils::loadIcon("forgound_colour"));
+    m_viewManager->actionCollection()->addAction("chooseForegroundColor", action);
+    action->setDefaultWidget(m_foreground);
+    connect(m_foreground, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor)));
+    connect(m_foreground, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetBGColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_foreground, SLOT(setBackgroundColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_foreground, SLOT(setForegroundColor(KoColor)));
+    m_foreground->setFixedSize(28, 28);
+    connect(action, SIGNAL(triggered()), m_foreground, SLOT(openForegroundDialog()));
+    connect(m_viewManager, &KisViewManager::viewChanged, [this](){
+        slotUpdateDisplayRenderer(m_foreground);
+    });
+
+
+    m_background = new KoBackgroundColour(m_viewManager->canvasResourceProvider(), displayRenderer,
+                                                    m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget());
+    m_background->setPopDialog(true);
+    action = new QWidgetAction(this);
+    action->setText(i18n("&Choose background colour"));
+    action->setIcon(KisIconUtils::loadIcon("background_colour"));
+    m_viewManager->actionCollection()->addAction("chooseBackgroundColor", action);
+    action->setDefaultWidget(m_background);
+    connect(m_background, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor)));
+    connect(m_background, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetBGColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_background, SLOT(setBackgroundColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_background, SLOT(setForegroundColor(KoColor)));
+    m_background->setFixedSize(28, 28);
+    connect(action, SIGNAL(triggered()), m_background, SLOT(openBackgroundDialog()));
+    connect(m_viewManager, &KisViewManager::viewChanged, [this]() {
+        slotUpdateDisplayRenderer(m_background);
+    });
+
+
+    m_swap = new KoSwapBgFgColours(m_viewManager->canvasResourceProvider(), displayRenderer,
+                                                    m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget());
+    m_swap->setPopDialog(true);
+    action = new QWidgetAction(this);
+    action->setText(i18n("&Swap Foreground and Background Colors"));
+    action->setIcon(KisIconUtils::loadIcon("swap_colour"));
+    m_viewManager->actionCollection()->addAction("toggle_fg_bg", action);
+    action->setDefaultWidget(m_swap);
+    connect(m_swap, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor)));
+    connect(m_swap, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetBGColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigBGColorChanged(KoColor)), m_swap, SLOT(setBackgroundColor(KoColor)));
+    connect(m_viewManager->canvasResourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), m_swap, SLOT(setForegroundColor(KoColor)));
+    m_swap->setFixedSize(28, 28);
+    connect(action, SIGNAL(triggered()), m_swap, SLOT(swapColours()));
+    connect(m_viewManager, &KisViewManager::viewChanged, [this]() {
+        slotUpdateDisplayRenderer(m_swap);
+    });
+
+
+    m_reset = new KoResetBgFgColours(m_viewManager->canvasResourceProvider(), displayRenderer,
+                                                    m_viewManager->mainWindowAsQWidget(), m_viewManager->mainWindowAsQWidget());
+    m_reset->setPopDialog(true);
+    action = new QWidgetAction(this);
+    action->setText(i18n("&reset Foreground and Background Colors"));
+    action->setIcon(KisIconUtils::loadIcon("reset_colour"));
+    m_viewManager->actionCollection()->addAction("reset_fg_bg", action);
+    action->setDefaultWidget(m_reset);
+    connect(m_reset, SIGNAL(foregroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetFGColor(KoColor)));
+    connect(m_reset, SIGNAL(backgroundColorChanged(KoColor)), m_viewManager->canvasResourceProvider(), SLOT(slotSetBGColor(KoColor)));
+    m_reset->setFixedSize(28, 28);
+    connect(action, SIGNAL(triggered()), m_reset, SLOT(ResetColours()));
+    connect(m_viewManager, &KisViewManager::viewChanged, [this]() {
+        slotUpdateDisplayRenderer(m_reset);
+    });
+    
 
     m_paintopBox = new KisPaintopBox(m_viewManager, parent, "paintopbox");
 
@@ -113,15 +196,6 @@ void KisControlFrame::setup(QWidget *parent)
     m_viewManager->actionCollection()->addAction("paintops", action);
     action->setDefaultWidget(m_paintopBox);
 
-    action = new QWidgetAction(this);
-    action->setText(i18n("&Open Foreground color selector"));
-    m_viewManager->actionCollection()->addAction("chooseForegroundColor", action);
-    connect(action, SIGNAL(triggered()), m_dual, SLOT(openForegroundDialog()));
-
-    action = new QWidgetAction(this);
-    action->setText(i18n("&Open Background color selector"));
-    m_viewManager->actionCollection()->addAction("chooseBackgroundColor", action);
-    connect(action, SIGNAL(triggered()), m_dual, SLOT(openBackgroundDialog()));
 
     createDockerBox(m_viewManager);
 
@@ -131,18 +205,19 @@ void KisControlFrame::setup(QWidget *parent)
     action->setDefaultWidget(m_dockerPopupButton);
 }
 
-void KisControlFrame::slotUpdateDisplayRenderer()
+void KisControlFrame::slotUpdateDisplayRenderer(KoDualColorButton* colourSelector)
 {
     if (m_viewManager->canvasBase()){
-        m_dual->setDisplayRenderer(m_viewManager->canvasBase()->displayColorConverter()->displayRendererInterface());
-        m_dual->setColorSpace(m_viewManager->canvasBase()->image()->colorSpace());
-        m_viewManager->canvasBase()->image()->disconnect(m_dual);
-        connect(m_viewManager->canvasBase()->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), m_dual, SLOT(setColorSpace(const KoColorSpace*)), Qt::UniqueConnection);
+        colourSelector->setDisplayRenderer(m_viewManager->canvasBase()->displayColorConverter()->displayRendererInterface());
+        colourSelector->updateColorSpace();
+        m_viewManager->canvasBase()->image()->disconnect(colourSelector);
+        connect(m_viewManager->canvasBase()->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), colourSelector, SLOT(updateColorSpace()), Qt::UniqueConnection);
     } else if (m_viewManager->viewCount()==0) {
-        m_dual->setDisplayRenderer();
+        colourSelector->setDisplayRenderer();
     }
 }
 
+
 void KisControlFrame::slotSetPattern(KoPatternSP pattern)
 {
     KIS_SAFE_ASSERT_RECOVER_RETURN(pattern);
diff --git a/libs/ui/kis_control_frame.h b/libs/ui/kis_control_frame.h
index eec2bab3125..f538fc1f565 100644
--- a/libs/ui/kis_control_frame.h
+++ b/libs/ui/kis_control_frame.h
@@ -27,6 +27,10 @@ class KisDockerHud;
 class KisViewManager;
 class KisIconWidget;
 class KoDualColorButton;
+class KoForegroundColour;
+class KoBackgroundColour;
+class KoSwapBgFgColours;
+class KoResetBgFgColours;
 
 /**
  *   Control Frame - status display with access to
@@ -51,7 +55,7 @@ private Q_SLOTS:
     void slotSetPattern(KoPatternSP pattern);
     void slotSetGradient(KoAbstractGradientSP gradient);
     void updateGradientPreviewOnPopupButton(KoAbstractGradientSP gradient);
-    void slotUpdateDisplayRenderer();
+    void slotUpdateDisplayRenderer(KoDualColorButton* colourSelector);
 
 private:
 
@@ -81,6 +85,10 @@ private:
     KisIconWidget *m_dockerPopupButton {nullptr};
 
     KoDualColorButton *m_dual {nullptr};
+    KoForegroundColour *m_foreground {nullptr};
+    KoBackgroundColour *m_background {nullptr};
+    KoSwapBgFgColours *m_swap {nullptr};
+    KoResetBgFgColours *m_reset {nullptr};
     KoCheckerBoardPainter m_checkersPainter;
 
 };
diff --git a/libs/ui/widgets/KoBackgroundColour.cpp b/libs/ui/widgets/KoBackgroundColour.cpp
new file mode 100644
index 00000000000..7049f356ad4
--- /dev/null
+++ b/libs/ui/widgets/KoBackgroundColour.cpp
@@ -0,0 +1,54 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#include "KoBackgroundColour.h"
+#include <QPainter>
+#include <QColorDialog>
+#include <QEvent>
+#include <kconfiggroup.h>
+#include <ksharedconfig.h>
+
+
+KoBackgroundColour::KoBackgroundColour(KisCanvasResourceProvider *canvasResourceProvider,
+                                     const KoColorDisplayRendererInterface *displayRenderer,
+                                     QWidget *parent, QWidget *dialogParent)
+    : KoDualColorButton(canvasResourceProvider, displayRenderer, parent, dialogParent)
+{
+    foregroundRect = QRect( 0, 0, 12, 12);
+    backgroundRect = QRect( 6, 6, 22, 22);
+    setColorDialogState(Background);
+}
+
+
+void KoBackgroundColour::paint_icons(QPainter &painter)
+{
+    Q_UNUSED(painter);
+}
+
+void KoBackgroundColour::mousePressEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
+
+void KoBackgroundColour::mouseReleaseEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+    
+    KConfigGroup cfg =  KSharedConfig::openConfig()->group("colorselector");
+    bool usePlatformDialog = cfg.readEntry("UsePlatformColorDialog", false);
+    
+    backgroundSelect(usePlatformDialog);
+
+    update();
+}
+
+bool KoBackgroundColour::event(QEvent *event)
+{
+    if (event->type() == QEvent::ToolTip) {
+        this->setToolTip(i18n("Background color selector"));
+    }
+    return QWidget::event(event);
+}
diff --git a/libs/ui/widgets/KoBackgroundColour.h b/libs/ui/widgets/KoBackgroundColour.h
new file mode 100644
index 00000000000..68b31713c57
--- /dev/null
+++ b/libs/ui/widgets/KoBackgroundColour.h
@@ -0,0 +1,28 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#ifndef KOBACKGROUNDCOLOUR_H
+#define KOBACKGROUNDCOLOUR_H
+
+
+#include <KoDualColorButton.h>
+
+
+class KisCanvas2;
+
+class KRITAUI_EXPORT KoBackgroundColour : public KoDualColorButton {
+    Q_OBJECT
+public:
+    KoBackgroundColour(KisCanvasResourceProvider *canvasResourceProvider,
+                      const KoColorDisplayRendererInterface *displayRenderer = 0,
+                      QWidget *parent = 0, QWidget *dialogParent = 0);
+    void paint_icons(QPainter &painter) override;
+    void mouseReleaseEvent( QMouseEvent *event ) override;
+    void mousePressEvent( QMouseEvent *event ) override;
+    bool event(QEvent *event) override;
+};
+
+#endif
\ No newline at end of file
diff --git a/libs/ui/widgets/KoDualColorButton.cpp b/libs/ui/widgets/KoDualColorButton.cpp
index 335185d9637..9ddce966fc8 100644
--- a/libs/ui/widgets/KoDualColorButton.cpp
+++ b/libs/ui/widgets/KoDualColorButton.cpp
@@ -1,5 +1,6 @@
 /* This file is part of the KDE libraries
    SPDX-FileCopyrightText: 1999 Daniel M. Duley <[email protected]>
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
 
    SPDX-License-Identifier: LGPL-2.0-only
 */
@@ -11,13 +12,14 @@
 #include <kconfiggroup.h>
 #include <ksharedconfig.h>
 
-#include "dcolorarrow.xbm"
 #include "dcolorreset.xpm"
 
 #include <QColorDialog>
 #include "KisDlgInternalColorSelector.h"
 
 #include "kis_signals_blocker.h"
+#include <kis_icon.h>
+#include "kis_canvas_resource_provider.h"
 
 #include <QBrush>
 #include <QDrag>
@@ -28,8 +30,7 @@
 #include <QApplication>
 #include <kis_signal_auto_connection.h>
 
-
-class Q_DECL_HIDDEN KoDualColorButton::Private
+class KoDualColorButton::Private
 {
 public:
     Private(const KoColor &fgColor, const KoColor &bgColor,
@@ -40,39 +41,13 @@ public:
         , miniCtlFlag( false )
         , foregroundColor(fgColor)
         , backgroundColor(bgColor)
-
         , displayRenderer(_displayRenderer)
     {
-        updateArrows();
-        resetPixmap = QPixmap( (const char **)dcolorreset_xpm );
-
         popDialog = true;
     }
 
-    void updateArrows() {
-        arrowBitmap = QPixmap(12,12);
-        arrowBitmap.fill(Qt::transparent);
-
-        QPainter p(&arrowBitmap);
-        p.setPen(dialogParent->palette().windowText().color());
-
-        // arrow pointing left
-        p.drawLine(0, 3, 7, 3);
-        p.drawLine(1, 2, 1, 4);
-        p.drawLine(2, 1, 2, 5);
-        p.drawLine(3, 0, 3, 6);
-
-        // arrow pointing down
-        p.drawLine(8, 4, 8, 11);
-        p.drawLine(5, 8, 11, 8);
-        p.drawLine(6, 9, 10, 9);
-        p.drawLine(7, 10, 9, 10);
-    }
-
     QWidget* dialogParent;
 
-    QPixmap arrowBitmap;
-    QPixmap resetPixmap;
     bool dragFlag, miniCtlFlag;
     KoColor foregroundColor;
     KoColor backgroundColor;
@@ -91,6 +66,8 @@ public:
     void init(KoDualColorButton *q);
 };
 
+
+
 void KoDualColorButton::Private::init(KoDualColorButton *q)
 {
     if ( q->sizeHint().isValid() )
@@ -102,22 +79,14 @@ void KoDualColorButton::Private::init(KoDualColorButton *q)
     config.modal = false;
     colorSelectorDialog = new KisDlgInternalColorSelector(q, foregroundColor, config, caption, displayRenderer);
     connect(colorSelectorDialog, &KisDlgInternalColorSelector::finished, q, &KoDualColorButton::slotColorDialogClosed);
-}
 
-KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor, QWidget *parent, QWidget* dialogParent )
-    : QWidget( parent ),
-      d( new Private(foregroundColor, backgroundColor,
-                     dialogParent,
-                     KoDumbColorDisplayRenderer::instance()) )
-{
-    d->init(this);
 }
 
-KoDualColorButton::KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor,
+KoDualColorButton::KoDualColorButton(KisCanvasResourceProvider *canvasResourceProvider,
                                      const KoColorDisplayRendererInterface *displayRenderer,
                                      QWidget *parent, QWidget* dialogParent)
     : QWidget( parent ),
-      d( new Private(foregroundColor, backgroundColor,
+      d( new Private(canvasResourceProvider->fgColor(),canvasResourceProvider->bgColor(),
                      dialogParent,
                      displayRenderer) )
 {
@@ -129,6 +98,33 @@ KoDualColorButton::~KoDualColorButton()
     delete d;
 }
 
+void KoDualColorButton::updateArrows() {
+    resetPixmap = QPixmap( (const char **)dcolorreset_xpm );
+
+    QColor windowText = d->dialogParent->palette().windowText().color();
+
+    arrowBitmap = KisIconUtils::loadIcon("swap_arrow").pixmap(12,12);
+    
+    QPainter pen(&arrowBitmap);
+    
+    pen.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    pen.fillRect(arrowBitmap.rect(),windowText);
+    pen.end();
+
+    resetArrowPixmap = KisIconUtils::loadIcon("reset_arrow").pixmap(10,12);
+    
+    pen.begin(&resetArrowPixmap);
+
+    pen.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    pen.fillRect(resetArrowPixmap.rect(),windowText);
+    pen.end();
+}
+
+void KoDualColorButton::setColorDialogState(Selection state){
+    d->colorDialogState->selection = state;
+    d->tmpSelection = state;
+}
+
 KoColor KoDualColorButton::foregroundColor() const
 {
     return d->foregroundColor;
@@ -175,7 +171,6 @@ void KoDualColorButton::setBackgroundColor( const KoColor &color )
         KisSignalsBlocker b(d->colorSelectorDialog);
         d->colorSelectorDialog->slotColorUpdated(color);
     }
-
     update();
 }
 
@@ -194,9 +189,9 @@ void KoDualColorButton::setDisplayRenderer(const KoColorDisplayRendererInterface
     }
 }
 
-void KoDualColorButton::setColorSpace(const KoColorSpace *cs)
+void KoDualColorButton::updateColorSpace()
 {
-    d->colorSelectorDialog->lockUsedColorSpace(cs);
+    d->colorSelectorDialog->lockUsedColorSpace(d->displayRenderer->getPaintingColorSpace());
 }
 
 QColor KoDualColorButton::getColorFromDisplayRenderer(KoColor c)
@@ -216,25 +211,21 @@ void KoDualColorButton::setPopDialog( bool popDialog )
     d->popDialog = popDialog;
 }
 
-void KoDualColorButton::metrics( QRect &foregroundRect, QRect &backgroundRect )
-{
-    foregroundRect = QRect( 0, 0, width() - 14, height() - 14 );
-    backgroundRect = QRect( 14, 14, width() - 14, height() - 14 );
-}
-
 void KoDualColorButton::paintEvent(QPaintEvent *)
 {
-    QRect foregroundRect;
-    QRect backgroundRect;
 
     QPainter painter( this );
 
-    metrics( foregroundRect, backgroundRect );
-
     QBrush defBrush = palette().brush( QPalette::Button );
+
     QBrush foregroundBrush( getColorFromDisplayRenderer(d->foregroundColor), Qt::SolidPattern );
     QBrush backgroundBrush( getColorFromDisplayRenderer(d->backgroundColor), Qt::SolidPattern );
 
+    if (resetColours) {
+        foregroundBrush = Qt::black;
+        backgroundBrush = Qt::white;
+    }
+
     qDrawShadeRect( &painter, backgroundRect, palette(), false, 1, 0,
                     isEnabled() ? &backgroundBrush : &defBrush );
 
@@ -243,10 +234,15 @@ void KoDualColorButton::paintEvent(QPaintEvent *)
 
     painter.setPen( palette().color( QPalette::Shadow ) );
 
-    painter.drawPixmap( foregroundRect.right() + 2, 1, d->arrowBitmap );
-    painter.drawPixmap( 1, foregroundRect.bottom() + 2, d->resetPixmap );
+    paint_icons(painter);
 }
 
+void KoDualColorButton::paint_icons(QPainter &painter){
+    painter.drawPixmap( foregroundRect.right() + 2, 1, arrowBitmap );
+    painter.drawPixmap( 1, foregroundRect.bottom() + 2, resetPixmap );
+}
+
+
 void KoDualColorButton::dragEnterEvent( QDragEnterEvent *event )
 {
     event->setAccepted( isEnabled() && KColorMimeData::canDecode( event->mimeData() ) );
@@ -255,20 +251,6 @@ void KoDualColorButton::dragEnterEvent( QDragEnterEvent *event )
 void KoDualColorButton::dropEvent( QDropEvent *event )
 {
     Q_UNUSED(event);
-    /*  QColor color = KColorMimeData::fromMimeData( event->mimeData() );
-
-  if ( color.isValid() ) {
-    if ( d->selection == Foreground ) {
-      d->foregroundColor = color;
-      Q_EMIT foregroundColorChanged( color );
-    } else {
-      d->backgroundColor = color;
-      Q_EMIT backgroundColorChanged( color );
-    }
-
-    update();
-  }
-*/
 }
 
 void KoDualColorButton::slotSetForegroundColorFromDialog(const KoColor color)
@@ -316,12 +298,42 @@ void KoDualColorButton::openBackgroundDialog()
     update();
 }
 
-void KoDualColorButton::mousePressEvent( QMouseEvent *event )
+void KoDualColorButton::backgroundSelect(bool usePlatformDialog)
 {
-    QRect foregroundRect;
-    QRect backgroundRect;
+    if( d->popDialog) {
+        if (usePlatformDialog) {
+            QColor c = d->backgroundColor.toQColor();
+            c = QColorDialog::getColor(c, this);
+            if (c.isValid()) {
+                d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
+                Q_EMIT backgroundColorChanged(d->backgroundColor);
+            }
+        }
+        else {
+            openBackgroundDialog();
+        }
+    }
+}
 
-    metrics( foregroundRect, backgroundRect );
+void KoDualColorButton::foregroundSelect(bool usePlatformDialog)
+{
+    if( d->popDialog) {
+        if (usePlatformDialog) {
+            QColor c = d->foregroundColor.toQColor();
+            c = QColorDialog::getColor(c, this);
+            if (c.isValid()) {
+                d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
+                Q_EMIT foregroundColorChanged(d->foregroundColor);
+            }
+        }
+        else {
+            openForegroundDialog();
+        }
+    }
+}
+
+void KoDualColorButton::mousePressEvent( QMouseEvent *event )
+{
 
     d->dragPosition = event->pos();
 
@@ -336,31 +348,38 @@ void KoDualColorButton::mousePressEvent( QMouseEvent *event )
         d->miniCtlFlag = false;
     }
     else if ( event->pos().x() > foregroundRect.width() ) {
-        // We handle the swap and reset controls as soon as the mouse is
-        // is pressed and ignore further events on this click (mosfet).
-
-        KoColor tmp = d->foregroundColor;
-        d->foregroundColor = d->backgroundColor;
-        d->backgroundColor = tmp;
-
-        Q_EMIT backgroundColorChanged( d->backgroundColor );
-        Q_EMIT foregroundColorChanged( d->foregroundColor );
+        swapColours();
 
         d->miniCtlFlag = true;
     }
     else if ( event->pos().x() < backgroundRect.x() ) {
-        d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black);
-        d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white);
-
-        Q_EMIT backgroundColorChanged( d->backgroundColor );
-        Q_EMIT foregroundColorChanged( d->foregroundColor );
-
+        ResetColours();
+        
         d->miniCtlFlag = true;
     }
     update();
 }
 
 
+void KoDualColorButton::ResetColours()
+{
+    d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::black);
+    d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(Qt::white);
+
+    Q_EMIT backgroundColorChanged( d->backgroundColor );
+    Q_EMIT foregroundColorChanged( d->foregroundColor );
+}
+
+void KoDualColorButton::swapColours()
+{
+    KoColor tmp = d->foregroundColor;
+    d->foregroundColor = d->backgroundColor;
+    d->backgroundColor = tmp;
+
+    Q_EMIT backgroundColorChanged( d->backgroundColor );
+    Q_EMIT foregroundColorChanged( d->foregroundColor );
+}
+
 void KoDualColorButton::mouseMoveEvent( QMouseEvent *event )
 {
     if ( !d->miniCtlFlag ) {
@@ -386,28 +405,13 @@ void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event )
 
     d->miniCtlFlag = false;
 
-    QRect foregroundRect;
-    QRect backgroundRect;
-    metrics( foregroundRect, backgroundRect );
 
     KConfigGroup cfg =  KSharedConfig::openConfig()->group("colorselector");
     bool usePlatformDialog = cfg.readEntry("UsePlatformColorDialog", false);
 
     if (foregroundRect.contains( event->pos())) {
         if (d->tmpSelection == Foreground) {
-            if (d->popDialog) {
-                if (usePlatformDialog) {
-                    QColor c = d->foregroundColor.toQColor();
-                    c = QColorDialog::getColor(c, this);
-                    if (c.isValid()) {
-                        d->foregroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
-                        Q_EMIT foregroundColorChanged(d->foregroundColor);
-                    }
-                }
-                else {
-                    openForegroundDialog();
-                }
-            }
+            foregroundSelect(usePlatformDialog);
         }
         else {
             d->foregroundColor = d->backgroundColor;
@@ -416,19 +420,7 @@ void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event )
     }
     else if (backgroundRect.contains( event->pos())) {
         if(d->tmpSelection == Background ) {
-            if( d->popDialog) {
-                if (usePlatformDialog) {
-                    QColor c = d->backgroundColor.toQColor();
-                    c = QColorDialog::getColor(c, this);
-                    if (c.isValid()) {
-                        d->backgroundColor = d->displayRenderer->approximateFromRenderedQColor(c);
-                        Q_EMIT backgroundColorChanged(d->backgroundColor);
-                    }
-                }
-                else {
-                    openBackgroundDialog();
-                }
-            }
+            backgroundSelect(usePlatformDialog);
         } else {
             d->backgroundColor = d->foregroundColor;
             Q_EMIT backgroundColorChanged( d->backgroundColor );
@@ -438,6 +430,9 @@ void KoDualColorButton::mouseReleaseEvent( QMouseEvent *event )
     update();
 }
 
+
+
+
 void KoDualColorButton::changeEvent(QEvent *event)
 {
     QWidget::changeEvent(event);
@@ -445,7 +440,7 @@ void KoDualColorButton::changeEvent(QEvent *event)
     switch (event->type()) {
     case QEvent::StyleChange:
     case QEvent::PaletteChange:
-        d->updateArrows();
+    updateArrows();
     default:
         break;
     }
@@ -454,9 +449,6 @@ void KoDualColorButton::changeEvent(QEvent *event)
 bool KoDualColorButton::event(QEvent *event)
 {
     if (event->type() == QEvent::ToolTip) {
-        QRect foregroundRect;
-        QRect backgroundRect;
-        metrics( foregroundRect, backgroundRect );
 
         const QHelpEvent *helpEvent = static_cast<QHelpEvent*>(event);
 
@@ -480,3 +472,4 @@ bool KoDualColorButton::event(QEvent *event)
     return QWidget::event(event);
 
 }
+
diff --git a/libs/ui/widgets/KoDualColorButton.h b/libs/ui/widgets/KoDualColorButton.h
index d4fdbca08dd..6eb5a2b5cdf 100644
--- a/libs/ui/widgets/KoDualColorButton.h
+++ b/libs/ui/widgets/KoDualColorButton.h
@@ -2,6 +2,7 @@
 
    SPDX-FileCopyrightText: 1999 Daniel M. Duley <[email protected]>
    SPDX-FileCopyrightText: 2006 Tobias Koenig <[email protected]>
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
 
    SPDX-License-Identifier: LGPL-2.0-only
 */
@@ -11,10 +12,13 @@
 
 #include <kritaui_export.h>
 #include <KoColorDisplayRendererInterface.h>
+
+
 #include <QWidget>
 
 class KoColor;
 class KoColorSpace;
+class KisCanvasResourceProvider;
 /**
  * @short A widget for selecting two related colors.
  *
@@ -48,6 +52,13 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
       Foreground,
       Background
     };
+    QRect foregroundRect = QRect( 0, 0, 14, 14);
+    QRect backgroundRect = QRect( 14, 14, 28, 28);
+    QPixmap resetArrowPixmap;
+    QPixmap resetPixmap;
+    QPixmap arrowBitmap;
+
+    bool resetColours = false;
 
     /**
      * Constructs a new KoDualColorButton with the supplied foreground and
@@ -56,12 +67,10 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
      * @param parent The parent widget of the KoDualColorButton.
      * @param dialogParent The parent widget of the color selection dialog.
      */
-    KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor,
-                      QWidget *parent = 0, QWidget* dialogParent = 0 );
 
-    KoDualColorButton(const KoColor &foregroundColor, const KoColor &backgroundColor,
+    KoDualColorButton(KisCanvasResourceProvider *canvasResourceProvider,
                       const KoColorDisplayRendererInterface *displayRenderer,
-                      QWidget *parent = 0, QWidget* dialogParent = 0 );
+                      QWidget *parent = 0, QWidget* dialogParent = 0);
 
     /**
      * Destroys the KoDualColorButton.
@@ -73,6 +82,9 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
      */
     KoColor foregroundColor() const;
 
+
+
+    
     /**
      * Returns the current background color.
      */
@@ -92,6 +104,16 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
     QSize sizeHint() const override;
 
   public Q_SLOTS:
+    void updateArrows();
+    
+    void ResetColours();
+    void swapColours();
+
+    void setColorDialogState(Selection state);
+
+
+    virtual void paint_icons(QPainter &painter);
+    
     /**
      * Sets the foreground color.
      */
@@ -101,6 +123,9 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
      * Sets the background color.
      */
     void setBackgroundColor( const KoColor &color );
+    
+    void foregroundSelect(bool usePlatformDialog);
+    void backgroundSelect(bool usePlatformDialog);
 
     void slotSetForegroundColorFromDialog (const KoColor color);
     void slotSetBackgroundColorFromDialog (const KoColor color);
@@ -113,7 +138,7 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
      * set ColorSpace so we can lock the selector. Right now this'll be changed per view-change.
      * @param cs
      */
-    void setColorSpace(const KoColorSpace *cs);
+    void updateColorSpace();
 
     /**
      * @brief getColorFromDisplayRenderer
@@ -153,12 +178,11 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
      * be at the top right, the reset control will always be at the bottom
      * left, and you must leave at least a 14x14 space in those corners.
      */
-    virtual void metrics( QRect &foregroundRect, QRect &backgroundRect );
 
     void paintEvent( QPaintEvent *event ) override;
-    void mousePressEvent( QMouseEvent *event ) override;
-    void mouseMoveEvent( QMouseEvent *event ) override;
-    void mouseReleaseEvent( QMouseEvent *event ) override;
+    virtual void mousePressEvent( QMouseEvent *event ) override;
+    virtual void mouseMoveEvent( QMouseEvent *event ) override;
+    virtual void mouseReleaseEvent( QMouseEvent *event ) override;
     void dragEnterEvent( QDragEnterEvent *event ) override;
     void dropEvent( QDropEvent *event ) override;
     void changeEvent(QEvent *event) override;
@@ -167,6 +191,8 @@ class KRITAUI_EXPORT KoDualColorButton : public QWidget
   private:
     class Private;
     Private *const d;
+
+
 };
 
 #endif
diff --git a/libs/ui/widgets/KoForegroundColour.cpp b/libs/ui/widgets/KoForegroundColour.cpp
new file mode 100644
index 00000000000..858cb9fc4a4
--- /dev/null
+++ b/libs/ui/widgets/KoForegroundColour.cpp
@@ -0,0 +1,53 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 1999 Daniel M. Duley <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#include "KoForegroundColour.h"
+#include <QPainter>
+#include <QColorDialog>
+#include <QEvent>
+#include <kconfiggroup.h>
+#include <ksharedconfig.h>
+
+KoForegroundColour::KoForegroundColour(KisCanvasResourceProvider *canvasResourceProvider,
+                                     const KoColorDisplayRendererInterface *displayRenderer,
+                                     QWidget *parent, QWidget *dialogParent)
+    : KoDualColorButton(canvasResourceProvider, displayRenderer, parent, dialogParent)
+{
+    foregroundRect = QRect( 0, 0, 22, 22);
+    backgroundRect = QRect( 16, 16, 12, 12);
+    setColorDialogState(Foreground);
+}
+
+
+void KoForegroundColour::paint_icons(QPainter &painter)
+{
+    Q_UNUSED(painter);
+}
+
+void KoForegroundColour::mousePressEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
+
+void KoForegroundColour::mouseReleaseEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+    
+    KConfigGroup cfg =  KSharedConfig::openConfig()->group("colorselector");
+    bool usePlatformDialog = cfg.readEntry("UsePlatformColorDialog", false);
+    
+    foregroundSelect(usePlatformDialog);
+
+    update();
+}
+
+bool KoForegroundColour::event(QEvent *event)
+{
+    if (event->type() == QEvent::ToolTip) {
+        this->setToolTip(i18n("Foreground color selector"));
+    }
+    return QWidget::event(event);
+}
diff --git a/libs/ui/widgets/KoForegroundColour.h b/libs/ui/widgets/KoForegroundColour.h
new file mode 100644
index 00000000000..9b58ed52b29
--- /dev/null
+++ b/libs/ui/widgets/KoForegroundColour.h
@@ -0,0 +1,28 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#ifndef KOFOREGROUNDCOLOUR_H
+#define KOFOREGROUNDCOLOUR_H
+
+
+#include <KoDualColorButton.h>
+
+
+class KisCanvas2;
+
+class KRITAUI_EXPORT KoForegroundColour : public KoDualColorButton {
+    Q_OBJECT
+public:
+    KoForegroundColour(KisCanvasResourceProvider *canvasResourceProvider,
+                      const KoColorDisplayRendererInterface *displayRenderer = 0,
+                      QWidget *parent = 0, QWidget *dialogParent = 0);
+    void paint_icons(QPainter &painter) override;
+    void mouseReleaseEvent( QMouseEvent *event ) override;
+    void mousePressEvent( QMouseEvent *event ) override;
+    bool event(QEvent *event) override;
+};
+
+#endif
\ No newline at end of file
diff --git a/libs/ui/widgets/KoResetBgFgColours.cpp b/libs/ui/widgets/KoResetBgFgColours.cpp
new file mode 100644
index 00000000000..f3b7b3a4945
--- /dev/null
+++ b/libs/ui/widgets/KoResetBgFgColours.cpp
@@ -0,0 +1,51 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#include "KoResetBgFgColours.h"
+#include <QPainter>
+#include <QEvent>
+
+
+
+KoResetBgFgColours::KoResetBgFgColours(KisCanvasResourceProvider *canvasResourceProvider,
+                                     const KoColorDisplayRendererInterface *displayRenderer,
+                                     QWidget *parent, QWidget *dialogParent)
+    : KoDualColorButton(canvasResourceProvider, displayRenderer, parent, dialogParent)
+{
+    foregroundRect = QRect( 0, 7, 14, 14);
+    backgroundRect = QRect( 7, 14, 14, 14);
+    resetColours = true;
+}
+
+
+void KoResetBgFgColours::paint_icons(QPainter &painter)
+{
+    painter.drawPixmap(16, 0, resetArrowPixmap);
+}
+
+void KoResetBgFgColours::mousePressEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+    ResetColours();
+}
+
+void KoResetBgFgColours::mouseReleaseEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
+
+bool KoResetBgFgColours::event(QEvent *event)
+{
+    if (event->type() == QEvent::ToolTip) {
+        this->setToolTip(i18n("Set foreground and background colors to black and white"));
+    }
+    return QWidget::event(event);
+}
+
+void KoResetBgFgColours::mouseMoveEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
diff --git a/libs/ui/widgets/KoResetBgFgColours.h b/libs/ui/widgets/KoResetBgFgColours.h
new file mode 100644
index 00000000000..b87525bcd80
--- /dev/null
+++ b/libs/ui/widgets/KoResetBgFgColours.h
@@ -0,0 +1,31 @@
+/* This file is part of the KDE libraries
+
+   SPDX-FileCopyrightText: 1999 Daniel M. Duley <[email protected]>
+   SPDX-FileCopyrightText: 2006 Tobias Koenig <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#ifndef KORESETBGFGCOLOURS_H
+#define KORESETBGFGCOLOURS_H
+
+
+#include <KoDualColorButton.h>
+
+#include <kis_canvas2.h>
+class KisCanvas2;
+
+class KRITAUI_EXPORT KoResetBgFgColours : public KoDualColorButton {
+    Q_OBJECT
+public:
+    KoResetBgFgColours(KisCanvasResourceProvider *canvasResourceProvider,
+                      const KoColorDisplayRendererInterface *displayRenderer = 0,
+                      QWidget *parent = 0, QWidget *dialogParent = 0);
+    void paint_icons(QPainter &painter) override;
+    void mouseReleaseEvent( QMouseEvent *event ) override;
+    void mousePressEvent( QMouseEvent *event ) override;
+    bool event(QEvent *event) override;
+    void mouseMoveEvent( QMouseEvent *event ) override;
+};
+
+#endif
\ No newline at end of file
diff --git a/libs/ui/widgets/KoSwapBgFgColours.cpp b/libs/ui/widgets/KoSwapBgFgColours.cpp
new file mode 100644
index 00000000000..882b4e30391
--- /dev/null
+++ b/libs/ui/widgets/KoSwapBgFgColours.cpp
@@ -0,0 +1,50 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#include "KoSwapBgFgColours.h"
+#include <QPainter>
+#include <QEvent>
+
+
+
+KoSwapBgFgColours::KoSwapBgFgColours(KisCanvasResourceProvider *canvasResourceProvider,
+                                     const KoColorDisplayRendererInterface *displayRenderer,
+                                     QWidget *parent, QWidget *dialogParent)
+    : KoDualColorButton(canvasResourceProvider, displayRenderer, parent, dialogParent)
+{
+    foregroundRect = QRect( 0, 7, 14, 14);
+    backgroundRect = QRect( 7, 14, 14, 14);
+}
+
+
+void KoSwapBgFgColours::paint_icons(QPainter &painter)
+{
+    painter.drawPixmap( 15, 1, arrowBitmap );
+}
+
+void KoSwapBgFgColours::mousePressEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+    swapColours();
+}
+
+void KoSwapBgFgColours::mouseReleaseEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
+
+bool KoSwapBgFgColours::event(QEvent *event)
+{
+    if (event->type() == QEvent::ToolTip) {
+        this->setToolTip(i18n("Swap foreground and background colors"));
+    }
+    return QWidget::event(event);
+}
+
+void KoSwapBgFgColours::mouseMoveEvent( QMouseEvent *event )
+{
+    Q_UNUSED(event);
+}
\ No newline at end of file
diff --git a/libs/ui/widgets/KoSwapBgFgColours.h b/libs/ui/widgets/KoSwapBgFgColours.h
new file mode 100644
index 00000000000..f791875f474
--- /dev/null
+++ b/libs/ui/widgets/KoSwapBgFgColours.h
@@ -0,0 +1,29 @@
+/* This file is part of the KDE libraries
+   SPDX-FileCopyrightText: 2026 Arkady Flury <[email protected]>
+
+   SPDX-License-Identifier: LGPL-2.0-only
+*/
+
+#ifndef KOSWAPBGFGCOLOURS_H
+#define KOSWAPBGFGCOLOURS_H
+
+
+#include <KoDualColorButton.h>
+
+
+class KisCanvas2;
+
+class KRITAUI_EXPORT KoSwapBgFgColours : public KoDualColorButton {
+    Q_OBJECT
+public:
+    KoSwapBgFgColours(KisCanvasResourceProvider *canvasResourceProvider,
+                      const KoColorDisplayRendererInterface *displayRenderer = 0,
+                      QWidget *parent = 0, QWidget *dialogParent = 0);
+    void paint_icons(QPainter &painter) override;
+    void mouseReleaseEvent( QMouseEvent *event ) override;
+    void mousePressEvent( QMouseEvent *event ) override;
+    bool event(QEvent *event) override;
+    void mouseMoveEvent( QMouseEvent *event ) override;
+};
+
+#endif
\ No newline at end of file
diff --git a/libs/widgets/dcolorarrow.xbm b/libs/widgets/dcolorarrow.xbm
deleted file mode 100644
index 24cabac692c..00000000000
--- a/libs/widgets/dcolorarrow.xbm
+++ /dev/null
@@ -1,6 +0,0 @@
-#define dcolorarrow_width 12
-#define dcolorarrow_height 12
-static const unsigned char dcolorarrow_bits[] = {
-  0x08, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x0e, 0x01, 0x0c, 0x01,
-  0x08, 0x01, 0x00, 0x01, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03, 0x00, 0x01,
-  };
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.