Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions daemon/Main.vala
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@

public class Gala.Daemon.Application : Gtk.Application {
private IBusService ibus_service;
private OSKManager osk_manager;

public Application () {
Object (application_id: "org.pantheon.gala.daemon");
}

construct {
ibus_service = new IBusService ();
osk_manager = new OSKManager (ibus_service);
}

public override void startup () {
Expand Down
31 changes: 31 additions & 0 deletions daemon/OSK/InputManager.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2026 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class Gala.Daemon.InputManager : Object {
public OSKService service { private get; construct; }

public InputManager (OSKService service) {
Object (service: service);
}

public void send_keyval (uint keyval) {
service.keyval_pressed (keyval);
service.keyval_released (keyval);
}

public void press_keyval (uint keyval) {
service.keyval_pressed (keyval);
}

public void release_keyval (uint keyval) {
service.keyval_released (keyval);
}

public void request_hide () {
service.hide_requested ();
}
}
55 changes: 55 additions & 0 deletions daemon/OSK/KeyboardModel/Key.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2026 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class Gala.Daemon.Key : Object {
public const string ACTION_GROUP_PREFIX = "keyboard";
public const string ACTION_PREFIX = ACTION_GROUP_PREFIX + ".";
/* Types the keyval given as the action target in a single combination of pressed + released */
public const string ACTION_TYPE_KEY_VAL = "keyval";
/* Sends a keyval pressed event */
public const string ACTION_PRESS_KEY_VAL = "keyval-press";
/* Sends a keyval released event */
public const string ACTION_RELEASE_KEY_VAL = "keyval-release";
/* Latches the keyboard view with the name given as the action target */
public const string ACTION_LATCH_VIEW = "latch-view";
/* Sets the keyboard view with the name given as the action target */
public const string ACTION_SET_VIEW = "set-view";
/* Hides the keyboard */
public const string ACTION_HIDE = "hide";

public double left_offset { get; construct; default = 0.0; }
public double width { get; construct; default = 1.0; }
public double height { get; construct; default = 1.0; }

/**
* Action triggered on release.
*/
public string detailed_action_name { get; construct; }

/**
* Additional optional action triggered on press.
*/
public string? press_detailed_action_name { get; construct; }

public ListModel popup_keys { get; construct; }

public string? label { get; construct; }
public Icon? icon { get; construct; }

public Key (double left_offset, double width, double height, string detailed_action_name, string? press_detailed_action_name, ListModel popup_keys, string? label, Icon? icon) {
Object (
left_offset: left_offset,
width: width,
height: height,
detailed_action_name: detailed_action_name,
press_detailed_action_name: press_detailed_action_name,
popup_keys: popup_keys,
label: label,
icon: icon
);
}
}
36 changes: 36 additions & 0 deletions daemon/OSK/KeyboardModel/KeyboardModel.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2026 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class Gala.Daemon.KeyboardModel : Object {
public ListModel views { get; construct; }

public KeyboardModel (ListModel views) {
Object (views: views);
}

public KeyboardView? get_view_by_name (string name) {
for (uint i = 0; i < views.get_n_items (); i++) {
var view = (KeyboardView) views.get_item (i);
if (view.name == name) {
return view;
}
}

return null;
}

public KeyboardView? find_default_view () {
for (uint i = 0; i < views.get_n_items (); i++) {
var view = (KeyboardView) views.get_item (i);
if (view.is_default) {
return view;
}
}

return (KeyboardView?) views.get_item (0);
}
}
151 changes: 151 additions & 0 deletions daemon/OSK/KeyboardModel/KeyboardModelBuilder.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/*
* Copyright 2026 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class Gala.Daemon.KeyboardModelBuilder : Object {
private KeyboardModel model;
private ListStore views_store;

private string? current_view_name;
private ListStore? current_view_store;
private bool current_view_is_default = false;

private ListStore? current_row;

private double current_key_left_offset = 0.0;
private double current_key_width = 1.0;
private double current_key_height = 1.0;
private string? current_key_detailed_action_name; // Mandatory to set
private string? current_key_press_detailed_action_name; // Additional action to trigger on press
private ListStore? current_key_popup_keys;
private string? current_key_label;
private Icon? current_key_icon;

construct {
views_store = new ListStore (typeof (KeyboardView));
model = new KeyboardModel (views_store);
}

public KeyboardModel end () {
return model;
}

public void begin_view (string name) requires (current_view_name == null && current_view_store == null) {
current_view_name = name;
current_view_store = new ListStore (typeof (ListStore));
}

public void set_view_default () requires (current_view_name != null && current_view_store != null) {
current_view_is_default = true;
}

public void end_view () requires (current_view_name != null && current_view_store != null) {
var view = new KeyboardView (current_view_name, current_view_store, current_view_is_default);
views_store.append (view);


current_view_name = null;
current_view_store = null;
current_view_is_default = false;
}

public void begin_row () requires (current_view_store != null && current_row == null) {
current_row = new ListStore (typeof (Key));
}

public void end_row () requires (current_view_store != null && current_row != null) {
current_view_store.append (current_row);
current_row = null;
}

public void begin_key () requires (current_row != null && current_key_detailed_action_name == null) {
current_key_popup_keys = new ListStore (typeof (Key));
}

public void set_key_left_offset (double left_offset) {
current_key_left_offset = left_offset;
}

public void set_key_width (double width) {
current_key_width = width;
}

public void set_key_height (double height) {
current_key_height = height;
}

public void set_key_val_action (uint val) {
current_key_press_detailed_action_name = Action.print_detailed_name (Key.ACTION_PREFIX + Key.ACTION_PRESS_KEY_VAL, new Variant.uint32 (val));
current_key_detailed_action_name = Action.print_detailed_name (Key.ACTION_PREFIX + Key.ACTION_RELEASE_KEY_VAL, new Variant.uint32 (val));
}

public void set_erase_action () {
set_key_val_action (Gdk.Key.BackSpace);
}

public void set_latch_view_action (string view_name) {
current_key_detailed_action_name = Action.print_detailed_name (Key.ACTION_PREFIX + Key.ACTION_LATCH_VIEW, new Variant.string (view_name));
}

public void set_set_view_action (string view_name) {
current_key_detailed_action_name = Action.print_detailed_name (Key.ACTION_PREFIX + Key.ACTION_SET_VIEW, new Variant.string (view_name));
}

public void set_hide_action () {
current_key_detailed_action_name = Action.print_detailed_name (Key.ACTION_PREFIX + Key.ACTION_HIDE, null);
}

public void set_key_label (string label) {
current_key_label = label;
}

public void set_key_icon (Icon icon) {
current_key_icon = icon;
}

public void set_key_icon_name (string icon_name) {
current_key_icon = new ThemedIcon (icon_name);
}

public void add_popup_key (string popup_key_string) requires (current_key_popup_keys != null) {
// var popup_key = new Key (
// 1.0f,
// 1.0f,
// ACTION_PREFIX + "popup." + popup_key_string,
// null,
// popup_key_string,
// null
// );
// current_key_popup_keys.append (popup_key);
}

public void end_key () requires (current_row != null) {
if (current_key_label != null && current_key_icon != null) {
critical ("A key should have at least an icon or label.");
}

var key = new Key (
current_key_left_offset,
current_key_width,
current_key_height,
current_key_detailed_action_name ?? "none",
current_key_press_detailed_action_name,
current_key_popup_keys,
current_key_label,
current_key_icon
);
current_row.append (key);

current_key_left_offset = 0.0;
current_key_width = 1.0;
current_key_height = 1.0;
current_key_detailed_action_name = null;
current_key_press_detailed_action_name = null;
current_key_popup_keys = null;
current_key_label = null;
current_key_icon = null;
}
}
16 changes: 16 additions & 0 deletions daemon/OSK/KeyboardModel/KeyboardView.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright 2026 elementary, Inc. (https://elementary.io)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Authored by: Leonhard Kargl <leo.kargl@proton.me>
*/

public class Gala.Daemon.KeyboardView : Object {
public string name { get; construct; }
public ListModel rows { get; construct; }
public bool is_default { get; construct; }

public KeyboardView (string name, ListModel rows, bool is_default = false) {
Object (name: name, rows: rows, is_default: is_default);
}
}
Loading
Loading