Compare commits
	
		
			31 Commits
		
	
	
		
			pureos/1.1
			...
			byz_1.14
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2e44b448af | |||
| 8293c5f10d | |||
| 601c835416 | |||
| 07d7486e06 | |||
| 5cb70a096c | |||
| cb211bb764 | |||
| 8c8728aa0f | |||
| f71e769315 | |||
| 273179e1ec | |||
| eb4b630b39 | |||
| b60ebdbd99 | |||
| 8afcd87fc8 | |||
| 99f062fe31 | |||
| be458fb10e | |||
| b8e74b3721 | |||
| 0bc654b832 | |||
| 00e9641a5f | |||
| ea3da22f9b | |||
| d753f2dc2c | |||
| 99c04fd8f5 | |||
| 2b7e8f829e | |||
| f91c58ae4d | |||
| 0c258711cf | |||
| 622cd03918 | |||
| 7589a2d1d1 | |||
| 7cb431b58d | |||
| 1dd4b38c88 | |||
| 1d3e8c9a4b | |||
| 1c6448a9f7 | |||
| 3d2f9f3d9e | |||
| a20ab70984 | 
							
								
								
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										24
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -265,9 +265,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "libc"
 | 
			
		||||
version = "0.2.93"
 | 
			
		||||
version = "0.2.94"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"
 | 
			
		||||
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "linked-hash-map"
 | 
			
		||||
@ -353,9 +353,9 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "regex-syntax"
 | 
			
		||||
version = "0.6.23"
 | 
			
		||||
version = "0.6.25"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
 | 
			
		||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rs"
 | 
			
		||||
@ -380,18 +380,18 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde"
 | 
			
		||||
version = "1.0.125"
 | 
			
		||||
version = "1.0.126"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
 | 
			
		||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "serde_derive",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "serde_derive"
 | 
			
		||||
version = "1.0.125"
 | 
			
		||||
version = "1.0.126"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
 | 
			
		||||
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
@ -412,9 +412,9 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
version = "1.0.69"
 | 
			
		||||
version = "1.0.72"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
 | 
			
		||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "proc-macro2",
 | 
			
		||||
 "quote",
 | 
			
		||||
@ -438,9 +438,9 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "unicode-xid"
 | 
			
		||||
version = "0.2.1"
 | 
			
		||||
version = "0.2.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
 | 
			
		||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "winapi"
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ if out_path:
 | 
			
		||||
    i = args.index(out_path)
 | 
			
		||||
    args.pop(i)    
 | 
			
		||||
 | 
			
		||||
subprocess.run(['sh', "{}/cargo.sh".format(shlex.quote(source_dir.as_posix())), 'build']
 | 
			
		||||
subprocess.run(['sh', "{}/cargo.sh".format(source_dir.as_posix()), 'build']
 | 
			
		||||
    + args,
 | 
			
		||||
    check=True)
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ if out_path:
 | 
			
		||||
    out_basename = out_path.name
 | 
			
		||||
    filename = filename or out_basename
 | 
			
		||||
    subprocess.run(['cp', '-a',
 | 
			
		||||
        './{}/{}'.format(shlex.quote(binary_dir), shlex.quote(filename)),
 | 
			
		||||
        './{}/{}'.format(binary_dir, filename),
 | 
			
		||||
        out_path],
 | 
			
		||||
        check=True)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -438,7 +438,7 @@ buttons:
 | 
			
		||||
                unlock_view: "カタカナ"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "。"
 | 
			
		||||
    # Buttons for Latin charachters
 | 
			
		||||
    # Buttons for Latin characters
 | 
			
		||||
    RSYM1:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
 | 
			
		||||
@ -438,7 +438,7 @@ buttons:
 | 
			
		||||
                unlock_view: "カタカナ"
 | 
			
		||||
        outline: "altline"
 | 
			
		||||
        label: "。"
 | 
			
		||||
    # Buttons for Latin charachters
 | 
			
		||||
    # Buttons for Latin characters
 | 
			
		||||
    RSYM1:
 | 
			
		||||
        action:
 | 
			
		||||
            locking:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										594
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										594
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							@ -1,570 +1,94 @@
 | 
			
		||||
squeekboard (1.13.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
squeekboard (1.14.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * layout: Latch keys when clicked twice
 | 
			
		||||
  * layout: Add stateless view switching
 | 
			
		||||
  * layout: Plug in stateless view switching
 | 
			
		||||
  * layout: Remove the little abomination of view change promise
 | 
			
		||||
  * view: Ąto-unlatching when multiple latching buttons pressed
 | 
			
		||||
  * renderer: Bring button drawing closer to Rust
 | 
			
		||||
  * ffi: Eliminate squeek_button and squeek_row
 | 
			
		||||
  * imservice: Increment serials on receiving done, not sending commit
 | 
			
		||||
  * input-method: Fix commit/done mixup in protocol text
 | 
			
		||||
  * CI: fix xheck_tag to be compatible with Amber
 | 
			
		||||
  * italian: Fix colon
 | 
			
		||||
  * popover: Fix prematurely deallocated CString
 | 
			
		||||
  * Rust: Remove unnecessary no_mangle statements to silence warnings
 | 
			
		||||
  * renderer: Reduce reliance on knowing the transform
 | 
			
		||||
  * renderer: Split mutable geometry and place it directly in GtkKeyboard
 | 
			
		||||
  * Revert "moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations."
 | 
			
		||||
  * layout: Make it possible to opt out of latching per-key
 | 
			
		||||
  * renderer: Mark latched buttons differently than locked
 | 
			
		||||
  * appearance: Colour latched/locked according to design
 | 
			
		||||
  * docs: Describe view switching
 | 
			
		||||
  * language-terminal: Place keyboards in a sub-path
 | 
			
		||||
  * layout selection: Fix emoji and number
 | 
			
		||||
  * rust: Fix compiler warnings
 | 
			
		||||
  * layout: Take into account text purpose again
 | 
			
		||||
  * layouts: Make selection testable
 | 
			
		||||
  * layouts: Stop assuming that layout name always changes on switch
 | 
			
		||||
  * Cargo: Version bump
 | 
			
		||||
  * debian: New upstream release
 | 
			
		||||
 | 
			
		||||
  [ J.D. Laub ]
 | 
			
		||||
  * Add US Dvorak layout (and Colemak wide)
 | 
			
		||||
  *     Add US Dvorak layout (and Colemak wide)
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 22 May 2021 14:19:27 +0000
 | 
			
		||||
 | 
			
		||||
  [ Jordi Masip ]
 | 
			
		||||
  * Catalan keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Myth ]
 | 
			
		||||
  * Added hebrew keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ David96 ]
 | 
			
		||||
  * Add Mod4 (Windows) key
 | 
			
		||||
 | 
			
		||||
  [ Panawat Wong-klaew ]
 | 
			
		||||
  * Add wide Thai keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * server-main: Add quit()
 | 
			
		||||
  * server-main: Properly register to gnome-session (Closes: #274)
 | 
			
		||||
 | 
			
		||||
  [ Kozova1 ]
 | 
			
		||||
  * Added Hebrew translations for most layouts.
 | 
			
		||||
  * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations.
 | 
			
		||||
  * Fixed Hebrew layout.
 | 
			
		||||
  * moved data/langs/he_IL.txt -> data/langs/he-IL.txt to better conform with existing translations.
 | 
			
		||||
 | 
			
		||||
  [ M33 ]
 | 
			
		||||
  * Revert "Update tests/meson.build"
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 12 Apr 2021 10:40:32 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.12.0pureos0~amber0) amber-phone; urgency=medium
 | 
			
		||||
squeekboard (1.13.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * docs: Correct Cargo update instructions
 | 
			
		||||
  * visibility: Centralize keyboard panel visibility policy and handling
 | 
			
		||||
  * build: Fix release
 | 
			
		||||
  * tests: Prefer the env var for finding test layouts
 | 
			
		||||
  * tests: Explicitly pass source directory to tests
 | 
			
		||||
  * debian: Build reproducibly
 | 
			
		||||
  * tests: Allow legacy mode to have much longer tests.
 | 
			
		||||
  * build: Enable unused warnings in C
 | 
			
		||||
  * build: Enable wformat to remove warnings about missing wformat
 | 
			
		||||
  * build: Fail on any C warnings when strict
 | 
			
		||||
  * data: Made data flow in fallback clearer
 | 
			
		||||
  * data: Flattened layout fallback function
 | 
			
		||||
  * layouts: Use base as fallback for alternative layouts
 | 
			
		||||
  * layouts: Simplify the main flow of source list
 | 
			
		||||
  * tests: Add some description to the list of tested layouts
 | 
			
		||||
  * layout_names: Unmess the list of builtin layouts
 | 
			
		||||
  * dbus: Reset hints if text input missing
 | 
			
		||||
  * visibility: Stop calling GTK functions from the visibility manager
 | 
			
		||||
  * debian: New upstream release
 | 
			
		||||
 | 
			
		||||
  [ Wannaphong Phatthiyaphaibun ]
 | 
			
		||||
  * Add thai keyboard
 | 
			
		||||
  * Update resources.rs
 | 
			
		||||
  * Update meson.build
 | 
			
		||||
  * escape " on thai keyboard
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 12 Apr 2021 10:50:32 +0000a
 | 
			
		||||
 | 
			
		||||
  [ clonex10100 ]
 | 
			
		||||
  * Added US Colemak Keyboard Layout
 | 
			
		||||
squeekboard (1.12.0-1pureos1) byzantium; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * debian: New Byzantium release
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Thu, 28 Jan 2021 14:36:20 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.12.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Henry-Nicolas Tourneur ]
 | 
			
		||||
  * d/rules: fix an FTBFS on mips64el with GOT > 64kb
 | 
			
		||||
  * d/rules: export RUSTFLAGS only on architecture that needs it
 | 
			
		||||
  * d/rules: export RUSTFLAGS only on architecture that needs it
 | 
			
		||||
 | 
			
		||||
  [ Jiří Stránský ]
 | 
			
		||||
  * Add Czech keyboard layouts
 | 
			
		||||
 | 
			
		||||
  [ Stefan Grotz ]
 | 
			
		||||
  * Esperanto keyboard
 | 
			
		||||
 | 
			
		||||
  [ Vladimir ]
 | 
			
		||||
  * Bulgarian language keyboard layout
 | 
			
		||||
 | 
			
		||||
  [ Vladimir Stoilov ]
 | 
			
		||||
  * bulgarian add translation and to needed lists
 | 
			
		||||
  * Fix bulgarian layout size
 | 
			
		||||
 | 
			
		||||
  [ Andreas Rönnquist ]
 | 
			
		||||
  * no: Use wide button switching between numbers, symbols and base
 | 
			
		||||
 | 
			
		||||
  [ jranaraki ]
 | 
			
		||||
  * Farsi/Persian keyboard layout
 | 
			
		||||
  * Farsi/Persian keyboard layout
 | 
			
		||||
  * Added requirements to resources.rs and meson.build
 | 
			
		||||
  * Updated the layout to provide more convenient and faster typing experience
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sun, 10 Jan 2021 09:43:42 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.11.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * keyboard: Fix semicolon in German layout
 | 
			
		||||
  * keyboard: Move semicolon in German layout to numbers view replacing redundant comma key
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * imservice: Set up UI according to current needs when it shows up
 | 
			
		||||
  * UI: Keep visibility factors in a central place
 | 
			
		||||
  * cargo: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 21 Nov 2020 11:08:06 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.11.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * UI: Delay hiding only when leaving a text field
 | 
			
		||||
  * ui: Cancel hiding delay when activity requested again
 | 
			
		||||
  * Update dependencies
 | 
			
		||||
 | 
			
		||||
  [ Fabio Tomat ]
 | 
			
		||||
  * Update fur-IT.txt fix typo for Spanish
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 14 Nov 2020 06:46:28 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.10.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * virtual_keyboard: Fix desynced modifiers state
 | 
			
		||||
  * rust: Fix deprecation warnings
 | 
			
		||||
  * docs: Tutorial syntax cleanups
 | 
			
		||||
  * docs: Reorganize tutorial
 | 
			
		||||
  * build: Error on repeating declarations
 | 
			
		||||
  * keymap: Generate from symbol map, not layout
 | 
			
		||||
  * data: Restore testability of action->keysym conversion
 | 
			
		||||
  * syntax: Let older rustc understand symbolmap's lifetime
 | 
			
		||||
  * debian: Insert a "breaks" for librem5-base < 24
 | 
			
		||||
  * keymap: Keep keymap fd management in one place
 | 
			
		||||
  * vkeyboard: Use a generic slice instead of a vector
 | 
			
		||||
  * tests: Check for missing return in builtin layouts except emoji
 | 
			
		||||
  * keymap: Concentrate special handling of BackSpace, which is implicit in Erase action
 | 
			
		||||
  * keymaps: Use multiple key maps, each within the limit of what Xorg can accept.
 | 
			
		||||
  * build: Avoid MaybeUninit on older Debian
 | 
			
		||||
  * tests: Fix bad field access
 | 
			
		||||
  * cargo: Update dependencies
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * eekboard-context-service: Return early if schema is unavailable
 | 
			
		||||
  * treewide: Use new style function definitions
 | 
			
		||||
  * build: Enable '-Wold-style-definition' '-Wstrict-prototypes'
 | 
			
		||||
  * build: Enable '-Wunused-function'
 | 
			
		||||
  * eekboard-context-service: Drop EEKBOARD_CONTEXT_SERVICE_GET_PRIVATE
 | 
			
		||||
  * keyboard: Fix warning
 | 
			
		||||
  * layout: Fix warning
 | 
			
		||||
  * gitlab-ci: Enable --Werror
 | 
			
		||||
  * eek-keyboard: Don't ignore return value
 | 
			
		||||
  * build: Enable -Winit-self
 | 
			
		||||
  * build: Enable -Wformat-security
 | 
			
		||||
  * build: Enable -Wmaybe-uninitialized
 | 
			
		||||
  * treewide: Drop redundant declarations
 | 
			
		||||
  * build: Enable -Wredundant-declarations
 | 
			
		||||
  * ServerContextService: Drop GObject boilerplate
 | 
			
		||||
  * build: Enable '-Wformat-nonliteral'
 | 
			
		||||
  * eekboad-context-service: Drop signal class handler
 | 
			
		||||
  * eekboard-context-service: Drop docstrings for inexistent functions
 | 
			
		||||
  * eekboard-context-service: Drop the GObject boilerplate
 | 
			
		||||
  * eekboard-context-service: Drop private struct
 | 
			
		||||
  * server-context-service: Consistenty name self argument 'self'
 | 
			
		||||
  * server-context-service: swap signal arguments
 | 
			
		||||
  * server-context-service: Don't show keyboard when disabled (Closes: #222)
 | 
			
		||||
 | 
			
		||||
  [ Nazarii Kretovych ]
 | 
			
		||||
  * Add Ukrainian keyboard layout.
 | 
			
		||||
 | 
			
		||||
  [ Benjamin Schaaf ]
 | 
			
		||||
  * Fix spelling mistakes in doc/hacking.md
 | 
			
		||||
  * Expand the development documentation in the readme
 | 
			
		||||
  * Expand key press detection to the edges of the view's bounding box
 | 
			
		||||
  * Sort layouts by type before sorting by name
 | 
			
		||||
  * Fix leak in level_keyboard_new
 | 
			
		||||
  * Fix leak endlessly adding a resource path to the default theme
 | 
			
		||||
  * Add settings option to popover
 | 
			
		||||
 | 
			
		||||
  [ Al ]
 | 
			
		||||
  * proposal for belgian layout (copy of fr)
 | 
			
		||||
  * alphabetical order for src/resources.rs tests/meson.build
 | 
			
		||||
  * debian: Build reproducibly
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * eek-gtk-keyboard: use virtual resolution to check arrangement kind
 | 
			
		||||
  * server-context-service: optimize height calculation
 | 
			
		||||
  * keyboards: add wide French layout
 | 
			
		||||
  * keyboards: add wide Belgian layout
 | 
			
		||||
  * keyboards: add wide terminal layout
 | 
			
		||||
  * New upstream version 1.12.0
 | 
			
		||||
 | 
			
		||||
  [ Fabio Tomat ]
 | 
			
		||||
  * Revert "Add friulian keyboard"
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 26 Jan 2021 18:19:42 +0100
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 19 Oct 2020 14:07:01 +0000
 | 
			
		||||
squeekboard (1.11.1-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.3) amber-phone; urgency=medium
 | 
			
		||||
  * New upstream version 1.11.1
 | 
			
		||||
 | 
			
		||||
  [ Björn Tantau ]
 | 
			
		||||
  * Show more useful keys at the same time.
 | 
			
		||||
  * Add Ctrl and Alt modifier keys.
 | 
			
		||||
  * Add missing Ê key.
 | 
			
		||||
  * Make f-keys slightly wider.
 | 
			
		||||
  * Add Menu key.
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 24 Nov 2020 11:52:41 +0100
 | 
			
		||||
 | 
			
		||||
  [ Guido Günther ]
 | 
			
		||||
  * d/rules: Only remove Cargo.lock if it exists
 | 
			
		||||
  * eek: Drop libcanberra usage
 | 
			
		||||
  * debian: Build-depend on libfeedback
 | 
			
		||||
  * eek-gtk-keyboard: Trigger event feedback on button press (Closes: #166)
 | 
			
		||||
squeekboard (1.11.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * build: Add missing gio-unix dependency
 | 
			
		||||
  * build: Make compatible with Debian Bullseye
 | 
			
		||||
  * debian: Add amber to legacy distro list
 | 
			
		||||
  * ci: Add amber job
 | 
			
		||||
  * debian: Require lsb-release
 | 
			
		||||
  * size: Hardcode size to work around screen rotation
 | 
			
		||||
  * ci: Re-add x64 Buster build
 | 
			
		||||
  * italian: Fix space and period
 | 
			
		||||
  * New upstream release 1.11.0
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * Revert "Merge branch 'btantau-master-patch-76686' into 'master'"
 | 
			
		||||
  * Terminal layout: another approach
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Mon, 16 Nov 2020 11:17:23 +0100
 | 
			
		||||
 | 
			
		||||
  [ Luís Fernando Stürmer da Rosa ]
 | 
			
		||||
  * Brazilian Portuguese Keyboard Layout.
 | 
			
		||||
squeekboard (1.10.0-2) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
 -- Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>  Wed, 05 Aug 2020 16:16:08 +0200
 | 
			
		||||
  * Team upload.
 | 
			
		||||
  * d/rules: set RUSTFLAGS to avoid an FTBFS on mips64el (Closes: #974036)
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.2) amber-phone; urgency=medium
 | 
			
		||||
 -- Henry-Nicolas Tourneur <debian@nilux.be>  Tue, 10 Nov 2020 18:40:50 +0000
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * keyboard: Remove unused code
 | 
			
		||||
  * gsettings: Don't crash when unavailable
 | 
			
		||||
  * dbus: Don't crash if can't make a connection
 | 
			
		||||
  * gsettings: Don't crash on switching when unavailable
 | 
			
		||||
  * layout: Split out choice to a struct on its own
 | 
			
		||||
  * renderer: Simplify by dropping gobjectness
 | 
			
		||||
  * levelkeyboard: Rearrange to make future conversion easier
 | 
			
		||||
  * layout: Minor generalizations
 | 
			
		||||
  * Remove unused code
 | 
			
		||||
  * sizing: Create a standalone UI shape manager
 | 
			
		||||
  * sizing: Ignore scaling factor for layout selection
 | 
			
		||||
  * CI: Fix typo
 | 
			
		||||
  * Update rust deps for release
 | 
			
		||||
squeekboard (1.10.0-1) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Andreas Rönnquist ]
 | 
			
		||||
  * Swedish keyboard, wide button switching between numbers, symbols and base
 | 
			
		||||
  * More fixes of button sizes
 | 
			
		||||
  * Folder is doc, not docs
 | 
			
		||||
  * New upstream release 1.10.0
 | 
			
		||||
  * d/control: build-depend on libfeedbackd-dev and set team maintainership
 | 
			
		||||
  * d/control: fix dependency name
 | 
			
		||||
  * d/copyright: add missing entries
 | 
			
		||||
  * d/copyright: add entries for new keyboard files and remove duplicate
 | 
			
		||||
    `src/meson.build` appeared in 2 different paragraphs, remove the
 | 
			
		||||
    duplicate entry.
 | 
			
		||||
  * d/gbp.conf: fix debian version number
 | 
			
		||||
 | 
			
		||||
  [ uzanto ]
 | 
			
		||||
  * Add new file
 | 
			
		||||
  * Replace duplicated show_symbols by show_eschars and removed "Delete" button that it's doing nothing
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Fri, 23 Oct 2020 13:18:43 +0200
 | 
			
		||||
 | 
			
		||||
  [ Arnaud Ferraris ]
 | 
			
		||||
  * keyboards: fr: fix keyboard layout
 | 
			
		||||
  * keyboards: fr: make sure the layout fits the screen
 | 
			
		||||
  * resources: include French keyboard layout
 | 
			
		||||
  * keyboards: fr: improve consistency with other layouts
 | 
			
		||||
  * keyboards: fr: improve diacritics layout
 | 
			
		||||
  * tests: add french layout
 | 
			
		||||
squeekboard (1.9.3-1) experimental; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Vlad ]
 | 
			
		||||
  * Fresh Russian layout
 | 
			
		||||
  * Upload to experimental
 | 
			
		||||
  * Update upstream source from tag 'v1.9.3'
 | 
			
		||||
    Update to upstream version '1.9.3'
 | 
			
		||||
    with Debian dir 7a3f8b82779759ba288b75755ba54500250b0ff4
 | 
			
		||||
  * d/control: Use librust-xkbcommon-dev
 | 
			
		||||
    This one avoids the empty feature package.
 | 
			
		||||
  * Ship sm.puri.OSK0.desktop.
 | 
			
		||||
    This is needed to fulfill phosh's session dependencies
 | 
			
		||||
  * Conflict with phosh-osk-stub.
 | 
			
		||||
    They're not useful at the same time and we'll drop phosh-osk-stub from
 | 
			
		||||
    Debian once squeekboard is in.
 | 
			
		||||
  * Drop pathes no longer required due to upstream changes
 | 
			
		||||
    - 0001-Cargo.toml-update-to-Debian-dependencies-versions.patch
 | 
			
		||||
    - 0002-popover.rs-fix-build-with-gtk-rs-0.7.0.patch
 | 
			
		||||
  * d/gbp.conf: Don't use patch numbers.
 | 
			
		||||
    Ordering is defined via the series file and patch numbers just
 | 
			
		||||
    cause manual work.
 | 
			
		||||
 | 
			
		||||
  [ Jordi Masip ]
 | 
			
		||||
  * Removed unused dependency 'libcroco'
 | 
			
		||||
 -- Guido Günther <agx@sigxcpu.org>  Sat, 26 Sep 2020 13:01:18 +0200
 | 
			
		||||
 | 
			
		||||
  [ Florian Klink ]
 | 
			
		||||
  * sm.puri.Squeekboard.desktop: make path to Exec= absolute
 | 
			
		||||
squeekboard (1.9.2-1) UNRELEASED; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Ole Guldberg ]
 | 
			
		||||
  * Danish keyboard layout
 | 
			
		||||
  * Danish keyboard layout
 | 
			
		||||
  * add test for danish layout
 | 
			
		||||
  * Initial Debian release (Closes: #956960)
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 01 Jun 2020 09:39:12 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * layout: Improve press handling
 | 
			
		||||
  * settings: Handle empty settings
 | 
			
		||||
  * Variant: Use proper pointer conversion between C and Rust
 | 
			
		||||
  * meta: Add doap file
 | 
			
		||||
  * modifiers: Support Control and Alt
 | 
			
		||||
  * CI: Test that any bump to changelog has a corresponding tag
 | 
			
		||||
  * docs: Add the guiding principle
 | 
			
		||||
  * hacking: Move into docs/
 | 
			
		||||
 | 
			
		||||
  [ &t ]
 | 
			
		||||
  * Fix minor comment typos
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * cargo: Bump package versions before release
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sun, 08 Mar 2020 10:04:29 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.9.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * imservice: Add commit_string method
 | 
			
		||||
  * submission: Handle submitting strings
 | 
			
		||||
  * input_method: Use for erasing
 | 
			
		||||
  * logging: Use in merged functions
 | 
			
		||||
  * translations: Remove redundant ones
 | 
			
		||||
  * translations: Translate builtin layouts
 | 
			
		||||
  * greek: Rename to gr which is used by gnome settings
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layouts: Add Polish layouts
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * locks: Draw based on current view
 | 
			
		||||
  * locking: Lock keys statelessly
 | 
			
		||||
  * layouts: Better accented uppercase in PL
 | 
			
		||||
  * emoji: Add more choices
 | 
			
		||||
  * row: Eliminate angle
 | 
			
		||||
  * layout: Center views relative to each other and the layout bounds
 | 
			
		||||
  * drawing: Generalized foreach_visible_button
 | 
			
		||||
  * variant: Fix double-free
 | 
			
		||||
  * variant: Fix leak
 | 
			
		||||
  * keyboard_layout: Fix leak
 | 
			
		||||
  * layout: Improve scoping of locked variable
 | 
			
		||||
  * terminal: Make */ easier to reach
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layouts: terminal: Use altline outline for dot key
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * text input: Disable erasing
 | 
			
		||||
  * cargo: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 19 Feb 2020 14:32:39 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.8.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * action: Rename Level to View
 | 
			
		||||
  * keyboard: Introduce a KeyCode type wrapping u32
 | 
			
		||||
  * layout: Centralize handling key releases
 | 
			
		||||
  * layout: Make handling presses uniform
 | 
			
		||||
  * UI: Drop indirection for show/hide functions
 | 
			
		||||
  * managers: Move visible flag to UI manager
 | 
			
		||||
  * dbus_service: Remove unused function
 | 
			
		||||
  * dbus: Remove unneeded gobjectness
 | 
			
		||||
  * dbus: Rename handler from eekboard_service
 | 
			
		||||
  * context: Moved keymap setting together with its generation
 | 
			
		||||
  * key-emitter: Remove unused
 | 
			
		||||
  * eekboard_context_service: Drop unused enable property
 | 
			
		||||
  * services: Split out layout management from EekboardContextService
 | 
			
		||||
  * submission: Move away from virtual-keyboard
 | 
			
		||||
  * submission: Create a new wrapper over imservice
 | 
			
		||||
  * imservice: Limited scope of unsafe
 | 
			
		||||
  * EekGtkKeyboard: Use a direct reference to EekboardContext
 | 
			
		||||
  * submission: Take over virtual_keyboard handling
 | 
			
		||||
  * keyboard: Cleanups of unused code
 | 
			
		||||
  * levelkeyboard: Drop unused manager references
 | 
			
		||||
  * keyboard: Gather up keymap handling, drop layout
 | 
			
		||||
  * submission: Remove wildcard reexport
 | 
			
		||||
  * imservice: Rename commit_state to done to match protocol
 | 
			
		||||
  * ci: Clean up `..` before it's searched for artifacts
 | 
			
		||||
  * dbus: Log error on dbus exit
 | 
			
		||||
  * logging: Try to improve common operations
 | 
			
		||||
  * imservice: Return something more resembling an Error on failure
 | 
			
		||||
  * logging: Unified to remove random eprint calls
 | 
			
		||||
  * press_key: Use proper logging
 | 
			
		||||
  * number: Fix keysym for Return
 | 
			
		||||
  * build: Strip clap of optional features
 | 
			
		||||
  * layouts: Fix segfault on switching to wide
 | 
			
		||||
  * font: Use font from style context
 | 
			
		||||
  * font: Only pass relevant data to label renderer
 | 
			
		||||
 | 
			
		||||
  [ Sebastian Krzyszkowiak ]
 | 
			
		||||
  * layout: terminal: Swap positions of preferences and actions button
 | 
			
		||||
  * layout: terminal: Show actions button on all views
 | 
			
		||||
  * layout: terminal: Replace actions button with period on symbols view
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * setup: Connect ui to the state manager
 | 
			
		||||
  * debian: Add missing commas
 | 
			
		||||
 | 
			
		||||
  [ David Boddie ]
 | 
			
		||||
  * Tidy build file and docs
 | 
			
		||||
  * Use pip to install recommonmark
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Fri, 31 Jan 2020 09:59:12 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.8.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * translations: Use gnome-desktop's xkb info database for layout names
 | 
			
		||||
  * translations: Make the code cleaner
 | 
			
		||||
  * overlay: Add terminal
 | 
			
		||||
  * eek-layout: Remove unused
 | 
			
		||||
  * pre-release: Update deps
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 14 Jan 2020 13:55:00 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.7.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * New terminal layout appearing on terminal input hint
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 08 Jan 2020 11:53:07 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.7.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * New terminal layout appearing on terminal input hint
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 08 Jan 2020 11:53:07 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.6.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * tools: Move entry.py
 | 
			
		||||
  * build: Move building of squeekboard-test-layout to tools
 | 
			
		||||
  * packaging: Install entty.py as squeekboard-entry
 | 
			
		||||
  * Remove unused build dependencies
 | 
			
		||||
  * Remove unused header generator
 | 
			
		||||
  * logging: Move all facilities to one file
 | 
			
		||||
  * logging: Described the design
 | 
			
		||||
  * logging: Add described log levels
 | 
			
		||||
  * popover: Install emoji layout
 | 
			
		||||
  * popover: Show overlays as selected
 | 
			
		||||
  * Fix old Rust woes
 | 
			
		||||
  * emoji: Add a passable layout
 | 
			
		||||
  * Fix g_ and stdlib allocation/free mismatches
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Thu, 02 Jan 2020 12:02:50 +0000
 | 
			
		||||
 
 | 
			
		||||
squeekboard (1.5.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * keycodes: Sort to eliminate runtime indeterminism
 | 
			
		||||
  * switcher: Switch layout on menu item click
 | 
			
		||||
  * Drop squeek_key
 | 
			
		||||
  * renderer: Remove some unneeded vars
 | 
			
		||||
  * renderer: Simplified outline rendering
 | 
			
		||||
  * renderer: Drop row from button rendering
 | 
			
		||||
  * renderer: Drop unused params
 | 
			
		||||
  * renderer: Simplify surface rendering
 | 
			
		||||
  * rendering: Simplify Cairo context usage, remove unneeded calls.
 | 
			
		||||
  * rendering: Remove unneeded redraw after button release
 | 
			
		||||
  * renderer: Remove unused locked key render function
 | 
			
		||||
  * renderer: Simply cut off when painting outside bounds
 | 
			
		||||
  * renderer: Render whole keyboard the same way as pressed buttons
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * layout: add German wide layout
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * renderer: Remove unused functions
 | 
			
		||||
  * cleanup: Remove references to squeek_view
 | 
			
		||||
  * cleanup: Unbox View and Row
 | 
			
		||||
  * cleanup: Remove unused single frame draw
 | 
			
		||||
  * positioning: Calculate sizes instead of storing, move position out of widgets
 | 
			
		||||
  * positioning: Clean up unused code
 | 
			
		||||
  * Fix old Rust woes
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * layout: add Japanese Kana wide layout
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * Entry test: Add Terminal input purpose
 | 
			
		||||
  * readme: Add note about Cargo dependencies
 | 
			
		||||
  * Create a library/UI module separation
 | 
			
		||||
  * hacking: Add DCO and licensing requirement
 | 
			
		||||
  * Fix internal .md link
 | 
			
		||||
 | 
			
		||||
  [ Mark Müller ]
 | 
			
		||||
  * squeekboard-test-layout: add argument parsing and some more output
 | 
			
		||||
 | 
			
		||||
  [ Dorota Czaplejewicz ]
 | 
			
		||||
  * Use clap in the lockfile
 | 
			
		||||
  * parsing: Remove bounds which weren't used anyway
 | 
			
		||||
  * layout: Respect margins
 | 
			
		||||
  * CI: Build arm64 .deb
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 23 Dec 2019 11:58:57 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.4.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * "text" property in layouts
 | 
			
		||||
  * Adjusts to user's color scheme
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 02 Dec 2019 19:37:01 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.2) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Make sure all key presses get accepted by the compositor
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 26 Nov 2019 15:36:27 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Update and fix layouts and languages
 | 
			
		||||
  * Make tests less likely to fail
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 20 Nov 2019 22:10:48 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.3.0) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Language selection popup
 | 
			
		||||
  * Swedish and Finnish layouts
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Sat, 16 Nov 2019 15:38:14 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.2) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Landscape mode
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Wed, 30 Oct 2019 12:38:39 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.1) amber-phone; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use different distribution
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 08 Oct 2019 10:56:10 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.2.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use Cargo-based dependencies
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 24 Sep 2019 10:42:15 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.1.0) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use new keyboard layout format
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Mon, 02 Sep 2019 10:12:02 +0000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
squeekboard (1.0.10) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Use a shared DBus definition
 | 
			
		||||
 | 
			
		||||
 -- Dorota Czaplejewicz <dorota.czaplejewicz@puri.sm>  Tue, 02 Jul 2019 20:12:02 +0000
 | 
			
		||||
 | 
			
		||||
squeekboard (1.0.9) unstable; urgency=medium
 | 
			
		||||
 | 
			
		||||
  * Initial release.
 | 
			
		||||
 | 
			
		||||
 -- David Boddie <david.boddie@puri.sm>  Tue, 25 Jun 2019 19:33:00 +0200
 | 
			
		||||
 -- Arnaud Ferraris <arnaud.ferraris@gmail.com>  Tue, 09 Jun 2020 23:29:19 +0200
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/control
									
									
									
									
										vendored
									
									
								
							@ -31,6 +31,8 @@ Build-Depends:
 | 
			
		||||
 wayland-protocols (>= 1.14),
 | 
			
		||||
Standards-Version: 4.1.3
 | 
			
		||||
Homepage: https://source.puri.sm/Librem5/squeekboard
 | 
			
		||||
Vcs-Browser: https://source.puri.sm/pureos/squeekboard
 | 
			
		||||
Vcs-Git: https://source.puri.sm/pureos/squeekboard.git
 | 
			
		||||
 | 
			
		||||
Package: squeekboard
 | 
			
		||||
Architecture: linux-any
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										7
									
								
								debian/gbp.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								debian/gbp.conf
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
			
		||||
[DEFAULT]
 | 
			
		||||
debian-branch = pureos/byzantium
 | 
			
		||||
debian-tag = pureos/%(version)s
 | 
			
		||||
debian-tag-msg = %(pkg)s %(version)s
 | 
			
		||||
 | 
			
		||||
[tag]
 | 
			
		||||
sign-tags = true
 | 
			
		||||
							
								
								
									
										29
									
								
								debian/librem5-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								debian/librem5-ci.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
include:
 | 
			
		||||
 - 'https://source.puri.sm/Librem5/librem5-ci/raw/master/librem5-pipeline-definitions.yml'
 | 
			
		||||
 - 'https://source.puri.sm/Librem5/librem5-ci/raw/master/librem5-pipeline-byzantium-jobs.yml'
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
 - package
 | 
			
		||||
 - test-package
 | 
			
		||||
 | 
			
		||||
.tags: &tags
 | 
			
		||||
  tags:
 | 
			
		||||
    - librem5
 | 
			
		||||
 | 
			
		||||
check_release:
 | 
			
		||||
  <<: *tags
 | 
			
		||||
  stage: test-package
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
      - pureos/byzantium
 | 
			
		||||
  script:
 | 
			
		||||
    - apt-get -y install git python3
 | 
			
		||||
    - (head -n 1 ./debian/changelog && git tag) | ./debian/check_release.py
 | 
			
		||||
 | 
			
		||||
# check-tarball relies on the contents of other branches,
 | 
			
		||||
# which are irrelevant for MRs. It's similar to checking tags in this way.
 | 
			
		||||
check-tarball:
 | 
			
		||||
  extends: .l5-check-tarball
 | 
			
		||||
  only:
 | 
			
		||||
    refs:
 | 
			
		||||
        - pureos/byzantium
 | 
			
		||||
							
								
								
									
										2
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
								
							@ -1 +1 @@
 | 
			
		||||
3.0 (native)
 | 
			
		||||
3.0 (quilt)
 | 
			
		||||
 | 
			
		||||
@ -287,7 +287,7 @@ eek_renderer_new (LevelKeyboard  *keyboard,
 | 
			
		||||
    }
 | 
			
		||||
    gtk_style_context_add_provider (renderer->view_context,
 | 
			
		||||
        GTK_STYLE_PROVIDER(renderer->css_provider),
 | 
			
		||||
        GTK_STYLE_PROVIDER_PRIORITY_USER);
 | 
			
		||||
        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 | 
			
		||||
 | 
			
		||||
    /* Create a style context for the buttons */
 | 
			
		||||
    path = gtk_widget_path_new();
 | 
			
		||||
@ -303,7 +303,7 @@ eek_renderer_new (LevelKeyboard  *keyboard,
 | 
			
		||||
    gtk_style_context_set_state (renderer->button_context, GTK_STATE_FLAG_NORMAL);
 | 
			
		||||
    gtk_style_context_add_provider (renderer->button_context,
 | 
			
		||||
        GTK_STYLE_PROVIDER(renderer->css_provider),
 | 
			
		||||
        GTK_STYLE_PROVIDER_PRIORITY_USER);
 | 
			
		||||
        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
 | 
			
		||||
    return renderer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
project(
 | 
			
		||||
    'squeekboard',
 | 
			
		||||
    'c', 'rust',
 | 
			
		||||
    version: '1.13.0',
 | 
			
		||||
    version: '1.14.0',
 | 
			
		||||
    license: 'GPLv3',
 | 
			
		||||
    meson_version: '>=0.51.0',
 | 
			
		||||
    default_options: [
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										424
									
								
								src/data/loading.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										424
									
								
								src/data/loading.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,424 @@
 | 
			
		||||
/* Copyright (C) 2020-2021 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! Loading layout files */
 | 
			
		||||
 | 
			
		||||
use std::env;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use std::convert::TryFrom;
 | 
			
		||||
 | 
			
		||||
use super::{ Error, LoadError };
 | 
			
		||||
use super::parsing;
 | 
			
		||||
 | 
			
		||||
use ::layout::ArrangementKind;
 | 
			
		||||
use ::logging;
 | 
			
		||||
use ::util::c::as_str;
 | 
			
		||||
use ::xdg;
 | 
			
		||||
use ::imservice::ContentPurpose;
 | 
			
		||||
 | 
			
		||||
// traits, derives
 | 
			
		||||
use ::logging::Warn;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use std::os::raw::c_char;
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_load_layout(
 | 
			
		||||
        name: *const c_char,    // name of the keyboard
 | 
			
		||||
        type_: u32,             // type like Wide
 | 
			
		||||
        variant: u32,          // purpose variant like numeric, terminal...
 | 
			
		||||
        overlay: *const c_char, // the overlay (looking for "terminal")
 | 
			
		||||
    ) -> *mut ::layout::Layout {
 | 
			
		||||
        let type_ = match type_ {
 | 
			
		||||
            0 => ArrangementKind::Base,
 | 
			
		||||
            1 => ArrangementKind::Wide,
 | 
			
		||||
            _ => panic!("Bad enum value"),
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let name = as_str(&name)
 | 
			
		||||
            .expect("Bad layout name")
 | 
			
		||||
            .expect("Empty layout name");
 | 
			
		||||
 | 
			
		||||
        let variant = ContentPurpose::try_from(variant)
 | 
			
		||||
                    .or_print(
 | 
			
		||||
                        logging::Problem::Warning,
 | 
			
		||||
                        "Received invalid purpose value",
 | 
			
		||||
                    )
 | 
			
		||||
                    .unwrap_or(ContentPurpose::Normal);
 | 
			
		||||
 | 
			
		||||
        let overlay_str = as_str(&overlay)
 | 
			
		||||
                .expect("Bad overlay name")
 | 
			
		||||
                .expect("Empty overlay name");
 | 
			
		||||
        let overlay_str = match overlay_str {
 | 
			
		||||
            "" => None,
 | 
			
		||||
            other => Some(other),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let (kind, layout) = load_layout_data_with_fallback(&name, type_, variant, overlay_str);
 | 
			
		||||
        let layout = ::layout::Layout::new(layout, kind);
 | 
			
		||||
        Box::into_raw(Box::new(layout))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FALLBACK_LAYOUT_NAME: &str = "us";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
enum DataSource {
 | 
			
		||||
    File(PathBuf),
 | 
			
		||||
    Resource(String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for DataSource {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            DataSource::File(path) => write!(f, "Path: {:?}", path.display()),
 | 
			
		||||
            DataSource::Resource(name) => write!(f, "Resource: {}", name),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* All functions in this family carry around ArrangementKind,
 | 
			
		||||
 * because it's not guaranteed to be preserved,
 | 
			
		||||
 * and the resulting layout needs to know which version was loaded.
 | 
			
		||||
 * See `squeek_layout_get_kind`.
 | 
			
		||||
 * Possible TODO: since this is used only in styling,
 | 
			
		||||
 * and makes the below code nastier than needed, maybe it should go.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/// Returns ordered names treating `name` as the base name,
 | 
			
		||||
/// ignoring any `+` inside.
 | 
			
		||||
fn _get_arrangement_names(name: &str, arrangement: ArrangementKind)
 | 
			
		||||
    -> Vec<(ArrangementKind, String)>
 | 
			
		||||
{
 | 
			
		||||
    let name_with_arrangement = match arrangement {    
 | 
			
		||||
        ArrangementKind::Base => name.into(),
 | 
			
		||||
        ArrangementKind::Wide => format!("{}_wide", name),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    let mut ret = Vec::new();
 | 
			
		||||
    if name_with_arrangement != name {
 | 
			
		||||
        ret.push((arrangement, name_with_arrangement));
 | 
			
		||||
    }
 | 
			
		||||
    ret.push((ArrangementKind::Base, name.into()));
 | 
			
		||||
    ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns names accounting for any `+` in the `name`,
 | 
			
		||||
/// including the fallback to the default layout.
 | 
			
		||||
fn get_preferred_names(name: &str, kind: ArrangementKind)
 | 
			
		||||
    -> Vec<(ArrangementKind, String)>
 | 
			
		||||
{
 | 
			
		||||
    let mut ret = _get_arrangement_names(name, kind);
 | 
			
		||||
    
 | 
			
		||||
    let base_name_preferences = {
 | 
			
		||||
        let mut parts = name.splitn(2, '+');
 | 
			
		||||
        match parts.next() {
 | 
			
		||||
            Some(base) => {
 | 
			
		||||
                // The name is already equal to base, so nothing to add
 | 
			
		||||
                if base == name {
 | 
			
		||||
                    vec![]
 | 
			
		||||
                } else {
 | 
			
		||||
                    _get_arrangement_names(base, kind)
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            // The layout's base name starts with a "+". Weird but OK.
 | 
			
		||||
            None => {
 | 
			
		||||
                log_print!(logging::Level::Surprise, "Base layout name is empty: {}", name);
 | 
			
		||||
                vec![]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    ret.extend(base_name_preferences.into_iter());
 | 
			
		||||
    let fallback_names = _get_arrangement_names(FALLBACK_LAYOUT_NAME, kind);
 | 
			
		||||
    ret.extend(fallback_names.into_iter());
 | 
			
		||||
    ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Includes the subdirectory before the forward slash.
 | 
			
		||||
type LayoutPath = String;
 | 
			
		||||
 | 
			
		||||
// This is only used inside iter_fallbacks_with_meta.
 | 
			
		||||
// Placed at the top scope
 | 
			
		||||
// because `use LayoutPurpose::*;`
 | 
			
		||||
// complains about "not in scope" otherwise.
 | 
			
		||||
// This seems to be a Rust 2015 edition problem.
 | 
			
		||||
/// Helper for determining where to look up the layout.
 | 
			
		||||
enum LayoutPurpose<'a> {
 | 
			
		||||
    Default,
 | 
			
		||||
    Special(&'a str),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the directory string
 | 
			
		||||
/// where the layout should be looked up, including the slash.
 | 
			
		||||
fn get_directory_string(
 | 
			
		||||
    content_purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>) -> String
 | 
			
		||||
{
 | 
			
		||||
    use self::LayoutPurpose::*;
 | 
			
		||||
 | 
			
		||||
    let layout_purpose = match overlay {
 | 
			
		||||
        None => match content_purpose {
 | 
			
		||||
            ContentPurpose::Number => Special("number"),
 | 
			
		||||
            ContentPurpose::Digits => Special("number"),
 | 
			
		||||
            ContentPurpose::Phone => Special("number"),
 | 
			
		||||
            ContentPurpose::Terminal => Special("terminal"),
 | 
			
		||||
            _ => Default,
 | 
			
		||||
        },
 | 
			
		||||
        Some(overlay) => Special(overlay),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // For intuitiveness,
 | 
			
		||||
    // default purpose layouts are stored in the root directory,
 | 
			
		||||
    // as they correspond to typical text
 | 
			
		||||
    // and are seen the most often.
 | 
			
		||||
    match layout_purpose {
 | 
			
		||||
        Default => "".into(),
 | 
			
		||||
        Special(purpose) => format!("{}/", purpose),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns an iterator over all fallback paths.
 | 
			
		||||
fn to_layout_paths(
 | 
			
		||||
    name_fallbacks: Vec<(ArrangementKind, String)>,
 | 
			
		||||
    content_purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>,
 | 
			
		||||
) -> impl Iterator<Item=(ArrangementKind, LayoutPath)> {
 | 
			
		||||
    let prepend_directory = get_directory_string(content_purpose, overlay);
 | 
			
		||||
 | 
			
		||||
    name_fallbacks.into_iter()
 | 
			
		||||
        .map(move |(arrangement, name)|
 | 
			
		||||
            (arrangement, format!("{}{}", prepend_directory, name))
 | 
			
		||||
        )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type LayoutSource = (ArrangementKind, DataSource);
 | 
			
		||||
 | 
			
		||||
fn to_layout_sources(
 | 
			
		||||
    layout_paths: impl Iterator<Item=(ArrangementKind, LayoutPath)>,
 | 
			
		||||
    filesystem_path: Option<PathBuf>,
 | 
			
		||||
) -> impl Iterator<Item=LayoutSource> {
 | 
			
		||||
    layout_paths.flat_map(move |(arrangement, layout_path)| {
 | 
			
		||||
        let mut sources = Vec::new();
 | 
			
		||||
        if let Some(path) = &filesystem_path {
 | 
			
		||||
            sources.push((
 | 
			
		||||
                arrangement,
 | 
			
		||||
                DataSource::File(
 | 
			
		||||
                    path.join(&layout_path)
 | 
			
		||||
                        .with_extension("yaml")
 | 
			
		||||
                )
 | 
			
		||||
            ));
 | 
			
		||||
        };
 | 
			
		||||
        sources.push((arrangement, DataSource::Resource(layout_path.clone())));
 | 
			
		||||
        sources.into_iter()
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns possible sources, with first as the most preferred one.
 | 
			
		||||
/// Trying order: native lang of the right kind, native base,
 | 
			
		||||
/// fallback lang of the right kind, fallback base
 | 
			
		||||
fn iter_layout_sources(
 | 
			
		||||
    name: &str,
 | 
			
		||||
    arrangement: ArrangementKind,
 | 
			
		||||
    purpose: ContentPurpose,
 | 
			
		||||
    ui_overlay: Option<&str>,
 | 
			
		||||
    layout_storage: Option<PathBuf>,
 | 
			
		||||
) -> impl Iterator<Item=LayoutSource> {
 | 
			
		||||
    let names = get_preferred_names(name, arrangement);
 | 
			
		||||
    let paths = to_layout_paths(names, purpose, ui_overlay);
 | 
			
		||||
    to_layout_sources(paths, layout_storage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_layout_data(source: DataSource)
 | 
			
		||||
    -> Result<::layout::LayoutData, LoadError>
 | 
			
		||||
{
 | 
			
		||||
    let handler = logging::Print {};
 | 
			
		||||
    match source {
 | 
			
		||||
        DataSource::File(path) => {
 | 
			
		||||
            parsing::Layout::from_file(path.clone())
 | 
			
		||||
                .map_err(LoadError::BadData)
 | 
			
		||||
                .and_then(|layout|
 | 
			
		||||
                    layout.build(handler).0.map_err(LoadError::BadKeyMap)
 | 
			
		||||
                )
 | 
			
		||||
        },
 | 
			
		||||
        DataSource::Resource(name) => {
 | 
			
		||||
            parsing::Layout::from_resource(&name)
 | 
			
		||||
                .and_then(|layout|
 | 
			
		||||
                    layout.build(handler).0.map_err(LoadError::BadKeyMap)
 | 
			
		||||
                )
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_layout_data_with_fallback(
 | 
			
		||||
    name: &str,
 | 
			
		||||
    kind: ArrangementKind,
 | 
			
		||||
    purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>,
 | 
			
		||||
) -> (ArrangementKind, ::layout::LayoutData) {
 | 
			
		||||
 | 
			
		||||
    // Build the path to the right keyboard layout subdirectory
 | 
			
		||||
    let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR")
 | 
			
		||||
        .map(PathBuf::from)
 | 
			
		||||
        .or_else(|| xdg::data_path("squeekboard/keyboards"));
 | 
			
		||||
 | 
			
		||||
    for (kind, source) in iter_layout_sources(&name, kind, purpose, overlay, path) {
 | 
			
		||||
        let layout = load_layout_data(source.clone());
 | 
			
		||||
        match layout {
 | 
			
		||||
            Err(e) => match (e, source) {
 | 
			
		||||
                (
 | 
			
		||||
                    LoadError::BadData(Error::Missing(e)),
 | 
			
		||||
                    DataSource::File(file)
 | 
			
		||||
                ) => log_print!(
 | 
			
		||||
                    logging::Level::Debug,
 | 
			
		||||
                    "Tried file {:?}, but it's missing: {}",
 | 
			
		||||
                    file, e
 | 
			
		||||
                ),
 | 
			
		||||
                (e, source) => log_print!(
 | 
			
		||||
                    logging::Level::Warning,
 | 
			
		||||
                    "Failed to load layout from {}: {}, skipping",
 | 
			
		||||
                    source, e
 | 
			
		||||
                ),
 | 
			
		||||
            },
 | 
			
		||||
            Ok(layout) => {
 | 
			
		||||
                log_print!(logging::Level::Info, "Loaded layout {}", source);
 | 
			
		||||
                return (kind, layout);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    panic!("No useful layout found!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    use ::logging::ProblemPanic;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn parsing_fallback() {
 | 
			
		||||
        assert!(parsing::Layout::from_resource(FALLBACK_LAYOUT_NAME)
 | 
			
		||||
            .map(|layout| layout.build(ProblemPanic).0.unwrap())
 | 
			
		||||
            .is_ok()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_fallback_basic_builtin() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, None);
 | 
			
		||||
        
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Prefer loading from file system before builtin.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_path() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, Some(".".into()));
 | 
			
		||||
        
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::File("./nb.yaml".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::File("./us.yaml".into())
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// If layout contains a "+", it should reach for what's in front of it too.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_base() {
 | 
			
		||||
        let sources = iter_layout_sources("nb+aliens", ArrangementKind::Base, ContentPurpose::Normal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb+aliens".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_arrangement() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Wide, ContentPurpose::Normal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Wide, DataSource::Resource("nb_wide".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Wide,
 | 
			
		||||
                    DataSource::Resource("us_wide".into())
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_overlay() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, Some("terminal"), None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("terminal/us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_hint() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Terminal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("terminal/us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										65
									
								
								src/data/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/data/mod.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
			
		||||
/* Copyright (C) 2020-2021 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*! Combined module for dealing with layout files */
 | 
			
		||||
 | 
			
		||||
mod loading;
 | 
			
		||||
pub mod parsing;
 | 
			
		||||
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
 | 
			
		||||
use ::keyboard::FormattingError;
 | 
			
		||||
 | 
			
		||||
/// Errors encountered loading the layout into yaml
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum Error {
 | 
			
		||||
    Yaml(serde_yaml::Error),
 | 
			
		||||
    Io(io::Error),
 | 
			
		||||
    /// The file was missing.
 | 
			
		||||
    /// It's distinct from Io in order to make it matchable
 | 
			
		||||
    /// without calling io::Error::kind()
 | 
			
		||||
    Missing(io::Error),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for Error {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Error::Yaml(e) => write!(f, "YAML: {}", e),
 | 
			
		||||
            Error::Io(e) => write!(f, "IO: {}", e),
 | 
			
		||||
            Error::Missing(e) => write!(f, "Missing: {}", e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<io::Error> for Error {
 | 
			
		||||
    fn from(e: io::Error) -> Self {
 | 
			
		||||
        let kind = e.kind();
 | 
			
		||||
        match kind {
 | 
			
		||||
            io::ErrorKind::NotFound => Error::Missing(e),
 | 
			
		||||
            _ => Error::Io(e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum LoadError {
 | 
			
		||||
    BadData(Error),
 | 
			
		||||
    MissingResource,
 | 
			
		||||
    BadResource(serde_yaml::Error),
 | 
			
		||||
    BadKeyMap(FormattingError),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for LoadError {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        use self::LoadError::*;
 | 
			
		||||
        match self {
 | 
			
		||||
            BadData(e) => write!(f, "Bad data: {}", e),
 | 
			
		||||
            MissingResource => write!(f, "Missing resource"),
 | 
			
		||||
            BadResource(e) => write!(f, "Bad resource: {}", e),
 | 
			
		||||
            BadKeyMap(e) => write!(f, "Bad key map: {}", e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,34 +1,30 @@
 | 
			
		||||
/**! The parsing of the data files for layouts */
 | 
			
		||||
/* Copyright (C) 2020-2021 Purism SPC
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0+
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// TODO: find a nice way to make sure non-positive sizes don't break layouts
 | 
			
		||||
/*! Parsing of the data files containing layouts */
 | 
			
		||||
 | 
			
		||||
use std::cell::RefCell;
 | 
			
		||||
use std::collections::{ HashMap, HashSet };
 | 
			
		||||
use std::env;
 | 
			
		||||
use std::ffi::CString;
 | 
			
		||||
use std::fmt;
 | 
			
		||||
use std::fs;
 | 
			
		||||
use std::io;
 | 
			
		||||
use std::path::PathBuf;
 | 
			
		||||
use std::rc::Rc;
 | 
			
		||||
use std::vec::Vec;
 | 
			
		||||
use std::convert::TryFrom;
 | 
			
		||||
 | 
			
		||||
use xkbcommon::xkb;
 | 
			
		||||
 | 
			
		||||
use super::{ Error, LoadError };
 | 
			
		||||
 | 
			
		||||
use ::action;
 | 
			
		||||
use ::keyboard::{
 | 
			
		||||
    KeyState, PressType,
 | 
			
		||||
    generate_keymaps, generate_keycodes, KeyCode, FormattingError
 | 
			
		||||
};
 | 
			
		||||
use ::layout;
 | 
			
		||||
use ::layout::ArrangementKind;
 | 
			
		||||
use ::logging;
 | 
			
		||||
use ::resources;
 | 
			
		||||
use ::util::c::as_str;
 | 
			
		||||
use ::util::hash_map_map;
 | 
			
		||||
use ::xdg;
 | 
			
		||||
use ::imservice::ContentPurpose;
 | 
			
		||||
use ::resources;
 | 
			
		||||
 | 
			
		||||
// traits, derives
 | 
			
		||||
use serde::Deserialize;
 | 
			
		||||
@ -36,299 +32,7 @@ use std::io::BufReader;
 | 
			
		||||
use std::iter::FromIterator;
 | 
			
		||||
use ::logging::Warn;
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use std::os::raw::c_char;
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_load_layout(
 | 
			
		||||
        name: *const c_char,    // name of the keyboard
 | 
			
		||||
        type_: u32,             // type like Wide
 | 
			
		||||
        variant: u32,          // purpose variant like numeric, terminal...
 | 
			
		||||
        overlay: *const c_char, // the overlay (looking for "terminal")
 | 
			
		||||
    ) -> *mut ::layout::Layout {
 | 
			
		||||
        let type_ = match type_ {
 | 
			
		||||
            0 => ArrangementKind::Base,
 | 
			
		||||
            1 => ArrangementKind::Wide,
 | 
			
		||||
            _ => panic!("Bad enum value"),
 | 
			
		||||
        };
 | 
			
		||||
        
 | 
			
		||||
        let name = as_str(&name)
 | 
			
		||||
            .expect("Bad layout name")
 | 
			
		||||
            .expect("Empty layout name");
 | 
			
		||||
 | 
			
		||||
        let variant = ContentPurpose::try_from(variant)
 | 
			
		||||
                    .or_print(
 | 
			
		||||
                        logging::Problem::Warning,
 | 
			
		||||
                        "Received invalid purpose value",
 | 
			
		||||
                    )
 | 
			
		||||
                    .unwrap_or(ContentPurpose::Normal);
 | 
			
		||||
 | 
			
		||||
        let overlay_str = as_str(&overlay)
 | 
			
		||||
                .expect("Bad overlay name")
 | 
			
		||||
                .expect("Empty overlay name");
 | 
			
		||||
        let overlay_str = match overlay_str {
 | 
			
		||||
            "" => None,
 | 
			
		||||
            other => Some(other),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let (kind, layout) = load_layout_data_with_fallback(&name, type_, variant, overlay_str);
 | 
			
		||||
        let layout = ::layout::Layout::new(layout, kind);
 | 
			
		||||
        Box::into_raw(Box::new(layout))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FALLBACK_LAYOUT_NAME: &str = "us";
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum LoadError {
 | 
			
		||||
    BadData(Error),
 | 
			
		||||
    MissingResource,
 | 
			
		||||
    BadResource(serde_yaml::Error),
 | 
			
		||||
    BadKeyMap(FormattingError),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for LoadError {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        use self::LoadError::*;
 | 
			
		||||
        match self {
 | 
			
		||||
            BadData(e) => write!(f, "Bad data: {}", e),
 | 
			
		||||
            MissingResource => write!(f, "Missing resource"),
 | 
			
		||||
            BadResource(e) => write!(f, "Bad resource: {}", e),
 | 
			
		||||
            BadKeyMap(e) => write!(f, "Bad key map: {}", e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
enum DataSource {
 | 
			
		||||
    File(PathBuf),
 | 
			
		||||
    Resource(String),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for DataSource {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            DataSource::File(path) => write!(f, "Path: {:?}", path.display()),
 | 
			
		||||
            DataSource::Resource(name) => write!(f, "Resource: {}", name),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* All functions in this family carry around ArrangementKind,
 | 
			
		||||
 * because it's not guaranteed to be preserved,
 | 
			
		||||
 * and the resulting layout needs to know which version was loaded.
 | 
			
		||||
 * See `squeek_layout_get_kind`.
 | 
			
		||||
 * Possible TODO: since this is used only in styling,
 | 
			
		||||
 * and makes the below code nastier than needed, maybe it should go.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/// Returns ordered names treating `name` as the base name,
 | 
			
		||||
/// ignoring any `+` inside.
 | 
			
		||||
fn _get_arrangement_names(name: &str, arrangement: ArrangementKind)
 | 
			
		||||
    -> Vec<(ArrangementKind, String)>
 | 
			
		||||
{
 | 
			
		||||
    let name_with_arrangement = match arrangement {    
 | 
			
		||||
        ArrangementKind::Base => name.into(),
 | 
			
		||||
        ArrangementKind::Wide => format!("{}_wide", name),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    let mut ret = Vec::new();
 | 
			
		||||
    if name_with_arrangement != name {
 | 
			
		||||
        ret.push((arrangement, name_with_arrangement));
 | 
			
		||||
    }
 | 
			
		||||
    ret.push((ArrangementKind::Base, name.into()));
 | 
			
		||||
    ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns names accounting for any `+` in the `name`,
 | 
			
		||||
/// including the fallback to the default layout.
 | 
			
		||||
fn get_preferred_names(name: &str, kind: ArrangementKind)
 | 
			
		||||
    -> Vec<(ArrangementKind, String)>
 | 
			
		||||
{
 | 
			
		||||
    let mut ret = _get_arrangement_names(name, kind);
 | 
			
		||||
    
 | 
			
		||||
    let base_name_preferences = {
 | 
			
		||||
        let mut parts = name.splitn(2, '+');
 | 
			
		||||
        match parts.next() {
 | 
			
		||||
            Some(base) => {
 | 
			
		||||
                // The name is already equal to base, so nothing to add
 | 
			
		||||
                if base == name {
 | 
			
		||||
                    vec![]
 | 
			
		||||
                } else {
 | 
			
		||||
                    _get_arrangement_names(base, kind)
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            // The layout's base name starts with a "+". Weird but OK.
 | 
			
		||||
            None => {
 | 
			
		||||
                log_print!(logging::Level::Surprise, "Base layout name is empty: {}", name);
 | 
			
		||||
                vec![]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    ret.extend(base_name_preferences.into_iter());
 | 
			
		||||
    let fallback_names = _get_arrangement_names(FALLBACK_LAYOUT_NAME, kind);
 | 
			
		||||
    ret.extend(fallback_names.into_iter());
 | 
			
		||||
    ret
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Includes the subdirectory before the forward slash.
 | 
			
		||||
type LayoutPath = String;
 | 
			
		||||
 | 
			
		||||
// This is only used inside iter_fallbacks_with_meta.
 | 
			
		||||
// Placed at the top scope
 | 
			
		||||
// because `use LayoutPurpose::*;`
 | 
			
		||||
// complains about "not in scope" otherwise.
 | 
			
		||||
// This seems to be a Rust 2015 edition problem.
 | 
			
		||||
/// Helper for determining where to look up the layout.
 | 
			
		||||
enum LayoutPurpose<'a> {
 | 
			
		||||
    Default,
 | 
			
		||||
    Special(&'a str),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns the directory string
 | 
			
		||||
/// where the layout should be looked up, including the slash.
 | 
			
		||||
fn get_directory_string(
 | 
			
		||||
    content_purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>) -> String
 | 
			
		||||
{
 | 
			
		||||
    use self::LayoutPurpose::*;
 | 
			
		||||
 | 
			
		||||
    let layout_purpose = match overlay {
 | 
			
		||||
        None => match content_purpose {
 | 
			
		||||
            ContentPurpose::Number => Special("number"),
 | 
			
		||||
            ContentPurpose::Digits => Special("number"),
 | 
			
		||||
            ContentPurpose::Phone => Special("number"),
 | 
			
		||||
            ContentPurpose::Terminal => Special("terminal"),
 | 
			
		||||
            _ => Default,
 | 
			
		||||
        },
 | 
			
		||||
        Some(overlay) => Special(overlay),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // For intuitiveness,
 | 
			
		||||
    // default purpose layouts are stored in the root directory,
 | 
			
		||||
    // as they correspond to typical text
 | 
			
		||||
    // and are seen the most often.
 | 
			
		||||
    match layout_purpose {
 | 
			
		||||
        Default => "".into(),
 | 
			
		||||
        Special(purpose) => format!("{}/", purpose),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns an iterator over all fallback paths.
 | 
			
		||||
fn to_layout_paths(
 | 
			
		||||
    name_fallbacks: Vec<(ArrangementKind, String)>,
 | 
			
		||||
    content_purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>,
 | 
			
		||||
) -> impl Iterator<Item=(ArrangementKind, LayoutPath)> {
 | 
			
		||||
    let prepend_directory = get_directory_string(content_purpose, overlay);
 | 
			
		||||
 | 
			
		||||
    name_fallbacks.into_iter()
 | 
			
		||||
        .map(move |(arrangement, name)|
 | 
			
		||||
            (arrangement, format!("{}{}", prepend_directory, name))
 | 
			
		||||
        )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type LayoutSource = (ArrangementKind, DataSource);
 | 
			
		||||
 | 
			
		||||
fn to_layout_sources(
 | 
			
		||||
    layout_paths: impl Iterator<Item=(ArrangementKind, LayoutPath)>,
 | 
			
		||||
    filesystem_path: Option<PathBuf>,
 | 
			
		||||
) -> impl Iterator<Item=LayoutSource> {
 | 
			
		||||
    layout_paths.flat_map(move |(arrangement, layout_path)| {
 | 
			
		||||
        let mut sources = Vec::new();
 | 
			
		||||
        if let Some(path) = &filesystem_path {
 | 
			
		||||
            sources.push((
 | 
			
		||||
                arrangement,
 | 
			
		||||
                DataSource::File(
 | 
			
		||||
                    path.join(&layout_path)
 | 
			
		||||
                        .with_extension("yaml")
 | 
			
		||||
                )
 | 
			
		||||
            ));
 | 
			
		||||
        };
 | 
			
		||||
        sources.push((arrangement, DataSource::Resource(layout_path.clone())));
 | 
			
		||||
        sources.into_iter()
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Returns possible sources, with first as the most preferred one.
 | 
			
		||||
/// Trying order: native lang of the right kind, native base,
 | 
			
		||||
/// fallback lang of the right kind, fallback base
 | 
			
		||||
fn iter_layout_sources(
 | 
			
		||||
    name: &str,
 | 
			
		||||
    arrangement: ArrangementKind,
 | 
			
		||||
    purpose: ContentPurpose,
 | 
			
		||||
    ui_overlay: Option<&str>,
 | 
			
		||||
    layout_storage: Option<PathBuf>,
 | 
			
		||||
) -> impl Iterator<Item=LayoutSource> {
 | 
			
		||||
    let names = get_preferred_names(name, arrangement);
 | 
			
		||||
    let paths = to_layout_paths(names, purpose, ui_overlay);
 | 
			
		||||
    to_layout_sources(paths, layout_storage)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_layout_data(source: DataSource)
 | 
			
		||||
    -> Result<::layout::LayoutData, LoadError>
 | 
			
		||||
{
 | 
			
		||||
    let handler = logging::Print {};
 | 
			
		||||
    match source {
 | 
			
		||||
        DataSource::File(path) => {
 | 
			
		||||
            Layout::from_file(path.clone())
 | 
			
		||||
                .map_err(LoadError::BadData)
 | 
			
		||||
                .and_then(|layout|
 | 
			
		||||
                    layout.build(handler).0.map_err(LoadError::BadKeyMap)
 | 
			
		||||
                )
 | 
			
		||||
        },
 | 
			
		||||
        DataSource::Resource(name) => {
 | 
			
		||||
            Layout::from_resource(&name)
 | 
			
		||||
                .and_then(|layout|
 | 
			
		||||
                    layout.build(handler).0.map_err(LoadError::BadKeyMap)
 | 
			
		||||
                )
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn load_layout_data_with_fallback(
 | 
			
		||||
    name: &str,
 | 
			
		||||
    kind: ArrangementKind,
 | 
			
		||||
    purpose: ContentPurpose,
 | 
			
		||||
    overlay: Option<&str>,
 | 
			
		||||
) -> (ArrangementKind, ::layout::LayoutData) {
 | 
			
		||||
 | 
			
		||||
    // Build the path to the right keyboard layout subdirectory
 | 
			
		||||
    let path = env::var_os("SQUEEKBOARD_KEYBOARDSDIR")
 | 
			
		||||
        .map(PathBuf::from)
 | 
			
		||||
        .or_else(|| xdg::data_path("squeekboard/keyboards"));
 | 
			
		||||
 | 
			
		||||
    for (kind, source) in iter_layout_sources(&name, kind, purpose, overlay, path) {
 | 
			
		||||
        let layout = load_layout_data(source.clone());
 | 
			
		||||
        match layout {
 | 
			
		||||
            Err(e) => match (e, source) {
 | 
			
		||||
                (
 | 
			
		||||
                    LoadError::BadData(Error::Missing(e)),
 | 
			
		||||
                    DataSource::File(file)
 | 
			
		||||
                ) => log_print!(
 | 
			
		||||
                    logging::Level::Debug,
 | 
			
		||||
                    "Tried file {:?}, but it's missing: {}",
 | 
			
		||||
                    file, e
 | 
			
		||||
                ),
 | 
			
		||||
                (e, source) => log_print!(
 | 
			
		||||
                    logging::Level::Warning,
 | 
			
		||||
                    "Failed to load layout from {}: {}, skipping",
 | 
			
		||||
                    source, e
 | 
			
		||||
                ),
 | 
			
		||||
            },
 | 
			
		||||
            Ok(layout) => {
 | 
			
		||||
                log_print!(logging::Level::Info, "Loaded layout {}", source);
 | 
			
		||||
                return (kind, layout);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    panic!("No useful layout found!");
 | 
			
		||||
}
 | 
			
		||||
// TODO: find a nice way to make sure non-positive sizes don't break layouts
 | 
			
		||||
 | 
			
		||||
/// The root element describing an entire keyboard
 | 
			
		||||
#[derive(Debug, Deserialize, PartialEq)]
 | 
			
		||||
@ -421,37 +125,6 @@ struct Outline {
 | 
			
		||||
    height: f64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Errors encountered loading the layout into yaml
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub enum Error {
 | 
			
		||||
    Yaml(serde_yaml::Error),
 | 
			
		||||
    Io(io::Error),
 | 
			
		||||
    /// The file was missing.
 | 
			
		||||
    /// It's distinct from Io in order to make it matchable
 | 
			
		||||
    /// without calling io::Error::kind()
 | 
			
		||||
    Missing(io::Error),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl fmt::Display for Error {
 | 
			
		||||
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 | 
			
		||||
        match self {
 | 
			
		||||
            Error::Yaml(e) => write!(f, "YAML: {}", e),
 | 
			
		||||
            Error::Io(e) => write!(f, "IO: {}", e),
 | 
			
		||||
            Error::Missing(e) => write!(f, "Missing: {}", e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl From<io::Error> for Error {
 | 
			
		||||
    fn from(e: io::Error) -> Self {
 | 
			
		||||
        let kind = e.kind();
 | 
			
		||||
        match kind {
 | 
			
		||||
            io::ErrorKind::NotFound => Error::Missing(e),
 | 
			
		||||
            _ => Error::Io(e),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn add_offsets<'a, I: 'a, T, F: 'a>(iterator: I, get_size: F)
 | 
			
		||||
    -> impl Iterator<Item=(f64, T)> + 'a
 | 
			
		||||
    where I: Iterator<Item=T>,
 | 
			
		||||
@ -871,10 +544,13 @@ fn extract_symbol_names<'a>(actions: &'a [(&str, action::Action)])
 | 
			
		||||
        .map(|named_keysym| named_keysym.0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    use std::env;
 | 
			
		||||
    
 | 
			
		||||
    use ::logging::ProblemPanic;
 | 
			
		||||
 | 
			
		||||
    fn path_from_root(file: &'static str) -> PathBuf {
 | 
			
		||||
@ -1024,124 +700,6 @@ mod tests {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn parsing_fallback() {
 | 
			
		||||
        assert!(Layout::from_resource(FALLBACK_LAYOUT_NAME)
 | 
			
		||||
            .map(|layout| layout.build(ProblemPanic).0.unwrap())
 | 
			
		||||
            .is_ok()
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// First fallback should be to builtin, not to FALLBACK_LAYOUT_NAME
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_fallback_basic_builtin() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, None);
 | 
			
		||||
        
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Prefer loading from file system before builtin.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_path() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, None, Some(".".into()));
 | 
			
		||||
        
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::File("./nb.yaml".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::File("./us.yaml".into())
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// If layout contains a "+", it should reach for what's in front of it too.
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_base() {
 | 
			
		||||
        let sources = iter_layout_sources("nb+aliens", ArrangementKind::Base, ContentPurpose::Normal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb+aliens".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource(FALLBACK_LAYOUT_NAME.into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_arrangement() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Wide, ContentPurpose::Normal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Wide, DataSource::Resource("nb_wide".into())),
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Wide,
 | 
			
		||||
                    DataSource::Resource("us_wide".into())
 | 
			
		||||
                ),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_overlay() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Normal, Some("terminal"), None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("terminal/us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_preferences_order_hint() {
 | 
			
		||||
        let sources = iter_layout_sources("nb", ArrangementKind::Base, ContentPurpose::Terminal, None, None);
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            sources.collect::<Vec<_>>(),
 | 
			
		||||
            vec!(
 | 
			
		||||
                (ArrangementKind::Base, DataSource::Resource("terminal/nb".into())),
 | 
			
		||||
                (
 | 
			
		||||
                    ArrangementKind::Base,
 | 
			
		||||
                    DataSource::Resource("terminal/us".into())
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn unicode_keysym() {
 | 
			
		||||
        let keysym = xkb::keysym_from_name(
 | 
			
		||||
@ -621,12 +621,6 @@ pub enum LatchedState {
 | 
			
		||||
    Not,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl LatchedState {
 | 
			
		||||
    pub fn is_latched(&self) -> bool {
 | 
			
		||||
        self != &LatchedState::Not
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TODO: split into sth like
 | 
			
		||||
// Arrangement (views) + details (keymap) + State (keys)
 | 
			
		||||
/// State of the UI, contains the backend as well
 | 
			
		||||
@ -776,23 +770,6 @@ impl Layout {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_locked_keys(&self) -> Vec<Rc<RefCell<KeyState>>> {
 | 
			
		||||
        let mut out = Vec::new();
 | 
			
		||||
        let view = self.get_current_view();
 | 
			
		||||
        for (_, row) in view.get_rows() {
 | 
			
		||||
            for (_, button) in &row.buttons {
 | 
			
		||||
                let locked = {
 | 
			
		||||
                    let state = RefCell::borrow(&button.state).clone();
 | 
			
		||||
                    state.action.is_locked(&self.current_view)
 | 
			
		||||
                };
 | 
			
		||||
                if locked {
 | 
			
		||||
                    out.push(button.state.clone());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        out
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn apply_view_transition(
 | 
			
		||||
        &mut self,
 | 
			
		||||
 | 
			
		||||
@ -401,6 +401,7 @@ pub fn show(
 | 
			
		||||
        width: position.width.floor() as i32,
 | 
			
		||||
        height: position.width.floor() as i32,
 | 
			
		||||
    });
 | 
			
		||||
    menu.set_constrain_to(gtk::PopoverConstraint::None);
 | 
			
		||||
 | 
			
		||||
    if let Some(current_layout) = get_current_layout(manager, &system_layouts) {
 | 
			
		||||
        let current_name_variant = choices.iter()
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ use std::iter::FromIterator;
 | 
			
		||||
// and what a convenience layout. "_wide" is not a layout,
 | 
			
		||||
// neither is "number"
 | 
			
		||||
/// List of builtin layouts
 | 
			
		||||
const KEYBOARDS: &[(*const str, *const str)] = &[
 | 
			
		||||
static KEYBOARDS: &[(&'static str, &'static str)] = &[
 | 
			
		||||
    // layouts: us must be left as first, as it is the,
 | 
			
		||||
    // fallback layout.
 | 
			
		||||
    ("us", include_str!("../data/keyboards/us.yaml")),
 | 
			
		||||
@ -93,34 +93,20 @@ const KEYBOARDS: &[(*const str, *const str)] = &[
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
pub fn get_keyboard(needle: &str) -> Option<&'static str> {
 | 
			
		||||
    // Need to dereference in unsafe code
 | 
			
		||||
    // comparing *const str to &str will compare pointers
 | 
			
		||||
    KEYBOARDS.iter()
 | 
			
		||||
        .find(|(name, _)| {
 | 
			
		||||
            let name: *const str = *name;
 | 
			
		||||
            (unsafe { &*name }) == needle
 | 
			
		||||
        })
 | 
			
		||||
        .map(|(_, value)| {
 | 
			
		||||
            let value: *const str = *value;
 | 
			
		||||
            unsafe { &*value }
 | 
			
		||||
        })
 | 
			
		||||
    KEYBOARDS.iter().find(|(name, _)| *name == needle).map(|(_, layout)| *layout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const OVERLAY_NAMES: &[*const str] = &[
 | 
			
		||||
static OVERLAY_NAMES: &[&'static str] = &[
 | 
			
		||||
    "emoji",
 | 
			
		||||
    "terminal",
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
pub fn get_overlays() -> Vec<&'static str> {
 | 
			
		||||
    OVERLAY_NAMES.iter()
 | 
			
		||||
        .map(|name| {
 | 
			
		||||
            let name: *const str = *name;
 | 
			
		||||
            unsafe { &*name }
 | 
			
		||||
        }).collect()
 | 
			
		||||
    OVERLAY_NAMES.to_vec()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Translations of the layout identifier strings
 | 
			
		||||
const LAYOUT_NAMES: &[(*const str, *const str)] = &[
 | 
			
		||||
static LAYOUT_NAMES: &[(&'static str, &'static str)] = &[
 | 
			
		||||
    ("de-DE", include_str!("../data/langs/de-DE.txt")),
 | 
			
		||||
    ("en-US", include_str!("../data/langs/en-US.txt")),
 | 
			
		||||
    ("es-ES", include_str!("../data/langs/es-ES.txt")),
 | 
			
		||||
@ -135,14 +121,8 @@ pub fn get_layout_names(lang: &str)
 | 
			
		||||
    -> Option<HashMap<&'static str, Translation<'static>>>
 | 
			
		||||
{
 | 
			
		||||
    let translations = LAYOUT_NAMES.iter()
 | 
			
		||||
        .find(|(name, _data)| {
 | 
			
		||||
            let name: *const str = *name;
 | 
			
		||||
            (unsafe { &*name }) == lang
 | 
			
		||||
        })
 | 
			
		||||
        .map(|(_name, data)| {
 | 
			
		||||
            let data: *const str = *data;
 | 
			
		||||
            unsafe { &*data }
 | 
			
		||||
        });
 | 
			
		||||
        .find(|(name, _data)| *name == lang)
 | 
			
		||||
        .map(|(_name, data)| *data);
 | 
			
		||||
    translations.map(make_mapping)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
/*! Testing functionality */
 | 
			
		||||
 | 
			
		||||
use ::data::Layout;
 | 
			
		||||
use ::data::parsing::Layout;
 | 
			
		||||
use ::logging;
 | 
			
		||||
use xkbcommon::xkb;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user