import "root:/" import "root:/services" import "root:/modules/common" import "root:/modules/common/widgets" import "root:/modules/common/functions/color_utils.js" as ColorUtils import QtQuick import QtQuick.Controls import QtQuick.Effects import QtQuick.Layouts import Quickshell.Io import Quickshell import Quickshell.Widgets import Quickshell.Wayland import Quickshell.Hyprland Scope { // Scope id: root property bool pinned: ConfigOptions?.osk.pinnedOnStartup ?? false component OskControlButton: GroupButton { // Pin button baseWidth: 40 baseHeight: 40 clickedWidth: baseWidth clickedHeight: baseHeight + 20 buttonRadius: Appearance.rounding.normal } Loader { id: oskLoader active: false onActiveChanged: { if (!oskLoader.active) { Ydotool.releaseAllKeys(); } } sourceComponent: PanelWindow { // Window id: oskRoot visible: oskLoader.active anchors { bottom: true left: true right: true } function hide() { oskLoader.active = false } exclusiveZone: root.pinned ? implicitHeight - Appearance.sizes.hyprlandGapsOut : 0 implicitWidth: oskBackground.width + Appearance.sizes.elevationMargin * 2 implicitHeight: oskBackground.height + Appearance.sizes.elevationMargin * 2 WlrLayershell.namespace: "quickshell:osk" WlrLayershell.layer: WlrLayer.Overlay // Hyprland 0.49: Focus is always exclusive and setting this breaks mouse focus grab // WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive color: "transparent" mask: Region { item: oskBackground } // Background StyledRectangularShadow { target: oskBackground } Rectangle { id: oskBackground anchors.centerIn: parent color: Appearance.colors.colLayer0 radius: Appearance.rounding.windowRounding property real padding: 10 implicitWidth: oskRowLayout.implicitWidth + padding * 2 implicitHeight: oskRowLayout.implicitHeight + padding * 2 Keys.onPressed: (event) => { // Esc to close if (event.key === Qt.Key_Escape) { oskRoot.hide() } } RowLayout { id: oskRowLayout anchors.centerIn: parent spacing: 5 VerticalButtonGroup { OskControlButton { // Pin button toggled: root.pinned onClicked: root.pinned = !root.pinned contentItem: MaterialSymbol { text: "keep" horizontalAlignment: Text.AlignHCenter iconSize: Appearance.font.pixelSize.larger color: root.pinned ? Appearance.m3colors.m3onPrimary : Appearance.colors.colOnLayer0 } } OskControlButton { onClicked: () => { oskRoot.hide() } contentItem: MaterialSymbol { horizontalAlignment: Text.AlignHCenter text: "keyboard_hide" iconSize: Appearance.font.pixelSize.larger } } } Rectangle { Layout.topMargin: 20 Layout.bottomMargin: 20 Layout.fillHeight: true implicitWidth: 1 color: Appearance.colors.colOutlineVariant } OskContent { id: oskContent Layout.fillWidth: true } } } } } IpcHandler { target: "osk" function toggle(): void { oskLoader.active = !oskLoader.active } function close(): void { oskLoader.active = false } function open(): void { oskLoader.active = true } } GlobalShortcut { name: "oskToggle" description: Translation.tr("Toggles on screen keyboard on press") onPressed: { oskLoader.active = !oskLoader.active; } } GlobalShortcut { name: "oskOpen" description: Translation.tr("Opens on screen keyboard on press") onPressed: { oskLoader.active = true; } } GlobalShortcut { name: "oskClose" description: Translation.tr("Closes on screen keyboard on press") onPressed: { oskLoader.active = false; } } }