Floating polish: visibility, resize, saved geometry, D-Bus, desktop entry

- VisibilityController: show on field focus, dismiss until next focus,
  manual show/hide/toggle overrides
- FloatingWindow: resize from the corner grip, clamp to screen
- WindowSettings: geometry per screen, debounced saves
- DBusControl: org.sloposk.Keyboard Show/Hide/Toggle for global shortcuts
- org.sloposk.keyboard.desktop so System Settings lists it as a virtual keyboard
- README with build/run/layout docs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 15:02:25 +02:00
co-authored by Claude Opus 5.5
parent 92c132c66f
commit c6c977eb4c
19 changed files with 489 additions and 40 deletions
+22
View File
@@ -0,0 +1,22 @@
#include "DBusControl.h"
#include "window/VisibilityController.h"
#include <QDBusConnection>
DBusControl::DBusControl(VisibilityController &visibility, QObject *parent)
: QObject(parent)
, m_visibility(visibility)
{
}
bool DBusControl::registerOnSessionBus()
{
QDBusConnection bus = QDBusConnection::sessionBus();
return bus.registerService(QStringLiteral("org.sloposk.Keyboard"))
&& bus.registerObject(QStringLiteral("/Keyboard"), this, QDBusConnection::ExportScriptableSlots);
}
void DBusControl::Show() { m_visibility.show(); }
void DBusControl::Hide() { m_visibility.hide(); }
void DBusControl::Toggle() { m_visibility.toggle(); }
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#include <QObject>
class VisibilityController;
// Session-bus remote control, e.g. for a global shortcut:
// qdbus org.sloposk.Keyboard /Keyboard org.sloposk.Keyboard.Toggle
class DBusControl : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.sloposk.Keyboard")
public:
explicit DBusControl(VisibilityController &visibility, QObject *parent = nullptr);
// False if the bus is unavailable or another instance owns the name.
bool registerOnSessionBus();
public Q_SLOTS:
Q_SCRIPTABLE void Show();
Q_SCRIPTABLE void Hide();
Q_SCRIPTABLE void Toggle();
private:
VisibilityController &m_visibility;
};
+38
View File
@@ -0,0 +1,38 @@
#include "DevHooks.h"
#include "backend/TextBackend.h"
#include <QCoreApplication>
#include <QQuickWindow>
#include <QTimer>
namespace {
void installAutotype(TextBackend &backend, const QString &text)
{
QObject::connect(&backend, &TextBackend::activeChanged, &backend, [&backend, text] {
if (backend.isActive())
backend.commitText(text);
});
}
void installScreenshot(QQuickWindow &window, const QString &path)
{
constexpr int SettleMs = 500;
QTimer::singleShot(SettleMs, &window, [&window, path] {
const bool saved = window.grabWindow().save(path);
if (!saved)
qWarning("Failed to save screenshot to %s", qPrintable(path));
QCoreApplication::exit(saved ? 0 : 1);
});
}
} // namespace
void installDevHooks(TextBackend &backend, QQuickWindow &window)
{
if (const QString text = qEnvironmentVariable("SLOPOSK_AUTOTYPE"); !text.isEmpty())
installAutotype(backend, text);
if (const QString path = qEnvironmentVariable("SLOPOSK_SCREENSHOT"); !path.isEmpty())
installScreenshot(window, path);
}
+9
View File
@@ -0,0 +1,9 @@
#pragma once
class QQuickWindow;
class TextBackend;
// Environment-driven helpers for headless testing; no effect when unset.
// SLOPOSK_AUTOTYPE=text commit `text` whenever a text field gets focus
// SLOPOSK_SCREENSHOT=path save the keyboard window to `path`, then quit
void installDevHooks(TextBackend &backend, QQuickWindow &window);