Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
566e54a5aa
|
|||
| 885383670a | |||
| cdb97d388d | |||
| 8d7afd8e4e | |||
| 8207cb7051 | |||
| 610b30fa12 | |||
| 053faf2598 | |||
| 716fa62e8b | |||
| f786f8d452 | |||
| 30f324c73a | |||
| 6cda9eb617 |
6
debian/changelog
vendored
6
debian/changelog
vendored
@ -1,3 +1,9 @@
|
|||||||
|
squeekboard (1.44.0~alpha0) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
|
* treewide: Increase version to 1.44.0~alpha0
|
||||||
|
|
||||||
|
-- MoonlightWave-12 <135532-MoonlightWave-12@users.noreply.gitlab.gnome.org> Fri, 15 Nov 2024 15:37:09 +0100
|
||||||
|
|
||||||
squeekboard (1.43.0) experimental; urgency=medium
|
squeekboard (1.43.0) experimental; urgency=medium
|
||||||
|
|
||||||
[ MoonlightWave-12 ]
|
[ MoonlightWave-12 ]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
project(
|
project(
|
||||||
'squeekboard',
|
'squeekboard',
|
||||||
'c', 'rust',
|
'c', 'rust',
|
||||||
version: '1.43.0',
|
version: '1.44.0-alpha0',
|
||||||
license: 'GPLv3',
|
license: 'GPLv3',
|
||||||
meson_version: '>=1.0.0',
|
meson_version: '>=1.0.0',
|
||||||
default_options: [
|
default_options: [
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
ar
|
||||||
be
|
be
|
||||||
bg
|
bg
|
||||||
ca
|
ca
|
||||||
cs
|
cs
|
||||||
de
|
de
|
||||||
el
|
el
|
||||||
|
en_GB
|
||||||
es
|
es
|
||||||
eu
|
eu
|
||||||
fa
|
fa
|
||||||
@ -17,6 +19,7 @@ hr
|
|||||||
ht
|
ht
|
||||||
hu
|
hu
|
||||||
it
|
it
|
||||||
|
ja
|
||||||
ka
|
ka
|
||||||
ko
|
ko
|
||||||
nl
|
nl
|
||||||
@ -31,4 +34,5 @@ sr
|
|||||||
tr
|
tr
|
||||||
uk
|
uk
|
||||||
sv
|
sv
|
||||||
|
uz
|
||||||
zh_CN
|
zh_CN
|
||||||
|
|||||||
45
po/ar.po
Normal file
45
po/ar.po
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Arabic translation for squeekboard.
|
||||||
|
# Copyright (C) 2024 squeekboard's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the squeekboard package.
|
||||||
|
# Ahmed Mohammed <iramosu@protonmail.com>, 2024.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squeekboard main\n"
|
||||||
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
|
||||||
|
"issues\n"
|
||||||
|
"POT-Creation-Date: 2024-08-08 20:39+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-10-22 13:54+0300\n"
|
||||||
|
"Last-Translator: Ahmed Mohammed <iramosu@protonmail.com>\n"
|
||||||
|
"Language-Team: Arabic <Arabic>\n"
|
||||||
|
"Language: ar\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.4.3\n"
|
||||||
|
|
||||||
|
#. translators: This is a emmoji keyboard layout
|
||||||
|
#: data/popover.ui:6
|
||||||
|
msgid "Emoji"
|
||||||
|
msgstr "إيموجي"
|
||||||
|
|
||||||
|
#. translators: This is a terminal keyboard layout
|
||||||
|
#: data/popover.ui:12
|
||||||
|
msgid "Terminal"
|
||||||
|
msgstr "الطرفية"
|
||||||
|
|
||||||
|
#: data/popover.ui:18
|
||||||
|
msgid "Keyboard Settings"
|
||||||
|
msgstr "إعدادات لوحة المفاتيح"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:3
|
||||||
|
msgid "Squeekboard"
|
||||||
|
msgstr "سكويك بورد"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:4
|
||||||
|
msgid "On Screen Keyboard"
|
||||||
|
msgstr "لوحة مفاتيح على الشاشة"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:5
|
||||||
|
msgid "An on screen virtual keyboard"
|
||||||
|
msgstr "لوحة مفاتيح افتراضية على الشاشة"
|
||||||
45
po/en_GB.po
Normal file
45
po/en_GB.po
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# British English translation for squeekboard.
|
||||||
|
# Copyright (C) 2024 squeekboard's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the squeekboard package.
|
||||||
|
# Andi Chandler <andi@gowling.com>, 2024.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squeekboard master\n"
|
||||||
|
"Report-Msgid-Bugs-To: https://source.puri.sm/Librem5/squeekboard/issues\n"
|
||||||
|
"POT-Creation-Date: 2024-03-08 15:47+0000\n"
|
||||||
|
"PO-Revision-Date: 2024-03-08 16:56+0000\n"
|
||||||
|
"Last-Translator: Andi Chandler <andi@gowling.com>\n"
|
||||||
|
"Language-Team: British English <en_GB@li.org>\n"
|
||||||
|
"Language: en_GB\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);;\n"
|
||||||
|
"X-Generator: Poedit 3.4.2\n"
|
||||||
|
|
||||||
|
#. translators: This is a emmoji keyboard layout
|
||||||
|
#: data/popover.ui:6
|
||||||
|
msgid "Emoji"
|
||||||
|
msgstr "Emoji"
|
||||||
|
|
||||||
|
#. translators: This is a terminal keyboard layout
|
||||||
|
#: data/popover.ui:12
|
||||||
|
msgid "Terminal"
|
||||||
|
msgstr "Terminal"
|
||||||
|
|
||||||
|
#: data/popover.ui:18
|
||||||
|
msgid "Keyboard Settings"
|
||||||
|
msgstr "Keyboard Settings"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:3
|
||||||
|
msgid "Squeekboard"
|
||||||
|
msgstr "Squeekboard"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:4
|
||||||
|
msgid "On Screen Keyboard"
|
||||||
|
msgstr "On Screen Keyboard"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:5
|
||||||
|
msgid "An on screen virtual keyboard"
|
||||||
|
msgstr "An on screen virtual keyboard"
|
||||||
45
po/ja.po
Normal file
45
po/ja.po
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Japanese translation for squeekboard.
|
||||||
|
# Copyright (C) 2025 squeekboard's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the squeekboard package.
|
||||||
|
# Kusano Takayuki <https://bsky.app/profile/tkusano.jp>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squeekboard main\n"
|
||||||
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
|
||||||
|
"issues\n"
|
||||||
|
"POT-Creation-Date: 2025-05-10 22:18+0000\n"
|
||||||
|
"PO-Revision-Date: 2025-05-28 23:36+0000\n"
|
||||||
|
"Last-Translator: Kusano Takayuki <https://bsky.app/profile/tkusano.jp>\n"
|
||||||
|
"Language-Team: Japanese <https://l10n.gnome.org/teams/ja/>\n"
|
||||||
|
"Language: ja\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
|
#. translators: This is a emmoji keyboard layout
|
||||||
|
#: data/popover.ui:6
|
||||||
|
msgid "Emoji"
|
||||||
|
msgstr "絵文字"
|
||||||
|
|
||||||
|
#. translators: This is a terminal keyboard layout
|
||||||
|
#: data/popover.ui:12
|
||||||
|
msgid "Terminal"
|
||||||
|
msgstr "端末"
|
||||||
|
|
||||||
|
#: data/popover.ui:18
|
||||||
|
msgid "Keyboard Settings"
|
||||||
|
msgstr "キーボード設定"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:3
|
||||||
|
msgid "Squeekboard"
|
||||||
|
msgstr "Squeekboard"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:4
|
||||||
|
msgid "On Screen Keyboard"
|
||||||
|
msgstr "オンスクリーンキーボード"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:5
|
||||||
|
msgid "An on screen virtual keyboard"
|
||||||
|
msgstr "オンスクリーンの仮想キーボード"
|
||||||
45
po/uz.po
Normal file
45
po/uz.po
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Uzbek (Latin) translation for squeekboard.
|
||||||
|
# Copyright (C) 2025 squeekboard's COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the squeekboard package.
|
||||||
|
# Baxrom Raxmatov <magdiyevbahrom@gmail.com>, 2025.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: squeekboard main\n"
|
||||||
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/World/Phosh/squeekboard/"
|
||||||
|
"issues\n"
|
||||||
|
"POT-Creation-Date: 2025-03-25 17:01+0000\n"
|
||||||
|
"PO-Revision-Date: 2025-04-04 22:08+0500\n"
|
||||||
|
"Last-Translator: \n"
|
||||||
|
"Language-Team: Uzbek (Latin) <uz@li.org>\n"
|
||||||
|
"Language: uz\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.6\n"
|
||||||
|
|
||||||
|
#. translators: This is a emmoji keyboard layout
|
||||||
|
#: data/popover.ui:6
|
||||||
|
msgid "Emoji"
|
||||||
|
msgstr "Emoji"
|
||||||
|
|
||||||
|
#. translators: This is a terminal keyboard layout
|
||||||
|
#: data/popover.ui:12
|
||||||
|
msgid "Terminal"
|
||||||
|
msgstr "Terminal"
|
||||||
|
|
||||||
|
#: data/popover.ui:18
|
||||||
|
msgid "Keyboard Settings"
|
||||||
|
msgstr "Klaviatura sozlamalari"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:3
|
||||||
|
msgid "Squeekboard"
|
||||||
|
msgstr "Squeekboard"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:4
|
||||||
|
msgid "On Screen Keyboard"
|
||||||
|
msgstr "Ekran klaviaturasi"
|
||||||
|
|
||||||
|
#: data/sm.puri.Squeekboard.desktop.in.in:5
|
||||||
|
msgid "An on screen virtual keyboard"
|
||||||
|
msgstr "Ekrandagi virtual klaviatura"
|
||||||
@ -1186,7 +1186,7 @@ mod seat {
|
|||||||
key_id,
|
key_id,
|
||||||
modifier, time,
|
modifier, time,
|
||||||
),
|
),
|
||||||
false => submission.handle_drop_modifier(key_id, time),
|
false => submission.handle_drop_modifier(key_id, modifier, time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// only show when UI is present
|
// only show when UI is present
|
||||||
|
|||||||
238
src/popover.rs
238
src/popover.rs
@ -1,24 +1,24 @@
|
|||||||
/*! The layout chooser popover */
|
/*! The layout chooser popover */
|
||||||
|
|
||||||
use gio;
|
|
||||||
use gtk;
|
|
||||||
use std::ffi::CString;
|
|
||||||
use std::cmp::Ordering;
|
|
||||||
use crate::actors;
|
use crate::actors;
|
||||||
use crate::layout::c::{ Bounds, EekGtkKeyboard };
|
use crate::layout::c::{Bounds, EekGtkKeyboard};
|
||||||
use crate::locale::{ OwnedTranslation, compare_current_locale };
|
use crate::locale::{compare_current_locale, OwnedTranslation};
|
||||||
use crate::logging;
|
use crate::logging;
|
||||||
use crate::receiver;
|
use crate::receiver;
|
||||||
use crate::resources;
|
use crate::resources;
|
||||||
use crate::state;
|
use crate::state;
|
||||||
|
use gio;
|
||||||
|
use gtk;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::ffi::CString;
|
||||||
|
|
||||||
// Traits
|
// Traits
|
||||||
|
use crate::logging::Warn;
|
||||||
use gio::prelude::ActionMapExt;
|
use gio::prelude::ActionMapExt;
|
||||||
use gio::prelude::SettingsExt;
|
use gio::prelude::SettingsExt;
|
||||||
use glib::translate::FromGlibPtrNone;
|
use glib::translate::FromGlibPtrNone;
|
||||||
use glib::variant::ToVariant;
|
use glib::variant::ToVariant;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use crate::logging::Warn;
|
|
||||||
|
|
||||||
mod c {
|
mod c {
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
@ -34,22 +34,23 @@ mod variants {
|
|||||||
use glib_sys;
|
use glib_sys;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
use glib::ToVariant;
|
|
||||||
use glib::translate::FromGlibPtrFull;
|
use glib::translate::FromGlibPtrFull;
|
||||||
use glib::translate::FromGlibPtrNone;
|
use glib::translate::FromGlibPtrNone;
|
||||||
use glib::translate::ToGlibPtr;
|
use glib::translate::ToGlibPtr;
|
||||||
|
use glib::ToVariant;
|
||||||
|
|
||||||
/// Unpacks tuple & array variants
|
/// Unpacks tuple & array variants
|
||||||
fn get_items(items: glib::Variant) -> Vec<glib::Variant> {
|
fn get_items(items: glib::Variant) -> Vec<glib::Variant> {
|
||||||
let variant_naked = items.to_glib_none().0;
|
let variant_naked = items.to_glib_none().0;
|
||||||
let count = unsafe { glib_sys::g_variant_n_children(variant_naked) };
|
let count = unsafe { glib_sys::g_variant_n_children(variant_naked) };
|
||||||
(0..count).map(|index|
|
(0..count)
|
||||||
unsafe {
|
.map(|index| unsafe {
|
||||||
glib::Variant::from_glib_full(
|
glib::Variant::from_glib_full(glib_sys::g_variant_get_child_value(
|
||||||
glib_sys::g_variant_get_child_value(variant_naked, index)
|
variant_naked,
|
||||||
)
|
index,
|
||||||
}
|
))
|
||||||
).collect()
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Unpacks "a(ss)" variants
|
/// Unpacks "a(ss)" variants
|
||||||
@ -57,19 +58,14 @@ mod variants {
|
|||||||
get_items(items)
|
get_items(items)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(get_items)
|
.map(get_items)
|
||||||
.map(|v| {
|
.map(|v| (v[0].get::<String>().unwrap(), v[1].get::<String>().unwrap()))
|
||||||
(
|
|
||||||
v[0].get::<String>().unwrap(),
|
|
||||||
v[1].get::<String>().unwrap(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "a(ss)" variant
|
/// "a(ss)" variant
|
||||||
/// Rust doesn't allow implementing existing traits for existing types
|
/// Rust doesn't allow implementing existing traits for existing types
|
||||||
pub struct ArrayPairString(pub Vec<(String, String)>);
|
pub struct ArrayPairString(pub Vec<(String, String)>);
|
||||||
|
|
||||||
impl ToVariant for ArrayPairString {
|
impl ToVariant for ArrayPairString {
|
||||||
fn to_variant(&self) -> Variant {
|
fn to_variant(&self) -> Variant {
|
||||||
let tspec = "a(ss)".to_glib_none();
|
let tspec = "a(ss)".to_glib_none();
|
||||||
@ -88,11 +84,7 @@ mod variants {
|
|||||||
let a: *const c_char = a.0;
|
let a: *const c_char = a.0;
|
||||||
let b: *const c_char = b.0;
|
let b: *const c_char = b.0;
|
||||||
unsafe {
|
unsafe {
|
||||||
glib_sys::g_variant_builder_add(
|
glib_sys::g_variant_builder_add(builder, ispec.0, a, b);
|
||||||
builder,
|
|
||||||
ispec.0,
|
|
||||||
a, b
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,24 +98,23 @@ mod variants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_settings(schema_name: &str) -> Option<gio::Settings> {
|
fn get_settings(schema_name: &str) -> Option<gio::Settings> {
|
||||||
let mut error_handler = logging::Print{};
|
let mut error_handler = logging::Print {};
|
||||||
|
|
||||||
let ss = gio::SettingsSchemaSource::default();
|
let ss = gio::SettingsSchemaSource::default();
|
||||||
|
|
||||||
ss.or_warn(
|
ss.or_warn(
|
||||||
|
&mut error_handler,
|
||||||
|
logging::Problem::Surprise,
|
||||||
|
"No gsettings schemas installed.",
|
||||||
|
)
|
||||||
|
.and_then(|sss| {
|
||||||
|
sss.lookup(schema_name, true).or_warn(
|
||||||
&mut error_handler,
|
&mut error_handler,
|
||||||
logging::Problem::Surprise,
|
logging::Problem::Surprise,
|
||||||
"No gsettings schemas installed.",
|
&format!("Gsettings schema {} not installed", schema_name),
|
||||||
)
|
)
|
||||||
.and_then(|sss|
|
})
|
||||||
sss.lookup(schema_name, true)
|
.map(|_sschema| gio::Settings::new(schema_name))
|
||||||
.or_warn(
|
|
||||||
&mut error_handler,
|
|
||||||
logging::Problem::Surprise,
|
|
||||||
&format!("Gsettings schema {} not installed", schema_name),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.map(|_sschema| gio::Settings::new(schema_name))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_layout(kind: &str, name: &str) {
|
fn set_layout(kind: &str, name: &str) {
|
||||||
@ -134,14 +125,11 @@ fn set_layout(kind: &str, name: &str) {
|
|||||||
let inputs = settings.value("sources");
|
let inputs = settings.value("sources");
|
||||||
|
|
||||||
let current = (kind.clone(), name.clone());
|
let current = (kind.clone(), name.clone());
|
||||||
let inputs = variants::get_tuples(inputs).into_iter()
|
let inputs = variants::get_tuples(inputs)
|
||||||
|
.into_iter()
|
||||||
.filter(|t| t != ¤t);
|
.filter(|t| t != ¤t);
|
||||||
let inputs = vec![(kind, name)].into_iter()
|
let inputs = vec![(kind, name)].into_iter().chain(inputs).collect();
|
||||||
.chain(inputs).collect();
|
let _ = settings.set_value("sources", &variants::ArrayPairString(inputs).to_variant());
|
||||||
let _ = settings.set_value(
|
|
||||||
"sources",
|
|
||||||
&variants::ArrayPairString(inputs).to_variant(),
|
|
||||||
);
|
|
||||||
settings.apply();
|
settings.apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,10 +138,7 @@ fn set_layout(kind: &str, name: &str) {
|
|||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
pub enum LayoutId {
|
pub enum LayoutId {
|
||||||
/// Affects the layout in system settings
|
/// Affects the layout in system settings
|
||||||
System {
|
System { kind: String, name: String },
|
||||||
kind: String,
|
|
||||||
name: String,
|
|
||||||
},
|
|
||||||
/// Only affects what this input method presents
|
/// Only affects what this input method presents
|
||||||
Local(String),
|
Local(String),
|
||||||
}
|
}
|
||||||
@ -167,14 +152,12 @@ impl LayoutId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_visible_layout(
|
fn set_visible_layout(layout_id: &LayoutId) {
|
||||||
layout_id: &LayoutId,
|
|
||||||
) {
|
|
||||||
match layout_id {
|
match layout_id {
|
||||||
LayoutId::System { kind, name } => {
|
LayoutId::System { kind, name } => {
|
||||||
set_layout(kind, name);
|
set_layout(kind, name);
|
||||||
},
|
}
|
||||||
_ => {},
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,18 +187,17 @@ fn translate_layout_names(layouts: &Vec<LayoutId>) -> Vec<OwnedTranslation> {
|
|||||||
// Attempt to take all xkb names from gnome-desktop's xkb info.
|
// Attempt to take all xkb names from gnome-desktop's xkb info.
|
||||||
let xkb_translator = crate::locale::XkbInfo::new();
|
let xkb_translator = crate::locale::XkbInfo::new();
|
||||||
|
|
||||||
let translated_names = layouts.iter()
|
let translated_names = layouts.iter().map(|id| match id {
|
||||||
.map(|id| match id {
|
LayoutId::System { name, kind: _ } => xkb_translator
|
||||||
LayoutId::System { name, kind: _ } => {
|
.get_display_name(name)
|
||||||
xkb_translator.get_display_name(name)
|
.map(|s| Status::Translated(OwnedTranslation(s)))
|
||||||
.map(|s| Status::Translated(OwnedTranslation(s)))
|
.or_print(
|
||||||
.or_print(
|
logging::Problem::Surprise,
|
||||||
logging::Problem::Surprise,
|
&format!("No display name for xkb layout {}", name),
|
||||||
&format!("No display name for xkb layout {}", name),
|
)
|
||||||
).unwrap_or_else(|| Status::Remaining(name.clone()))
|
.unwrap_or_else(|| Status::Remaining(name.clone())),
|
||||||
},
|
LayoutId::Local(_) => unreachable!(),
|
||||||
LayoutId::Local (_) => unreachable!(),
|
});
|
||||||
});
|
|
||||||
|
|
||||||
translated_names
|
translated_names
|
||||||
.map(|status| match status {
|
.map(|status| match status {
|
||||||
@ -234,7 +216,8 @@ pub fn show(
|
|||||||
unsafe { gtk::set_initialized() };
|
unsafe { gtk::set_initialized() };
|
||||||
let window = unsafe { gtk::Widget::from_glib_none(window.0) };
|
let window = unsafe { gtk::Widget::from_glib_none(window.0) };
|
||||||
|
|
||||||
let overlay_layouts = resources::get_overlays().into_iter()
|
let overlay_layouts = resources::get_overlays()
|
||||||
|
.into_iter()
|
||||||
.map(|name| LayoutId::Local(name.to_string()));
|
.map(|name| LayoutId::Local(name.to_string()));
|
||||||
|
|
||||||
let settings = get_settings("org.gnome.desktop.input-sources");
|
let settings = get_settings("org.gnome.desktop.input-sources");
|
||||||
@ -245,14 +228,10 @@ pub fn show(
|
|||||||
variants::get_tuples(inputs)
|
variants::get_tuples(inputs)
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|| Vec::new());
|
.unwrap_or_else(|| Vec::new());
|
||||||
|
|
||||||
let system_layouts: Vec<LayoutId> = inputs.into_iter()
|
|
||||||
.map(|(kind, name)| LayoutId::System { kind, name })
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let all_layouts: Vec<LayoutId> = system_layouts.clone()
|
let system_layouts: Vec<LayoutId> = inputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(overlay_layouts)
|
.map(|(kind, name)| LayoutId::System { kind, name })
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let translated_names = translate_layout_names(&system_layouts);
|
let translated_names = translate_layout_names(&system_layouts);
|
||||||
@ -268,96 +247,35 @@ pub fn show(
|
|||||||
match (layout_a, layout_b) {
|
match (layout_a, layout_b) {
|
||||||
(LayoutId::Local(_), LayoutId::System { .. }) => Ordering::Greater,
|
(LayoutId::Local(_), LayoutId::System { .. }) => Ordering::Greater,
|
||||||
(LayoutId::System { .. }, LayoutId::Local(_)) => Ordering::Less,
|
(LayoutId::System { .. }, LayoutId::Local(_)) => Ordering::Less,
|
||||||
_ => compare_current_locale(&tr_a.0, &tr_b.0)
|
_ => compare_current_locale(&tr_a.0, &tr_b.0),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let model: gio::Menu = {
|
let current_layout = get_current_layout(popover, &system_layouts);
|
||||||
{
|
let mut found_current = false;
|
||||||
let builder = gtk::Builder::from_resource("/sm/puri/squeekboard/popover.ui");
|
let mut target_layout = None;
|
||||||
builder.object("app-menu").unwrap()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (tr, l) in human_names.iter().rev() {
|
for (_, l) in human_names.iter() {
|
||||||
let detailed_action = format!("layout::{}", l.get_name());
|
if found_current {
|
||||||
let item = gio::MenuItem::new(Some(&tr.0), Some(detailed_action.as_str()));
|
target_layout = Some(l.clone());
|
||||||
model.prepend_item (&item);
|
break;
|
||||||
|
}
|
||||||
|
if let Some(current) = ¤t_layout {
|
||||||
|
if current == l {
|
||||||
|
println!("Found current: {:?} vs {:?}", current, l);
|
||||||
|
found_current = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if target_layout.is_none() {
|
||||||
|
target_layout = human_names.first().map(|item| item.1.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let menu = gtk::Popover::from_model(Some(&window), &model);
|
if let Some(target) = target_layout {
|
||||||
|
println!("Target layout: {:?}", target);
|
||||||
menu.set_pointing_to(>k::Rectangle::new (
|
app_state
|
||||||
position.x.ceil() as i32,
|
.send(state::Event::OverlayChanged(target.clone()))
|
||||||
position.y.ceil() as i32,
|
.or_print(logging::Problem::Bug, &format!("Can't send to state"));
|
||||||
position.width.floor() as i32,
|
set_visible_layout(&target);
|
||||||
position.width.floor() as i32,
|
}
|
||||||
));
|
|
||||||
menu.set_constrain_to(gtk::PopoverConstraint::None);
|
|
||||||
|
|
||||||
let action_group = gio::SimpleActionGroup::new();
|
|
||||||
|
|
||||||
if let Some(current_layout) = get_current_layout(popover, &system_layouts) {
|
|
||||||
let current_layout_name = all_layouts.iter()
|
|
||||||
.find(
|
|
||||||
|l| l.get_name() == current_layout.get_name()
|
|
||||||
).unwrap()
|
|
||||||
.get_name();
|
|
||||||
log_print!(logging::Level::Debug, "Current Layout {}", current_layout_name);
|
|
||||||
|
|
||||||
let layout_action = gio::SimpleAction::new_stateful(
|
|
||||||
"layout",
|
|
||||||
Some(current_layout_name.to_variant().type_()),
|
|
||||||
¤t_layout_name.to_variant()
|
|
||||||
);
|
|
||||||
|
|
||||||
let menu_inner = menu.clone();
|
|
||||||
layout_action.connect_change_state(move |_action, state| {
|
|
||||||
match state {
|
|
||||||
Some(v) => {
|
|
||||||
log_print!(logging::Level::Debug, "Selected layout {}", v);
|
|
||||||
v.get::<String>()
|
|
||||||
.or_print(
|
|
||||||
logging::Problem::Bug,
|
|
||||||
&format!("Variant is not string: {:?}", v)
|
|
||||||
)
|
|
||||||
.map(|state| {
|
|
||||||
let layout = all_layouts.iter()
|
|
||||||
.find(
|
|
||||||
|choices| state == choices.get_name()
|
|
||||||
).unwrap();
|
|
||||||
app_state
|
|
||||||
.send(state::Event::OverlayChanged(layout.clone()))
|
|
||||||
.or_print(
|
|
||||||
logging::Problem::Bug,
|
|
||||||
&format!("Can't send to state"),
|
|
||||||
);
|
|
||||||
set_visible_layout(layout)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
None => log_print!(
|
|
||||||
logging::Level::Debug,
|
|
||||||
"No variant selected",
|
|
||||||
),
|
|
||||||
};
|
|
||||||
menu_inner.popdown();
|
|
||||||
});
|
|
||||||
action_group.add_action(&layout_action);
|
|
||||||
};
|
|
||||||
|
|
||||||
let settings_action = gio::SimpleAction::new("settings", None);
|
|
||||||
settings_action.set_enabled(popover.settings_active);
|
|
||||||
settings_action.connect_activate(move |_, _| {
|
|
||||||
let s = CString::new("keyboard").unwrap();
|
|
||||||
unsafe { c::popover_open_settings_panel(s.as_ptr()) };
|
|
||||||
});
|
|
||||||
action_group.add_action(&settings_action);
|
|
||||||
|
|
||||||
menu.insert_action_group("popup", Some(&action_group));
|
|
||||||
|
|
||||||
menu.bind_model(Some(&model), Some("popup"));
|
|
||||||
glib::idle_add_local(move || {
|
|
||||||
menu.popup();
|
|
||||||
glib::ControlFlow::Break
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -220,7 +220,8 @@ impl Submission {
|
|||||||
pub fn handle_add_modifier(
|
pub fn handle_add_modifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
key_id: KeyStateId,
|
key_id: KeyStateId,
|
||||||
modifier: Modifier, _time: Timestamp,
|
modifier: Modifier,
|
||||||
|
_time: Timestamp,
|
||||||
) {
|
) {
|
||||||
self.modifiers_active.push((key_id, modifier));
|
self.modifiers_active.push((key_id, modifier));
|
||||||
self.update_modifiers();
|
self.update_modifiers();
|
||||||
@ -228,10 +229,11 @@ impl Submission {
|
|||||||
|
|
||||||
pub fn handle_drop_modifier(
|
pub fn handle_drop_modifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
key_id: KeyStateId,
|
_key_id: KeyStateId,
|
||||||
|
modifier: Modifier,
|
||||||
_time: Timestamp,
|
_time: Timestamp,
|
||||||
) {
|
) {
|
||||||
vec_remove(&mut self.modifiers_active, |(id, _)| *id == key_id);
|
vec_remove(&mut self.modifiers_active, |(_, m)| *m == modifier);
|
||||||
self.update_modifiers();
|
self.update_modifiers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -311,7 +311,7 @@ pub trait WarningHandler {
|
|||||||
fn handle(&mut self, warning: &str);
|
fn handle(&mut self, warning: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the first matcing item
|
/// Removes the first matching item
|
||||||
pub fn vec_remove<T, F: FnMut(&T) -> bool>(v: &mut Vec<T>, pred: F) -> Option<T> {
|
pub fn vec_remove<T, F: FnMut(&T) -> bool>(v: &mut Vec<T>, pred: F) -> Option<T> {
|
||||||
let idx = v.iter().position(pred);
|
let idx = v.iter().position(pred);
|
||||||
idx.map(|idx| v.remove(idx))
|
idx.map(|idx| v.remove(idx))
|
||||||
|
|||||||
Reference in New Issue
Block a user