See-through keyboard background with optional blur
- Opacity slider for the panel behind the keys (10–100%); keys stay opaque - Blur Behind: asks the compositor (KWin) to blur under the rounded panel via KF6 WindowSystem; skipped at full opacity - Settings panel draws over the window background so changes show live, and scrolls when it doesn't fit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,7 @@ set(SLOPOSK_QML_FILES
|
||||
SettingsButton.qml
|
||||
SettingsPanel.qml
|
||||
ToggleRow.qml
|
||||
SliderRow.qml
|
||||
Theme.qml
|
||||
)
|
||||
list(TRANSFORM SLOPOSK_QML_FILES PREPEND ${PROJECT_SOURCE_DIR}/qml/ OUTPUT_VARIABLE sloposk_qml_paths)
|
||||
@@ -98,6 +99,7 @@ target_link_libraries(sloposk PRIVATE
|
||||
Qt6::DBus
|
||||
Qt6::WaylandClient
|
||||
LayerShellQt::Interface
|
||||
KF6::WindowSystem
|
||||
PkgConfig::WAYLAND
|
||||
)
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ constexpr auto HoldKeysKey = "typing/holdKeys";
|
||||
constexpr auto VisibleSectionsKey = "layout/visibleSections";
|
||||
constexpr auto FullKeyboardKey = "layout/fullKeyboard";
|
||||
constexpr auto AlwaysVisibleKey = "window/alwaysVisible";
|
||||
constexpr auto BackgroundOpacityKey = "appearance/backgroundOpacity";
|
||||
constexpr auto BlurBackgroundKey = "appearance/blurBackground";
|
||||
}
|
||||
|
||||
Settings::Settings(QObject *parent)
|
||||
@@ -26,6 +28,27 @@ Settings::Settings(QObject *parent)
|
||||
m_visibleSections = {MainSectionId};
|
||||
m_fullKeyboard = store.value(FullKeyboardKey, false).toBool();
|
||||
m_alwaysVisible = store.value(AlwaysVisibleKey, false).toBool();
|
||||
m_backgroundOpacity = qBound(MinBackgroundOpacity, store.value(BackgroundOpacityKey, 1.0).toReal(), 1.0);
|
||||
m_blurBackground = store.value(BlurBackgroundKey, true).toBool();
|
||||
}
|
||||
|
||||
void Settings::setBackgroundOpacity(qreal opacity)
|
||||
{
|
||||
opacity = qBound(MinBackgroundOpacity, opacity, 1.0);
|
||||
if (qFuzzyCompare(opacity, m_backgroundOpacity))
|
||||
return;
|
||||
m_backgroundOpacity = opacity;
|
||||
QSettings().setValue(BackgroundOpacityKey, opacity);
|
||||
Q_EMIT appearanceChanged();
|
||||
}
|
||||
|
||||
void Settings::setBlurBackground(bool blur)
|
||||
{
|
||||
if (blur == m_blurBackground)
|
||||
return;
|
||||
m_blurBackground = blur;
|
||||
QSettings().setValue(BlurBackgroundKey, blur);
|
||||
Q_EMIT appearanceChanged();
|
||||
}
|
||||
|
||||
void Settings::setAlwaysVisible(bool always)
|
||||
|
||||
@@ -22,6 +22,10 @@ class Settings : public QObject
|
||||
Q_PROPERTY(bool fullKeyboard READ fullKeyboard WRITE setFullKeyboard NOTIFY fullKeyboardChanged)
|
||||
// Shown even without a focused text field, to type into any window.
|
||||
Q_PROPERTY(bool alwaysVisible READ alwaysVisible WRITE setAlwaysVisible NOTIFY alwaysVisibleChanged)
|
||||
// Opacity of the panel behind the keys (MinBackgroundOpacity–1); keys stay opaque.
|
||||
Q_PROPERTY(qreal backgroundOpacity READ backgroundOpacity WRITE setBackgroundOpacity NOTIFY appearanceChanged)
|
||||
// Blurs what shows through a translucent background (needs compositor support, e.g. KWin).
|
||||
Q_PROPERTY(bool blurBackground READ blurBackground WRITE setBlurBackground NOTIFY appearanceChanged)
|
||||
|
||||
public:
|
||||
explicit Settings(QObject *parent = nullptr);
|
||||
@@ -44,11 +48,18 @@ public:
|
||||
bool alwaysVisible() const { return m_alwaysVisible; }
|
||||
void setAlwaysVisible(bool always);
|
||||
|
||||
static constexpr qreal MinBackgroundOpacity = 0.1;
|
||||
qreal backgroundOpacity() const { return m_backgroundOpacity; }
|
||||
void setBackgroundOpacity(qreal opacity);
|
||||
bool blurBackground() const { return m_blurBackground; }
|
||||
void setBlurBackground(bool blur);
|
||||
|
||||
Q_SIGNALS:
|
||||
void typingOptionsChanged();
|
||||
void visibleSectionsChanged();
|
||||
void fullKeyboardChanged();
|
||||
void alwaysVisibleChanged();
|
||||
void appearanceChanged();
|
||||
|
||||
private:
|
||||
void setTypingOptions(const TypingOptions &options);
|
||||
@@ -57,4 +68,6 @@ private:
|
||||
QStringList m_visibleSections;
|
||||
bool m_fullKeyboard = false;
|
||||
bool m_alwaysVisible = false;
|
||||
qreal m_backgroundOpacity = 1.0;
|
||||
bool m_blurBackground = true;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "FloatingWindow.h"
|
||||
|
||||
#include <KWindowEffects>
|
||||
#include <LayerShellQt/Window>
|
||||
#include <QPainterPath>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
#include <QWindow>
|
||||
@@ -81,6 +83,17 @@ void FloatingWindow::setInputRegion(const QRectF ®ion)
|
||||
m_window->setMask(QRegion(region.toAlignedRect()));
|
||||
}
|
||||
|
||||
void FloatingWindow::setBlurRegion(const QRectF ®ion, qreal radius)
|
||||
{
|
||||
if (region.isEmpty()) {
|
||||
KWindowEffects::enableBlurBehind(m_window, false);
|
||||
return;
|
||||
}
|
||||
QPainterPath path;
|
||||
path.addRoundedRect(region, radius, radius);
|
||||
KWindowEffects::enableBlurBehind(m_window, true, QRegion(path.toFillPolygon().toPolygon()));
|
||||
}
|
||||
|
||||
void FloatingWindow::show()
|
||||
{
|
||||
m_window->setVisible(true);
|
||||
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
Q_INVOKABLE void resizeBy(qreal dw, qreal dh);
|
||||
// Only this part of the window takes input; the rest passes through.
|
||||
Q_INVOKABLE void setInputRegion(const QRectF ®ion);
|
||||
// Asks the compositor to blur behind this rounded rect; an empty rect turns blur off.
|
||||
Q_INVOKABLE void setBlurRegion(const QRectF ®ion, qreal radius);
|
||||
Q_INVOKABLE void show();
|
||||
Q_INVOKABLE void hide();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user