Compare commits

...

131 Commits

Author SHA1 Message Date
735ce62e8b shadow: Don't attempt to create a shadow for unallocated actors
Calling clutter_actor_get_allocation_box() can potentially cause a
re-layout, which in _st_create_shadow_pipeline_from_actor() would
mean invalidating the shadow_spec passed as a parameter, which
could crash the shell later on since the value for shadow_spec->blur
passed from _st_create_shadow_pipeline() to blur_pixels() would
not be a valid one.

Thus, whether the ClutterActor has an allocation before calling
clutter_actor_get_allocation_box(), and early return if needed.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/36

Closes: #36
2018-02-09 12:22:58 +00:00
cc028dd55a st-icon: Null-check for shadow_spec before trying to paint a shadow
The value of priv->shadow_spec can be NULL at the time an icon is
going to be paint (e.g. because of a change in style), so we need
to check it's a valid one before using it in st_icon_paint(), as
it's already being done in other parts of the code.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/36

Closes: #36
2018-02-09 12:22:13 +00:00
fc5b1591ad Update Galician translation 2018-02-09 11:16:55 +00:00
d63c0e277c altTab: Add also a shortcut to close windows from the switcher popups
Similar to what has been done for the apps switcher, this allows closing
windows pressing W or F4 while operating the windows switcher popup or
the apps switcher popup while navigating the list of windows for an app.

https://bugzilla.gnome.org/show_bug.cgi?id=620106
2018-02-09 09:26:50 +00:00
06f790d86c switcherPopup: Handle removal of items from SwitcherPopup
This will be mainly useful for closing apps from the applications
switcher, but can be implemented generically enough to select the
nearest existing item after removal if there's any, or destroying
the popup's actor otherwise.

Specifically for the apps switcher, doing this also removes the need
of having to manually either update the current app in AppSwitcher
and highlight it, if there are still any items after the removal, or
simply destroy the AppSwitcher otherwise. Besides, calling _select()
in the handler for item-removed makes sure that the list of thumbnails
in the switcher is always closed, if open, when quitting the app.

https://bugzilla.gnome.org/show_bug.cgi?id=620106
2018-02-09 09:26:50 +00:00
a3918d8c38 altTab: Add shortcut to quit application
Allow to quit the currently selected application by hitting Alt-q,
similar to the OS X switcher.

https://bugzilla.gnome.org/show_bug.cgi?id=620106
2018-02-09 09:26:50 +00:00
5122b06839 altTab: Update the switcher when apps and/or windows get stopped/closed
Make sure that the items from the applications switcher and the windows
switcher are removed when the related applications get stopped, or some
of the associated windows closed.

https://bugzilla.gnome.org/show_bug.cgi?id=620106
2018-02-09 09:26:49 +00:00
f2d12e22b5 Update Polish translation 2018-02-08 23:59:32 +01:00
a647445b95 calendar Preparing for genitive/nominative months
glibc 2.27 introduced new format specifiers for the month names.
It's obligatory to use them in several languages already and it's
encouraged to use them for all languages because it is not destructive
for any language. As more languages are expected to follow this
standard it's better to use the "%OB" format specifier now so it will
start working correctly automatically.
See also: https://sourceware.org/bugzilla/show_bug.cgi?id=10871

This standard has been also working in BSD and OS X since 1990s,
if anyone tries to use gnome-shell in these systems.

Note: This will not work correctly with glibc < 2.27, there is no
detection whether the system is old or new.

https://bugzilla.gnome.org/show_bug.cgi?id=780957
2018-02-08 12:48:31 +01:00
9dbe10889b calendar: Make month and month-year formats translatable
Don't try to figure out the month-year order from gtk+.
Provide the format for the translators.  This is easier
and more versatile.

https://bugzilla.gnome.org/show_bug.cgi?id=781329
2018-02-08 12:39:00 +01:00
5f6aace8aa Update Polish translation 2018-02-08 01:30:27 +01:00
f2e2af962d panel: Fix active button style on solid panel
Fix regression from bug 747163

https://bugzilla.gnome.org/show_bug.cgi?id=792616
2018-02-07 17:40:46 +01:00
6f0c187cf4 shell-recorder: save cursor's image hot x/y coordinates
Whenever a new cursor image is loaded also save it's hot x/y
coordinates. The drawing code already respects these values, however
they were never set. This change will place the cursor image at the
correct location as seen on screen. shell-screenshot.c served as
reference.

https://bugzilla.gnome.org/show_bug.cgi?id=792860
2018-02-07 13:16:36 +01:00
d3a3b7f514 screenShield: Do not save lock state on wayland
We keep track of the lock state and restore it on startup to prevent
a crash from bypassing the screen lock. However on wayland, a crash
doesn't result in gnome-session restarting gnome-shell, but brings
down the entire session - that is, restoring the lock state does not
actually protect the existing session in that case, but forces the
user to authenticate twice in order to start the next session. This
is clearly not helpful, so avoid this by not saving the state when
running as wayland compositor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/17
2018-02-07 04:35:57 +00:00
80ad471812 Update Finnish translation 2018-02-06 21:42:17 +00:00
0206a579c2 Update Friulian translation 2018-02-06 21:38:47 +00:00
86b853b23a Update Spanish translation 2018-02-06 12:27:31 +00:00
cd0af33947 panel: center date entry with workarea
Align and center the date entry with the workspace's workarea.
This way, maximized applications have their window aligned with the top date
entry.
This doesn't change anything for desktops with no docks or when left/right
workareas are aligned with the monitor.

The offset is leftOffset - rightOffset:
(workArea.x - monitor.x) - (monitor.width - ((workArea.x - monitor.x) +
                                              workArea.width))

https://bugzilla.gnome.org/show_bug.cgi?id=792354
2018-02-06 11:19:58 +01:00
0b51ead004 Update POTFILES.in 2018-02-06 02:15:20 +01:00
d6107a60e4 Update Swedish translation 2018-02-05 22:42:48 +00:00
194040dcb2 thunderbolt: add policy provider and indicator
We will now basically act as "policy provider" for thunderbolt
peripherals by using org.freedesktop.bolt service: when new
devices are connect and session is a unlocked user session
we will automatically enroll (authorize and store in the database)
them.
If new devices are connected but the session is locked a message
will be shown informing the user that the device needs to be
reconnected to properly work.
The org.freedesktop.bolt service is provided by the "bolt" daemon.
2018-02-05 21:38:49 +01:00
8fdf47ea5b keyboard: Do not create widgetry for all keyboard groups at once
Instead do this on demand based on the current group. It is less
taxing at the time of initially creating the Keyboard object.
2018-02-05 17:46:57 +01:00
82cecf2e36 keyboard: Add languages selection popup
Currently the language options displayed pretty much mirror those of the
top bar keyboard layout selection popup. It may make sense in the future
to only list languages, and automatically switch to the enabled IMs that
the OSK can benefit from (eg. by filling in suggestions).
2018-02-05 17:46:57 +01:00
d7f8a39023 keyboard: slide focused window on OSK visibility
The focused window will move up/down together with the OSK if the focus
area happens to be covered by the area to be covered by the OSK. This
state is reverted whenever the window loses focus, given it wasn't
relayout in between.
2018-02-05 17:46:57 +01:00
083d11a032 misc: Make IBus a mandatory dependency
IBus was initially made optional as gnome-shell depended on too
recent API. This API is now old enough and gnome-shell is committing
further to IBus by implementing a ClutterInputMethod through it.
Let's just make IBus a mandatory dependency, instead of making code
paths trickier to cater for situations where it's missing.
2018-02-05 17:46:57 +01:00
e0852e5991 keyboard: Remove duplicate code
The same calls happen right at the beginning of the function.
2018-02-05 17:46:57 +01:00
5cec4ae670 keyboard: Move extended keys pop up/down into the Key object
We do not need the parent Keyboard object to handle those specially, the
code can be self-contained enough. The Key object will simply emit
pressed/released events containing the keycode/string, be it from the
parent key or one contained in the BoxPointer.
2018-02-05 17:46:57 +01:00
e4ee944d8d viewSelector: Send first printable keystroke to the search entry
StIMText used to handle key events for IM consumption in the capture phase,
this made the search box work automagically with nothing explicitly focusing
it. Since it's no longer the case, it has to be done somewhere.
2018-02-05 17:46:57 +01:00
70bc94946f keyboard: add a special KeyContainer actor to contain keyboard layers
Instead of manually resizing each key everytime the keyboard needs to
relayout, have a special grid container that will preserve aspect when
resized.

This actor works in two stages though, first the keys need to be added
and then layoutButtons() need to be called for the actors to be
reparented to the container with the right attachment options.
2018-02-05 17:46:57 +01:00
8c3f5b615f shell: Remove gdk_screen property/getter
It's used nowhere.
2018-02-05 17:46:57 +01:00
d1bebba77a shell: Remove intricate key event handling code
We no longer need to do contortions with key events, as Clutter
key events will be already handed to IMs through ClutterInputMethod.
2018-02-05 17:46:57 +01:00
83accce24e st: Remove StIMText
It is entirely unused now.
2018-02-05 17:46:57 +01:00
d86b62d1b7 st: Make StEntry rely entirely on ClutterInputMethod/Focus
StIMText is no longer needed here.
2018-02-05 17:46:57 +01:00
a2303c5272 ibusCandidatePopup: Feed OSK suggestions from ibus panel candidates
We don't currently hide the ibus completion panel, and this is done from
within the popup that we are meant to hide itself, so thoroughly sucks.
2018-02-05 17:46:57 +01:00
e0910c0f7c keyboard: Add visible property
So its visibility can be queried externally.
2018-02-05 17:46:57 +01:00
5b1e705561 keyboard: Add Suggestions object/actor
This will display completion suggestions, that when clicked will get the
text inserted into the current IM focus.
2018-02-05 17:46:57 +01:00
d93037c05e keyboard: Lookup minimum number of grid slots for each keymap
Instead of doing max() of all. Results on better used screen space on
every keymap.
2018-02-05 17:46:57 +01:00
73c7441279 keyboard: Use InputMethod underneath 2018-02-05 17:46:57 +01:00
5914f225a2 misc: Add InputMethod class
This is a ClutterInputMethod implementation using IBus underneath. The
input method will interact with the currently focused ClutterInputFocus,
be it shell chrome or wayland clients through the text_input protocol.
2018-02-05 17:46:57 +01:00
774930f1a1 keyboard: Ensure to resize keys after layer change
The keys possibly need resizing after a (new) layer has been set, there's
however calling places that don't. Instead, fold this._redraw() into
setActiveLayer().
2018-02-05 17:46:57 +01:00
3dd3c1ac34 st: Make st_button_fake_release() work with touch press
The st_button_release() call wouldn't happen because StButton does not
set priv->button_mask on touch events. And if we make it called, we can't
try to unset the device grab at the end of the function, as device/sequence
are unset earlier on.
2018-02-05 17:46:57 +01:00
40db4a6795 main: Stop acquiring caribou name
This is not necessary anymore.
2018-02-05 17:46:57 +01:00
7fd8fa3478 keyboard: Rework OSK
Caribou is no longer used to load keyboard layouts,
gnome-shell uses the JSON files extracted from Unicode
CLDR instead.
2018-02-05 17:46:57 +01:00
33c3ed68fd keyboard: Drop message tray source, and tray focus handling
These are long unused.
2018-02-05 17:46:57 +01:00
a1ce0da9e7 main: Load OSK layouts resource 2018-02-05 17:46:57 +01:00
52a779e432 data: Add keyboard layout JSON files
These have been created with the script at
git://repo.or.cz/cldr2json.git to translate the XML android
keymaps at http://www.unicode.org/Public/cldr/latest/keyboards.zip
into JSON, easier to parse from gnome-shell.
2018-02-05 17:46:57 +01:00
6795fb0bd6 data: Add README and supporting script to update keyboard layouts from CLDR
The README describes the steps in detail, but most of it is abstracted away
by the update-osk-layouts.sh script.
2018-02-05 17:46:57 +01:00
7544bba0c1 keyboard: Restore intended OSK visibility behavior
Getting the necessary "setting enabled, or input from touchscreen"
conditions to have the OSK shown are not enough on the lack of a
current focus. As we are setting up the caret tracker here, wait for
the focus in event before showing the keyboard.

This fixes 2 issues, with the setting disabled it became really hard
to get the OSK hidden on eg. touchscreen->pointer device switches,
as visibility only depended on the a11y setting here. And secondly,
enabling the setting would always end up with the OSK being shown
regardless of focus, while it should stay hidden if there's no text
edition.

https://bugzilla.gnome.org/show_bug.cgi?id=788188
2018-02-05 17:46:57 +01:00
2d79ab6c5c private: Avoid unnecessary conversions in shadow computation
The type was changed from double to float for no apparent reason
when moving code in commit 5060081db5.

https://bugzilla.gnome.org/show_bug.cgi?id=788627
2018-02-05 11:09:01 -05:00
fd034f3724 Update zh_CN translation 2018-02-05 09:39:38 +08:00
8502be66fa Update Polish translation 2018-02-04 23:37:21 +01:00
626bbeffbf Update Finnish translation 2018-02-03 12:04:25 +00:00
4a3c610d70 Update Indonesian translation 2018-02-01 17:55:15 +00:00
bc9e5a4252 Update Swedish translation 2018-01-31 22:39:24 +00:00
e09f8c87e8 padOsd: Fixup to the previous commit
Forgot to squash this change before pushing, I will leave something in the
money jar as I close the door.
2018-01-30 16:41:25 +01:00
9ad7f59cdb padOsd: Ensure to pick pad devices only
If the underlying X11 input driver creates multiple devices from a single
device node, we may end up picking up the wrong device. So, instead of
picking the first device based on node and bailing out if it's not a pad,
pick the first pad that has that device node, and bail out if there is
none.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/10

Closes: #10
2018-01-30 16:19:42 +01:00
6e74f987ec build: Update gvc to support renamed options
gvc has made some recent changes that rename its user options
following meson guidelines for GNOME packages[0].

The options used in gvc as a subproject have been renamed
accordingly.

[0] https://wiki.gnome.org/Initiatives/GnomeGoals/MesonPorting
2018-01-30 13:37:38 +01:00
8c8a7f089f Update Hungarian translation 2018-01-28 21:49:02 +00:00
9b6a931b43 build: Update gvc to not require ALSA support
ALSA support is only used in gnome-settings-daemon, so always disable
the option, which wouldn't work on non-Linux anyway.
2018-01-26 11:24:03 +01:00
c31bd67538 Update Spanish translation 2018-01-25 11:51:04 +00:00
5297e86591 Update Slovak translation 2018-01-22 19:41:26 +00:00
1d3154a89e networkAgent: Pick up VPN service dir from pkg-config
It turns out that NetworkManager does export the directory as pkg-config
variable after all, so use that instead of building the path ourselves
from the prefix.

https://bugzilla.gnome.org/show_bug.cgi?id=789811
2018-01-22 08:44:19 +01:00
fed5657b40 [l10n] Update Catalan translation 2018-01-22 00:22:18 +01:00
53f4d12566 Update Catalan translation 2018-01-20 22:10:11 +01:00
5d20516330 Update German translation 2018-01-19 23:04:32 +00:00
69da686fa9 dnd: Declare restore location variables
https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-01-17 13:04:41 -05:00
35eac697c1 appDisplay: don't try to close the popup menu that is already destroyed
This would lead to a JS error otherwise, as we might end up
in deleting actors that have been already destructed.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2018-01-17 13:04:41 -05:00
705915cd31 keyboard: Don't pop up on touch events
We want touch events to enable the keyboard and focus tracking, but
not to actually show it right away. Implement that behavior by only
changing the visibility of the keyboard when triggered by a GSettings
change.

https://bugzilla.gnome.org/show_bug.cgi?id=788188
2018-01-16 17:41:46 +01:00
cf23490c37 keyboard: Split enabled setting from enabled state
We enable the keyboard when it is either enabled explicitly via
a11y settings or when using a touch device. We'll soon want to
special-case changes to the GSettings, so track its value in a
dedicated property.

https://bugzilla.gnome.org/show_bug.cgi?id=788188
2018-01-16 17:41:46 +01:00
d5f081a108 keyboard: Minor cleanup
_syncEnabled() will call _setupKeyboard() if necessary, so no need
to call it explicitly before.

https://bugzilla.gnome.org/show_bug.cgi?id=788188
2018-01-16 17:41:46 +01:00
f2917968ea Update Friulian translation 2018-01-15 10:54:48 +00:00
16a1c35e28 network: unregister the agent when it's disabled
When the agent doesn't work (e.g. when the screen is locked), it shouldn't be
registered with NM. Otherwise it will keep cancelling the requests that
could happily be serviced with system secrets.

https://bugzilla.gnome.org/show_bug.cgi?id=789811
2018-01-12 11:50:49 +01:00
baacd216dd network: remove the vpn request when it's serviced
The native agent already forgets about the request at the point it's
serviced and the further attempt to use it (e.g. cancel it when the screen
is locked) will trigger an assertion failure:

  ** (gnome-shell:30862): CRITICAL **: shell_network_agent_respond: assertion 'request != NULL' failed

https://bugzilla.gnome.org/show_bug.cgi?id=789811
2018-01-12 11:48:52 +01:00
d71af5e579 network: port to libnm
The libnm-glib is depreacted for a long time already.

https://bugzilla.gnome.org/show_bug.cgi?id=789811
2018-01-12 11:48:49 +01:00
bc5be10d78 ui: Add keyboard accessibility dialog
Show a dialog informing the user each time the keyboard accessibility
flags are changed by one of the clutter backends (either from toggle
keys or two-keys-off modifiers).

https://bugzilla.gnome.org/show_bug.cgi?id=788564
2018-01-10 19:10:18 +01:00
f91fbd7728 network: Fix visibility of VPN section
Commit f2a9467f91 was too eager to simplify the code, and removed
the bits that hid the section in case no VPNs are set up - add them
back to fix the visibility.

https://bugzilla.gnome.org/show_bug.cgi?id=787845
2018-01-10 10:11:25 +01:00
f40ad89c9f Update Finnish translation 2018-01-09 18:24:32 +00:00
723c49a8b7 location: Use translated reason string
Gio now has API to look up localized strings from desktop files,
so we can display a correctly translated reason where available.

https://bugzilla.gnome.org/show_bug.cgi?id=779413
2018-01-09 00:25:46 +01:00
3f3e514ff2 networkAgent: Update VPN config path
The location moved a while ago, so update the path to point to
the non-deprecated location.

https://bugzilla.gnome.org/show_bug.cgi?id=791487
2018-01-09 00:25:46 +01:00
aab7656d88 man: Update project website 2018-01-07 21:39:18 +01:00
45e756f247 Updated Slovenian translation 2017-12-31 11:38:12 +01:00
027a08804a Update Swedish translation 2017-12-26 11:44:38 +00:00
e64a482972 Update Turkish translation 2017-12-20 19:56:13 +00:00
eb4cd57aa2 Update Latvian translation 2017-12-18 20:16:45 +02:00
94b96f8d97 background: don't leak wall clock when background changes
The background code allocates a GnomeWallClock when its first created,
but neglects to drop a reference to that clock at destroy time.
The undestroyed clocks lead to a timerfd leak that eventually prevents
the shell from functioning.

https://bugzilla.gnome.org/show_bug.cgi?id=791655
2017-12-15 10:57:14 -05:00
989c7bf27e Update Friulian translation 2017-12-15 12:30:08 +00:00
77ec6a8ea6 Update Spanish translation 2017-12-13 15:35:10 +00:00
fb9db4e171 system: Align submenu labels with parent
All section titles use an icon, while all corresponding submenu items
are plain-text. As a result, labels in submenus aren't aligned with
the labels in the parent, which makes them harder to read and look
unbalanced. Address this by adding additional whitespace to submenu
items to account for the additional elements in the title.

https://bugzilla.gnome.org/show_bug.cgi?id=706191
2017-12-11 16:19:09 +01:00
54013182d4 Update Arabic translation 2017-12-10 11:32:35 +02:00
7571f0d59e Update Catalan translation 2017-12-08 10:51:15 +01:00
90534afc20 Update Icelandic translation
(cherry picked from commit 74f4447b38)
2017-12-08 09:01:25 +00:00
29987ae033 dateMenu: Fix possible crash with unknown locations
If there are locations unknown to the libgweather version gnome-shell is
using, don't crash.

JS ERROR: TypeError: b.location is null
WorldClocksSection<._clocksChanged/<@resource:///org/gnome/shell/ui/dateMenu.js:141:1
WorldClocksSection<._clocksChanged@resource:///org/gnome/shell/ui/dateMenu.js:139:9

https://bugzilla.gnome.org/show_bug.cgi?id=791148
2017-12-06 02:02:48 +01:00
a29ceb31dd dateMenu: Ignore malformed world-clocks settings
Guard against a malformed setting that doesn't contain a
'location' key.

https://bugzilla.gnome.org/show_bug.cgi?id=791148
2017-12-06 02:02:48 +01:00
74683b7ef7 dash: Do not shadow ClutterActor's destroy()
Since commit ef1e27966d turned DashItemContainer into an StWidget,
the destroy() method overrides the ClutterActor method, which is at
the very least bad style. Instead, follow the usual pattern of using
a ::destroy handler.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2017-12-05 18:07:00 -05:00
6c655a6c71 dash: Make sure item labels are only destroyed once
Labels are currently destroyed from both animateOutAndDestroy()
and destroy(), which now (rightfully) triggers a gjs warning. As
the label is created unconditionally since commit 36e5ae4a25,
mirror that and always release it in destroy() and hide it
elsewhere.

https://bugzilla.gnome.org/show_bug.cgi?id=791233
2017-12-05 18:06:58 -05:00
13fdaa80bf Update Indonesian translation 2017-12-05 14:58:58 +00:00
6e3178d5b6 build: Remove Build API wrapper
GNOME Continuous gained native meson support, so we don't need the
wrapper script anymore.
2017-12-01 16:04:48 +01:00
ca367e4e26 build: Stop detecting features automatically
Auto-detect options add some convenience for platforms where a
particular feature isn't available - systemd on non-Linux OS comes
to mind - but the downside is that it is easy to accidentally build
without a desired feature. We consider the latter much more serious
nowadays, so turn our auto-detect options into regular boolean
options.

https://bugzilla.gnome.org/show_bug.cgi?id=791007
2017-11-30 00:24:53 +01:00
10c602fe95 build: Remove 'enable' prefix from option names
Meson options are typed, so the prefix isn't necessary, and indeed
looks odd when used to disable the option:
 -Denable_foo=false

Also replace underscores with dashes, which is the preferred meson
style.

https://bugzilla.gnome.org/show_bug.cgi?id=791007
2017-11-30 00:24:53 +01:00
ecd9fba514 Updated Hebrew tranlsation 2017-11-26 22:32:27 +02:00
71585f37e4 Updated Hebrew tranlsation 2017-11-26 22:19:39 +02:00
99e53a68b9 Updated Lithuanian translation 2017-11-25 21:53:01 +02:00
69e22f849e Updated Czech translation 2017-11-22 10:17:51 +01:00
9bad2182dd systemActions: Add more keywords
https://bugzilla.gnome.org/show_bug.cgi?id=786987
2017-11-21 13:32:21 -05:00
32b2639052 systemActions: Use Title Case
Use Title Case for the new GNOME 3.26 System Action shortcuts,
to match basically everything else in the Activities Overview.

https://bugzilla.gnome.org/show_bug.cgi?id=786987
2017-11-21 13:29:51 -05:00
35a9c3ec86 extension: log message if extension could not be installed
https://bugzilla.gnome.org/show_bug.cgi?id=776940
2017-11-21 13:15:05 -05:00
a46af9edf0 status/keyboard: Reset menuItems and Label objects on change
In the current code it could happen that we've menuItems and indicatorLabels
for sources that aren't anymore around, because in case a source is removed
we don't cleanup the their container objects.
Also, we should nullify InputManager's _currentSource when sources change
or it might point to some invalid data again.

So it could happen that we try to access an invalid menuitem or label
if a source change happens mentioning a source that has been deleted.

https://bugzilla.gnome.org/show_bug.cgi?id=788931
2017-11-21 02:16:38 -05:00
9dc977e324 Update Czech translation 2017-11-19 12:36:17 +01:00
cdc212ff6e overview: Protect ::drag-end handlers
These end up emitting item-drag-end/window-drag-end pretty much
without checks. Given the MetaDnd object may end up emitting
::drag-leave as a result of the plugin ending its grab, this
would result on spurious emission of those events and subsequent
warnings.

For extra paranoia, the _inDrag variable has been split into
_inItemDrag/_inWindowDrag so we can't cross the streams.

https://bugzilla.gnome.org/show_bug.cgi?id=784545
2017-11-17 14:34:40 +01:00
c53557b4c6 Updated Norwegian bokmål translation. 2017-11-09 20:20:46 +01:00
1af65c616a Update Arabic translation 2017-11-03 10:18:20 +02:00
feed029ae4 panel: focus windows on Escape key press
https://bugzilla.gnome.org/show_bug.cgi?id=671121
2017-11-01 20:52:58 +01:00
93925c99b4 style: Fix left tile preview
Windows that are tiled to the left/right only use rounded corners
where they are attached to the edge, the preview should follow that.
2017-11-01 19:59:26 +01:00
e765e684c3 windowAttentionHandler: Fix typo
Gah, thanks Alessandro Bono for the quick catch ...
2017-10-26 19:54:50 +02:00
eecbd4dd42 windowAttentionHandler: Follow app policy for attention notifications
While window attention notifications are created by the shell itself
rather than applications (most likely as a result of focus stealing
prevention), users still commonly link them to the application for
which they are shown. It makes therefore sense to follow the appropriate
policy set by the user rather than showing them unconditionally.

https://bugzilla.gnome.org/show_bug.cgi?id=779974
2017-10-26 19:39:04 +02:00
fa276a3349 theme: Restore drag effect between workspaces
When dragging a window between two workspaces a light effect used
to be present. The effect was lost probably during the theme revamp
in version 3.16.

https://bugzilla.gnome.org/show_bug.cgi?id=789103
2017-10-26 19:10:16 +02:00
100d6a7fa7 dialog: Reset initial focus on destroy
Since 0b02f757f8 we track the button that should have key focus
when the dialog is opened. However when the dialog is reused, the
button may get destroyed - clear the initial focus in that case to
allow setButton() to set a new one.

https://bugzilla.gnome.org/show_bug.cgi?id=788542
2017-10-26 18:14:52 +02:00
9537bb276b Update Dutch translation 2017-10-25 09:06:02 +00:00
891bc45e36 main: use SA_NODEFER to track signals to being able to raise from alarm
After we receive one of the tracked signals, in case we get stuck inside
the gjs_dumpstack () call, we use an alarm to raise the previously emitted
signal, however without using SA_NODEFER, the raise inside the alarm handler
will be ignored.

To avoid to handle new signals caused by the handler calls, once we get the
first signal, we just ignore them all as they could only lead to dirty traces.

Also, cleaning up a bit the code, and disabling the shell log handler
in dump_gjs_stack_alarm_sigaction since this might lead to a new
gjs_dumpstack () request.

https://bugzilla.gnome.org/show_bug.cgi?id=789237
2017-10-24 14:18:45 +08:00
f90b225eaa main: call gjs_dumpstack on aborts and traps and optionally on segfaults
In order to debug issues triggered by JS code we might need to
see the stack of it, this is not normally visible in static stack traces,
thus we need to call gjs_dumpstack () before dying the process.

Intercepting signals SIGABRT, SIGTRAP (needed for catching fatal glib
errors) SIGFPE and SIGIOT by default, while introducing a new
'backtrace-segfaults' flag for the SHELL_DEBUG environment variable to
do the same on SIGSEGV and SIGBUS (this is a precaution to avoid that we
corrupt the stack for automatic errors trackers).

In any case after dumping the stack we raise the signal again, in order
to make the system aware of it.

https://bugzilla.gnome.org/show_bug.cgi?id=789237
2017-10-23 05:05:51 -05:00
f9569912df window-tracker: use generic meta_window_get_sandboxed_app_id
This is valid for both Flatpak's and snaps now, we can use a more generic
API then.

https://bugzilla.gnome.org/show_bug.cgi?id=789277
2017-10-21 13:37:13 -05:00
29eefc06d7 Update zh_CN translation 2017-10-21 19:35:59 +08:00
aa0858529e network: Spawn wifi panel for further WPA enterprise configuration
Settings recently split Wi-Fi configuration from the Network panel,
so launch that instead.

https://bugzilla.gnome.org/show_bug.cgi?id=789231
2017-10-20 18:03:33 +02:00
fb3070981c bluetooth: Add missing 'BluetoothHardwareAirplaneMode' to D-Bus interface
This D-Bus property was never been added here, which caused inconsistencies
under some scenarios (e.g. coming back from suspend) if some devices were
previously paired, since _sync() would then make the bluetooth menu visible
unconditially, because of the proxied property evaluating to 'false'.

Adding this to the D-Bus interface makes sure that it's no longer undefined
and returns the right value, fixing the bug.

https://bugzilla.gnome.org/show_bug.cgi?id=789110
2017-10-17 20:16:38 +01:00
129690eed2 Bump version to 3.27.1
Update NEWS.
2017-10-17 17:47:51 +02:00
c12da66da8 popupMenu: Fix setting ImageMenuItem's icons via strings
Commit 28ca96064b added support for setting PopupImageMenuItem's icons
via GIcons as well as via strings. However as the check whether an object
implements the GIcon interface only works on GObjects, specifying an icon
name was broken. Fix that to actually allow both strings and GIcons.

https://bugzilla.gnome.org/show_bug.cgi?id=789018
2017-10-16 20:47:05 +02:00
01d8811913 gdm: Remove separate greeter universal access icon
The idea behind always showing the icon on the login screen is that
the users' needs aren't known at that point. However we can achieve
the same behavior by including the 'always-show-universal-access-status'
key in GDM's presets, so drop the special-case.

https://bugzilla.gnome.org/show_bug.cgi?id=788943
2017-10-13 16:53:54 +02:00
e16eb55339 Update Friulian translation
(cherry picked from commit 43ec5280b4)
2017-10-11 06:35:39 +00:00
f3f8ecff20 Updated Slovenian translation 2017-10-09 20:53:39 +02:00
db43c45b12 layout: Unset primary and bottom monitor when headless
We were handling being initially headless by only setting the primary
and bottom monitor if there was any primary monitor, then checking the
primary monitor reference before making calls assuming there was any
monitors.

What we didn't do was unset the primary and bottom monitor when going
headless, meaning that temporarly disconnecting a monitor while having
windows open caused an assert to be triggered due to various code paths
taking the path assuming there are valid monitors.

Unsetting both the primary and bottom monitor when going headless avoids
the code paths in the same way as they were avoided when starting
headless.

https://bugzilla.gnome.org/show_bug.cgi?id=788607
2017-10-06 20:31:14 -04:00
fa8523db1e [l10n] Updated Catalan (Valencian) translation 2017-10-05 13:59:19 +02:00
144 changed files with 38450 additions and 6456 deletions

1
.gitignore vendored
View File

@ -8,6 +8,7 @@ ChangeLog
INSTALL
aclocal.m4
autom4te.cache
data/.osk-layout-workbench
data/org.gnome.Shell.desktop
data/org.gnome.Shell.desktop.in
data/gnome-shell-extension-prefs.desktop

11
NEWS
View File

@ -1,3 +1,14 @@
3.27.1
======
* Fix using icon-name strings with PopupImageMenuItems [Florian; #789018]
* Misc. bug fixes [Jonas, Florian; #788607, #788943]
Contributors:
Jonas Ådahl, Florian Müllner
Translations:
Xavi Ivars [ca@valencia], Matej Urbančič [sl], Fabio Tomat [fur]
3.26.1
======
* Don't detach launched apps to not break pkexec and friends [Florian; #763531]

158
configure vendored
View File

@ -1,158 +0,0 @@
#!/bin/bash
# configure script adapter for Meson
# Based on build-api: https://github.com/cgwalters/build-api
# Copyright 2010, 2011, 2013 Colin Walters <walters@verbum.org>
# Copyright 2016, 2017 Emmanuele Bassi
# Licensed under the new-BSD license (http://www.opensource.org/licenses/bsd-license.php)
# Build API variables:
# Little helper function for reading args from the commandline.
# it automatically handles -a b and -a=b variants, and returns 1 if
# we need to shift $3.
read_arg() {
# $1 = arg name
# $2 = arg value
# $3 = arg parameter
local rematch='^[^=]*=(.*)$'
if [[ $2 =~ $rematch ]]; then
read "$1" <<< "${BASH_REMATCH[1]}"
else
read "$1" <<< "$3"
# There is no way to shift our callers args, so
# return 1 to indicate they should do it instead.
return 1
fi
}
sanitycheck() {
# $1 = arg name
# $1 = arg command
# $2 = arg alternates
local cmd=$( which $2 2>/dev/null )
if [ -x "$cmd" ]; then
read "$1" <<< "$cmd"
return 0
fi
test -z $3 || {
for alt in $3; do
cmd=$( which $alt 2>/dev/null )
if [ -x "$cmd" ]; then
read "$1" <<< "$cmd"
return 0
fi
done
}
echo -e "\e[1;31mERROR\e[0m: Command '$2' not found"
exit 1
}
sanitycheck MESON 'meson'
sanitycheck NINJA 'ninja' 'ninja-build'
enable_docs='-Denable-gtk-doc=false'
enable_man='-Denable-man=false'
enable_introspection=''
while (($# > 0)); do
case "${1%%=*}" in
--prefix) read_arg prefix "$@" || shift;;
--bindir) read_arg bindir "$@" || shift;;
--sbindir) read_arg sbindir "$@" || shift;;
--libexecdir) read_arg libexecdir "$@" || shift;;
--datarootdir) read_arg datarootdir "$@" || shift;;
--datadir) read_arg datadir "$@" || shift;;
--sysconfdir) read_arg sysconfdir "$@" || shift;;
--libdir) read_arg libdir "$@" || shift;;
--mandir) read_arg mandir "$@" || shift;;
--includedir) read_arg includedir "$@" || shift;;
--enable-gtk-doc) enable_docs='-Denable-gtk-doc=true';;
--disable-gtk-doc) enable_docs='-Denable-gtk-doc=false';;
--enable-man) enable_man='-Denable-man=true';;
--disable-man) enable_man='-Denable-man=false';;
--enable-introspection) enable_introspection='';;
--disable-introspection) enable_introspection='-Ddisable_introspection=true';;
*) echo -e "\e[1;33mINFO\e[0m: Ignoring unknown option '$1'";;
esac
shift
done
# Defaults
test -z ${prefix} && prefix="/usr/local"
test -z ${bindir} && bindir=${prefix}/bin
test -z ${sbindir} && sbindir=${prefix}/sbin
test -z ${libexecdir} && libexecdir=${prefix}/bin
test -z ${datarootdir} && datarootdir=${prefix}/share
test -z ${datadir} && datadir=${datarootdir}
test -z ${sysconfdir} && sysconfdir=${prefix}/etc
test -z ${libdir} && libdir=${prefix}/lib
test -z ${mandir} && mandir=${prefix}/share/man
test -z ${includedir} && includedir=${prefix}/include
# The source directory is the location of this file
srcdir=$(dirname $0)
# The build directory is the current location
builddir=`pwd`
# If we're calling this file from the source directory then
# we automatically create a build directory and ensure that
# both Meson and Ninja invocations are relative to that
# location
if [[ -f "${builddir}/meson.build" ]]; then
mkdir -p _build
builddir="${builddir}/_build"
NINJA_OPT="-C ${builddir}"
fi
# Wrapper Makefile for Ninja
cat > Makefile <<END
# Generated by configure; do not edit
all:
CC="\$(CC)" CXX="\$(CXX)" ${NINJA} ${NINJA_OPT}
install:
DESTDIR="\$(DESTDIR)" ${NINJA} ${NINJA_OPT} install
check:
${MESON} test ${NINJA_OPT}
END
echo "Summary:"
echo " meson:....... ${MESON}"
echo " ninja:....... ${NINJA}"
echo " prefix:...... ${prefix}"
echo " bindir:...... ${bindir}"
echo " sbindir:..... ${sbindir}"
echo " libexecdir:.. ${libexecdir}"
echo " datarootdir:. ${datarootdir}"
echo " datadir:..... ${datadir}"
echo " sysconfdir:.. ${sysconfdir}"
echo " libdir:...... ${libdir}"
echo " mandir:...... ${mandir}"
echo " includedir:.. ${includedir}"
echo " additional:.."
echo " - ${enable_docs} ${enable_man} ${enable_introspection}"
exec ${MESON} \
--prefix=${prefix} \
--libdir=${libdir} \
--libexecdir=${libexecdir} \
--datadir=${datadir} \
--sysconfdir=${sysconfdir} \
--bindir=${bindir} \
--includedir=${includedir} \
--mandir=${mandir} \
--default-library shared \
${enable_docs} \
${enable_man} \
${enable_introspection} \
${builddir} \
${srcdir}
# vim: ai ts=8 noet sts=2 ft=sh

33
data/README.osk-layouts Normal file
View File

@ -0,0 +1,33 @@
Gnome-shell OSK layouts are extracted from CLDR layout definitions:
https://www.unicode.org/cldr/charts/latest/keyboards/layouts/index.html
Updating these involves several steps:
1) Downloading and unzipping the tarball found at:
http://www.unicode.org/Public/cldr/latest/keyboards.zip
This file contains XML files describing the keyboard layouts.
2) Cloning the cldr2json script at:
git://repo.or.cz/cldr2json.git
It will be used to convert the XML files into JSON that can be
directly consumed by gnome-shell.
3) Running the script to produce the files:
./cldr2json <input-directory> <output-directory>
We shall usually use the "android" folder, since that's most
complete, and similar to our UI and target sizes. And the target
directory must be data/osk-layouts in this repository.
4) Modify gnome-shell-osk-layouts.gresource.xml to include the files
5) Do git add on the updated/new files, and git commit.
Or alternatively:
1) Run update-osk-layouts.sh
2) Do git add and git commit

View File

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/osk-layouts">
<file>am.json</file>
<file>ara.json</file>
<file>be.json</file>
<file>bg.json</file>
<file>by.json</file>
<file>cz.json</file>
<file>de.json</file>
<file>dk.json</file>
<file>ee.json</file>
<file>epo.json</file>
<file>es+cat.json</file>
<file>es.json</file>
<file>fi.json</file>
<file>fr.json</file>
<file>ge.json</file>
<file>gr.json</file>
<file>hr.json</file>
<file>hu.json</file>
<file>id.json</file>
<file>il.json</file>
<file>in+bolnagri.json</file>
<file>ir.json</file>
<file>is.json</file>
<file>it.json</file>
<file>ke.json</file>
<file>kg.json</file>
<file>kh.json</file>
<file>la.json</file>
<file>latam.json</file>
<file>lt.json</file>
<file>lv.json</file>
<file>mk.json</file>
<file>mn.json</file>
<file>my.json</file>
<file>nl.json</file>
<file>no.json</file>
<file>ph.json</file>
<file>pl.json</file>
<file>pt.json</file>
<file>ro.json</file>
<file>rs.json</file>
<file>ru.json</file>
<file>se.json</file>
<file>si.json</file>
<file>sk.json</file>
<file>th.json</file>
<file>tr.json</file>
<file>ua.json</file>
<file>uk.json</file>
<file>us.json</file>
<file>vn.json</file>
<file>za.json</file>
</gresource>
</gresources>

View File

@ -62,6 +62,14 @@ theme_resources = gnome.compile_resources(
install_dir: pkgdatadir
)
osk_layout_resources = gnome.compile_resources(
'gnome-shell-osk-layouts', 'gnome-shell-osk-layouts.gresource.xml',
source_dir: 'osk-layouts',
gresource_bundle: true,
install: true,
install_dir: pkgdatadir
)
perfconf = configuration_data()
perfconf.set('datadir', datadir)
configure_file(

599
data/osk-layouts/am.json Normal file
View File

@ -0,0 +1,599 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"է"
],
[
"թ"
],
[
"փ"
],
[
"ձ"
],
[
"ջ"
],
[
"ր"
],
[
"չ"
],
[
"ճ"
],
[
"ժ"
],
[
"ծ"
]
],
[
[
"ք"
],
[
"ո"
],
[
"ե",
"և"
],
[
"ռ"
],
[
"տ"
],
[
"ը"
],
[
"ւ"
],
[
"ի"
],
[
"օ"
],
[
"պ"
]
],
[
[
"ա"
],
[
"ս"
],
[
"դ"
],
[
"ֆ"
],
[
"գ"
],
[
"հ"
],
[
"յ"
],
[
"կ"
],
[
"լ"
],
[
"խ"
]
],
[
[
"զ"
],
[
"ղ"
],
[
"ց"
],
[
"վ"
],
[
"բ"
],
[
"ն"
],
[
"մ"
],
[
"շ"
]
],
[
[
","
],
[
" "
],
[
"։"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Է"
],
[
"Թ"
],
[
"Փ"
],
[
"Ձ"
],
[
"Ջ"
],
[
"Ր"
],
[
"Չ"
],
[
"Ճ"
],
[
"Ժ"
],
[
"Ծ"
]
],
[
[
"Ք"
],
[
"Ո"
],
[
"Ե",
"ԵՒ"
],
[
"Ռ"
],
[
"Տ"
],
[
"Ը"
],
[
"Ւ"
],
[
"Ի"
],
[
"Օ"
],
[
"Պ"
]
],
[
[
"Ա"
],
[
"Ս"
],
[
"Դ"
],
[
"Ֆ"
],
[
"Գ"
],
[
"Հ"
],
[
"Յ"
],
[
"Կ"
],
[
"Լ"
],
[
"Խ"
]
],
[
[
"Զ"
],
[
"Ղ"
],
[
"Ց"
],
[
"Վ"
],
[
"Բ"
],
[
"Ն"
],
[
"Մ"
],
[
"Շ"
]
],
[
[
","
],
[
" "
],
[
"։"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"՜",
"¡"
],
[
"?",
"՞",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
"՝"
],
[
"։",
"!",
"?",
",",
".",
"֊",
"՜",
"՝",
"՞",
":",
";",
"@",
"ՙ",
"՚",
"՛",
"՟"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
"՝"
],
[
"։",
"!",
"?",
",",
".",
"֊",
"՜",
"՝",
"՞",
":",
";",
"@",
"ՙ",
"՚",
"՛",
"՟"
]
]
]
}
],
"locale": "hy",
"name": "Armenian"
}

488
data/osk-layouts/ara.json Normal file
View File

@ -0,0 +1,488 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ض"
],
[
"ص"
],
[
"ث"
],
[
"ق",
"ڨ"
],
[
"ف",
"ڤ",
"ڢ",
"ڥ"
],
[
"غ"
],
[
"ع"
],
[
"ه",
"ه"
],
[
"خ"
],
[
"ح"
],
[
"ج",
"چ"
]
],
[
[
"ش",
"ڜ"
],
[
"س"
],
[
"ي",
"ئ",
"ى"
],
[
"ب",
"پ"
],
[
"ل",
"لا",
"لأ",
"لإ",
"لآ"
],
[
"ا",
"آ",
"ء",
"أ",
"إ",
"ٱ"
],
[
"ت"
],
[
"ن"
],
[
"م"
],
[
"ك",
"گ",
"ک"
],
[
"ط"
]
],
[
[
"ذ"
],
[
"ء"
],
[
"ؤ"
],
[
"ر"
],
[
"ى",
"ئ"
],
[
"ة"
],
[
"و"
],
[
"ز",
"ژ"
],
[
"ظ"
],
[
"د"
]
],
[
[
"،"
],
[
" "
],
[
".",
"\"",
"'",
"#",
"-",
":",
"!",
"،",
"؟",
"@",
"&",
"%",
"+",
"؛",
"/",
")",
"("
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"١",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"٢",
"²",
"⅔"
],
[
"٣",
"³",
"¾",
"⅜"
],
[
"٤",
"⁴"
],
[
"٥",
"⅝"
],
[
"٦"
],
[
"٧",
"⅞"
],
[
"٨"
],
[
"٩"
],
[
"٠",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"٪",
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"﴿",
">",
"}",
"]"
],
[
")",
"",
"<",
"{",
"["
]
],
[
[
"*",
"★",
"٭"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
"؛",
";"
],
[
"!",
"¡"
],
[
"؟",
"?"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
"،",
"؟",
"؛",
"!",
":",
"-",
"/",
"'",
"\""
],
[
".",
"ٕ",
"ٔ",
"ْ",
"ٍ",
"ٌ",
"ً",
"ّ",
"ٖ",
"ٰ",
"ٓ",
"ِ",
"ُ",
"َ",
"ـ"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≥",
"»"
],
[
">",
"",
"≤",
"«"
],
[
" "
],
[
"،",
"؟",
"؛",
"!",
":",
"-",
"/",
"'",
"\""
],
[
".",
"ٕ",
"ٔ",
"ْ",
"ٍ",
"ٌ",
"ً",
"ّ",
"ٖ",
"ٰ",
"ٓ",
"ِ",
"ُ",
"َ",
"ـ"
]
]
]
}
],
"locale": "ar",
"name": "Arabic"
}

584
data/osk-layouts/be.json Normal file
View File

@ -0,0 +1,584 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ë",
"ê",
"è",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y",
"ij"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
],
[
"i",
"í",
"ï",
"ì",
"î",
"į",
"ī",
"ij"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"ä",
"â",
"à",
"æ",
"ã",
"å",
"ā"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ë",
"Ê",
"È",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y",
"IJ"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
],
[
"I",
"Í",
"Ï",
"Ì",
"Î",
"Į",
"Ī",
"IJ"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"Ä",
"Â",
"À",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "nl-BE",
"name": "Dutch (Belgium)"
}

533
data/osk-layouts/bg.json Normal file
View File

@ -0,0 +1,533 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"я"
],
[
"в"
],
[
"е"
],
[
"р"
],
[
"т"
],
[
"ъ"
],
[
"у"
],
[
"и",
"ѝ"
],
[
"о"
],
[
"п"
],
[
"ч"
]
],
[
[
"а"
],
[
"с"
],
[
"д"
],
[
"ф"
],
[
"г"
],
[
"х"
],
[
"й"
],
[
"к"
],
[
"л"
],
[
"ш"
],
[
"щ"
]
],
[
[
"з"
],
[
"ь"
],
[
"ц"
],
[
"ж"
],
[
"б"
],
[
"н"
],
[
"м"
],
[
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Я"
],
[
"В"
],
[
"Е"
],
[
"Р"
],
[
"Т"
],
[
"Ъ"
],
[
"У"
],
[
"И",
"Ѝ"
],
[
"О"
],
[
"П"
],
[
"Ч"
]
],
[
[
"А"
],
[
"С"
],
[
"Д"
],
[
"Ф"
],
[
"Г"
],
[
"Х"
],
[
"Й"
],
[
"К"
],
[
"Л"
],
[
"Ш"
],
[
"Щ"
]
],
[
[
"З"
],
[
"Ь"
],
[
"Ц"
],
[
"Ж"
],
[
"Б"
],
[
"Н"
],
[
"М"
],
[
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "bg",
"name": "Bulgarian"
}

541
data/osk-layouts/by.json Normal file
View File

@ -0,0 +1,541 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"й"
],
[
"ц"
],
[
"у"
],
[
"к"
],
[
"е",
"ё"
],
[
"н"
],
[
"г"
],
[
"ш"
],
[
"ў"
],
[
"з"
],
[
"х"
]
],
[
[
"ф"
],
[
"ы"
],
[
"в"
],
[
"а"
],
[
"п"
],
[
"р"
],
[
"о"
],
[
"л"
],
[
"д"
],
[
"ж"
],
[
"э"
]
],
[
[
"я"
],
[
"ч"
],
[
"с"
],
[
"м"
],
[
"і"
],
[
"т"
],
[
"ь",
"ъ"
],
[
"б"
],
[
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Й"
],
[
"Ц"
],
[
"У"
],
[
"К"
],
[
"Е",
"Ё"
],
[
"Н"
],
[
"Г"
],
[
"Ш"
],
[
"Ў"
],
[
"З"
],
[
"Х"
]
],
[
[
"Ф"
],
[
"Ы"
],
[
"В"
],
[
"А"
],
[
"П"
],
[
"Р"
],
[
"О"
],
[
"Л"
],
[
"Д"
],
[
"Ж"
],
[
"Э"
]
],
[
[
"Я"
],
[
"Ч"
],
[
"С"
],
[
"М"
],
[
"І"
],
[
"Т"
],
[
"Ь",
"Ъ"
],
[
"Б"
],
[
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "be",
"name": "Belarusian"
}

613
data/osk-layouts/cz.json Normal file
View File

@ -0,0 +1,613 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ě",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
[
"r",
"ř"
],
[
"t",
"ť"
],
[
"z",
"ž",
"ź",
"ż"
],
[
"u",
"ú",
"ů",
"û",
"ü",
"ù",
"ū"
],
[
"i",
"í",
"î",
"ï",
"ì",
"į",
"ī"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"š",
"ß",
"ś"
],
[
"d",
"ď"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"y",
"ý",
"ÿ"
],
[
"x"
],
[
"c",
"č",
"ç",
"ć"
],
[
"v"
],
[
"b"
],
[
"n",
"ň",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ě",
"È",
"Ê",
"Ë",
"Ę",
"Ė",
"Ē"
],
[
"R",
"Ř"
],
[
"T",
"Ť"
],
[
"Z",
"Ž",
"Ź",
"Ż"
],
[
"U",
"Ú",
"Ů",
"Û",
"Ü",
"Ù",
"Ū"
],
[
"I",
"Í",
"Î",
"Ï",
"Ì",
"Į",
"Ī"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"À",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"Š",
"SS",
"Ś"
],
[
"D",
"Ď"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Y",
"Ý",
"Ÿ"
],
[
"X"
],
[
"C",
"Č",
"Ç",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N",
"Ň",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "cs",
"name": "Czech"
}

570
data/osk-layouts/de.json Normal file
View File

@ -0,0 +1,570 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"ė"
],
[
"r"
],
[
"t"
],
[
"z"
],
[
"u",
"ü",
"û",
"ù",
"ú",
"ū"
],
[
"i"
],
[
"o",
"ö",
"ô",
"ò",
"ó",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"ä",
"â",
"à",
"á",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"ß",
"ś",
"š"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"y"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"Ė"
],
[
"R"
],
[
"T"
],
[
"Z"
],
[
"U",
"Ü",
"Û",
"Ù",
"Ú",
"Ū"
],
[
"I"
],
[
"O",
"Ö",
"Ô",
"Ò",
"Ó",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Ä",
"Â",
"À",
"Á",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"SS",
"Ś",
"Š"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Y"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "de",
"name": "German"
}

590
data/osk-layouts/dk.json Normal file
View File

@ -0,0 +1,590 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ë"
],
[
"r"
],
[
"t"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
],
[
"i",
"í",
"ï"
],
[
"o",
"ó",
"ô",
"ò",
"õ",
"œ",
"ō"
],
[
"p"
],
[
"å"
]
],
[
[
"a",
"á",
"ä",
"à",
"â",
"ã",
"ā"
],
[
"s",
"ß",
"ś",
"š"
],
[
"d",
"ð"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l",
"ł"
],
[
"æ",
"ä"
],
[
"ø",
"ö"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ë"
],
[
"R"
],
[
"T"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
],
[
"I",
"Í",
"Ï"
],
[
"O",
"Ó",
"Ô",
"Ò",
"Õ",
"Œ",
"Ō"
],
[
"P"
],
[
"Å"
]
],
[
[
"A",
"Á",
"Ä",
"À",
"Â",
"Ã",
"Ā"
],
[
"S",
"SS",
"Ś",
"Š"
],
[
"D",
"Ð"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L",
"Ł"
],
[
"Æ",
"Ä"
],
[
"Ø",
"Ö"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "da",
"name": "Danish"
}

666
data/osk-layouts/ee.json Normal file
View File

@ -0,0 +1,666 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"ē",
"è",
"ė",
"é",
"ê",
"ë",
"ę",
"ě"
],
[
"r",
"ŗ",
"ř",
"ŕ"
],
[
"t",
"ţ",
"ť"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ü",
"ū",
"ų",
"ù",
"ú",
"û",
"ů",
"ű"
],
[
"i",
"ī",
"ì",
"į",
"í",
"î",
"ï",
"ı"
],
[
"o",
"ö",
"õ",
"ò",
"ó",
"ô",
"œ",
"ő",
"ø"
],
[
"p"
],
[
"ü"
]
],
[
[
"a",
"ä",
"ā",
"à",
"á",
"â",
"ã",
"å",
"æ",
"ą"
],
[
"s",
"š",
"ß",
"ś",
"ş"
],
[
"d",
"ď"
],
[
"f"
],
[
"g",
"ģ",
"ğ"
],
[
"h"
],
[
"j"
],
[
"k",
"ķ"
],
[
"l",
"ļ",
"ł",
"ĺ",
"ľ"
],
[
"ö",
"õ"
],
[
"ä"
]
],
[
[
"z",
"ž",
"ż",
"ź"
],
[
"x"
],
[
"c",
"č",
"ç",
"ć"
],
[
"v"
],
[
"b"
],
[
"n",
"ņ",
"ñ",
"ń",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"Ē",
"È",
"Ė",
"É",
"Ê",
"Ë",
"Ę",
"Ě"
],
[
"R",
"Ŗ",
"Ř",
"Ŕ"
],
[
"T",
"Ţ",
"Ť"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ü",
"Ū",
"Ų",
"Ù",
"Ú",
"Û",
"Ů",
"Ű"
],
[
"I",
"Ī",
"Ì",
"Į",
"Í",
"Î",
"Ï",
"I"
],
[
"O",
"Ö",
"Õ",
"Ò",
"Ó",
"Ô",
"Œ",
"Ő",
"Ø"
],
[
"P"
],
[
"Ü"
]
],
[
[
"A",
"Ä",
"Ā",
"À",
"Á",
"Â",
"Ã",
"Å",
"Æ",
"Ą"
],
[
"S",
"Š",
"SS",
"Ś",
"Ş"
],
[
"D",
"Ď"
],
[
"F"
],
[
"G",
"Ģ",
"Ğ"
],
[
"H"
],
[
"J"
],
[
"K",
"Ķ"
],
[
"L",
"Ļ",
"Ł",
"Ĺ",
"Ľ"
],
[
"Ö",
"Õ"
],
[
"Ä"
]
],
[
[
"Z",
"Ž",
"Ż",
"Ź"
],
[
"X"
],
[
"C",
"Č",
"Ç",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N",
"Ņ",
"Ñ",
"Ń",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "et",
"name": "Estonian"
}

711
data/osk-layouts/epo.json Normal file
View File

@ -0,0 +1,711 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ŝ",
"q"
],
[
"ĝ",
"w",
"ŵ"
],
[
"e",
"é",
"ě",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
[
"r",
"ř",
"ŕ",
"ŗ"
],
[
"t",
"ť",
"ț",
"ţ",
"ŧ"
],
[
"ŭ",
"y",
"ý",
"ŷ",
"ÿ",
"þ"
],
[
"u",
"ú",
"ů",
"û",
"ü",
"ù",
"ū",
"ũ",
"ű",
"ų",
"µ"
],
[
"i",
"í",
"î",
"ï",
"ĩ",
"ì",
"į",
"ī",
"ı",
"ij"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō",
"ő",
"º"
],
[
"p"
]
],
[
[
"a",
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā",
"ă",
"ą",
"ª"
],
[
"s",
"ß",
"š",
"ś",
"ș",
"ş"
],
[
"d",
"ð",
"ď",
"đ"
],
[
"f"
],
[
"g",
"ğ",
"ġ",
"ģ"
],
[
"h",
"ĥ",
"ħ"
],
[
"j"
],
[
"k",
"ķ",
"ĸ"
],
[
"l",
"ĺ",
"ļ",
"ľ",
"ŀ",
"ł"
],
[
"ĵ"
]
],
[
[
"z",
"ź",
"ż",
"ž"
],
[
"ĉ",
"x"
],
[
"c",
"ć",
"č",
"ç",
"ċ"
],
[
"v",
"w",
"ŵ"
],
[
"b"
],
[
"n",
"ñ",
"ń",
"ņ",
"ň",
"ʼn",
"ŋ"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Ŝ",
"Q"
],
[
"Ĝ",
"W",
"Ŵ"
],
[
"E",
"É",
"Ě",
"È",
"Ê",
"Ë",
"Ę",
"Ė",
"Ē"
],
[
"R",
"Ř",
"Ŕ",
"Ŗ"
],
[
"T",
"Ť",
"Ț",
"Ţ",
"Ŧ"
],
[
"Ŭ",
"Y",
"Ý",
"Ŷ",
"Ÿ",
"Þ"
],
[
"U",
"Ú",
"Ů",
"Û",
"Ü",
"Ù",
"Ū",
"Ũ",
"Ű",
"Ų",
"Μ"
],
[
"I",
"Í",
"Î",
"Ï",
"Ĩ",
"Ì",
"Į",
"Ī",
"I",
"IJ"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō",
"Ő",
"º"
],
[
"P"
]
],
[
[
"A",
"Á",
"À",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā",
"Ă",
"Ą",
"ª"
],
[
"S",
"SS",
"Š",
"Ś",
"Ș",
"Ş"
],
[
"D",
"Ð",
"Ď",
"Đ"
],
[
"F"
],
[
"G",
"Ğ",
"Ġ",
"Ģ"
],
[
"H",
"Ĥ",
"Ħ"
],
[
"J"
],
[
"K",
"Ķ",
"ĸ"
],
[
"L",
"Ĺ",
"Ļ",
"Ľ",
"Ŀ",
"Ł"
],
[
"Ĵ"
]
],
[
[
"Z",
"Ź",
"Ż",
"Ž"
],
[
"Ĉ",
"X"
],
[
"C",
"Ć",
"Č",
"Ç",
"Ċ"
],
[
"V",
"W",
"Ŵ"
],
[
"B"
],
[
"N",
"Ñ",
"Ń",
"Ņ",
"Ň",
"ʼN",
"Ŋ"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "eo",
"name": "Esperanto"
}

View File

@ -0,0 +1,602 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ë",
"ê",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ú",
"ü",
"ù",
"û",
"ū"
],
[
"i",
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
[
"o",
"ò",
"ó",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l",
"l·l",
"ł"
],
[
"ç"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"·",
"!",
",",
"?",
":",
";",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ë",
"Ê",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ú",
"Ü",
"Ù",
"Û",
"Ū"
],
[
"I",
"Í",
"Ï",
"Ì",
"Î",
"Į",
"Ī"
],
[
"O",
"Ò",
"Ó",
"Ö",
"Ô",
"Õ",
"Ø",
"Œ",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Ä",
"Â",
"Ã",
"Å",
"Ą",
"Æ",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L",
"L·L",
"Ł"
],
[
"Ç"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"·",
"!",
",",
"?",
":",
";",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"?",
"·"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"?",
"·"
]
]
]
}
],
"locale": "ca",
"name": "Catalan"
}

604
data/osk-layouts/es.json Normal file
View File

@ -0,0 +1,604 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ú",
"ü",
"ù",
"û",
"ū"
],
[
"i",
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
[
"o",
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
],
[
"ñ"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
";",
"!",
",",
"?",
":",
"¡",
"@",
"¿"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ë",
"Ê",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ú",
"Ü",
"Ù",
"Û",
"Ū"
],
[
"I",
"Í",
"Ï",
"Ì",
"Î",
"Į",
"Ī"
],
[
"O",
"Ó",
"Ò",
"Ö",
"Ô",
"Õ",
"Ø",
"Œ",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"Á",
"À",
"Ä",
"Â",
"Ã",
"Å",
"Ą",
"Æ",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
],
[
"Ñ"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
";",
"!",
",",
"?",
":",
"¡",
"@",
"¿"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
",",
"!",
"¡"
],
[
".",
"?",
"¿"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
",",
"!",
"¡"
],
[
".",
"?",
"¿"
]
]
]
}
],
"locale": "es",
"name": "Spanish"
}

570
data/osk-layouts/fi.json Normal file
View File

@ -0,0 +1,570 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ü"
],
[
"i"
],
[
"o",
"ø",
"ô",
"ò",
"ó",
"õ",
"œ",
"ō"
],
[
"p"
],
[
"å"
]
],
[
[
"a",
"æ",
"à",
"á",
"â",
"ã",
"ā"
],
[
"s",
"š",
"ß",
"ś"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
],
[
"ö",
"ø"
],
[
"ä",
"æ"
]
],
[
[
"z",
"ž",
"ź",
"ż"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ü"
],
[
"I"
],
[
"O",
"Ø",
"Ô",
"Ò",
"Ó",
"Õ",
"Œ",
"Ō"
],
[
"P"
],
[
"Å"
]
],
[
[
"A",
"Æ",
"À",
"Á",
"Â",
"Ã",
"Ā"
],
[
"S",
"Š",
"SS",
"Ś"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
],
[
"Ö",
"Ø"
],
[
"Ä",
"Æ"
]
],
[
[
"Z",
"Ž",
"Ź",
"Ż"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "fi",
"name": "Finnish"
}

599
data/osk-layouts/fr.json Normal file
View File

@ -0,0 +1,599 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"%",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y",
"%",
"ÿ"
],
[
"u",
"ù",
"û",
"%",
"ü",
"ú",
"ū"
],
[
"i",
"î",
"%",
"ï",
"ì",
"í",
"į",
"ī"
],
[
"o",
"ô",
"œ",
"%",
"ö",
"ò",
"ó",
"õ",
"ø",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"à",
"â",
"%",
"æ",
"á",
"ä",
"ã",
"å",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"%",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y",
"%",
"Ÿ"
],
[
"U",
"Ù",
"Û",
"%",
"Ü",
"Ú",
"Ū"
],
[
"I",
"Î",
"%",
"Ï",
"Ì",
"Í",
"Į",
"Ī"
],
[
"O",
"Ô",
"Œ",
"%",
"Ö",
"Ò",
"Ó",
"Õ",
"Ø",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"À",
"Â",
"%",
"Æ",
"Á",
"Ä",
"Ã",
"Å",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "fr-CA",
"name": "French Canada"
}

409
data/osk-layouts/ge.json Normal file
View File

@ -0,0 +1,409 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ქ"
],
[
"წ"
],
[
"ე",
"ჱ"
],
[
"რ"
],
[
"ტ"
],
[
"",
"ჸ"
],
[
"უ"
],
[
"ი",
"ჲ"
],
[
"ო"
],
[
"პ"
]
],
[
[
"ა",
"ჺ"
],
[
"ს"
],
[
"დ"
],
[
"ფ",
"ჶ"
],
[
"გ",
"ჹ"
],
[
"ჰ",
"ჵ"
],
[
"ჯ",
"ჷ"
],
[
"კ"
],
[
"ლ"
]
],
[
[
"ზ"
],
[
"ხ",
"ჴ"
],
[
"ც"
],
[
"ვ",
"ჳ"
],
[
"ბ"
],
[
"ნ",
"ჼ"
],
[
"მ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ka",
"name": "Georgian"
}

532
data/osk-layouts/gr.json Normal file
View File

@ -0,0 +1,532 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
";",
":"
],
[
"ς"
],
[
"ε",
"έ"
],
[
"ρ"
],
[
"τ"
],
[
"υ",
"ύ",
"ϋ",
"ΰ"
],
[
"θ"
],
[
"ι",
"ί",
"ϊ",
"ΐ"
],
[
"ο",
"ό"
],
[
"π"
]
],
[
[
"α",
"ά"
],
[
"σ"
],
[
"δ"
],
[
"φ"
],
[
"γ"
],
[
"η",
"ή"
],
[
"ξ"
],
[
"κ"
],
[
"λ"
]
],
[
[
"ζ"
],
[
"χ"
],
[
"ψ"
],
[
"ω",
"ώ"
],
[
"β"
],
[
"ν"
],
[
"μ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
";",
":"
],
[
"Σ"
],
[
"Ε",
"Έ"
],
[
"Ρ"
],
[
"Τ"
],
[
"Υ",
"Ύ",
"Ϋ",
"Ϋ́"
],
[
"Θ"
],
[
"Ι",
"Ί",
"Ϊ",
"Ϊ́"
],
[
"Ο",
"Ό"
],
[
"Π"
]
],
[
[
"Α",
"Ά"
],
[
"Σ"
],
[
"Δ"
],
[
"Φ"
],
[
"Γ"
],
[
"Η",
"Ή"
],
[
"Ξ"
],
[
"Κ"
],
[
"Λ"
]
],
[
[
"Ζ"
],
[
"Χ"
],
[
"Ψ"
],
[
"Ω",
"Ώ"
],
[
"Β"
],
[
"Ν"
],
[
"Μ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "el",
"name": "Greek"
}

531
data/osk-layouts/hr.json Normal file
View File

@ -0,0 +1,531 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"z",
"ž",
"ź",
"ż"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s",
"š",
"ś",
"ß"
],
[
"d",
"đ"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"y"
],
[
"x"
],
[
"c",
"č",
"ć",
"ç"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Z",
"Ž",
"Ź",
"Ż"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S",
"Š",
"Ś",
"SS"
],
[
"D",
"Đ"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Y"
],
[
"X"
],
[
"C",
"Č",
"Ć",
"Ç"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "hr",
"name": "Croatian"
}

579
data/osk-layouts/hu.json Normal file
View File

@ -0,0 +1,579 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"z"
],
[
"u",
"ú",
"ü",
"ű",
"û",
"ù",
"ū"
],
[
"i",
"í",
"î",
"ï",
"ì",
"į",
"ī"
],
[
"o",
"ó",
"ö",
"ő",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"y"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Z"
],
[
"U",
"Ú",
"Ü",
"Ű",
"Û",
"Ù",
"Ū"
],
[
"I",
"Í",
"Î",
"Ï",
"Ì",
"Į",
"Ī"
],
[
"O",
"Ó",
"Ö",
"Ő",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"À",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Y"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "hu",
"name": "Hungarian"
}

507
data/osk-layouts/id.json Normal file
View File

@ -0,0 +1,507 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "id",
"name": "Indonesian"
}

419
data/osk-layouts/il.json Normal file
View File

@ -0,0 +1,419 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"'",
"\""
],
[
"-",
"_"
],
[
"ק"
],
[
"ר"
],
[
"א"
],
[
"ט"
],
[
"ו"
],
[
"ן"
],
[
"ם"
],
[
"פ"
]
],
[
[
"ש"
],
[
"ד"
],
[
"ג",
"ג׳"
],
[
"כ"
],
[
"ע"
],
[
"י",
"ײַ"
],
[
"ח",
"ח׳"
],
[
"ל"
],
[
"ך"
],
[
"ף"
]
],
[
[
"ז",
"ז׳"
],
[
"ס"
],
[
"ב"
],
[
"ה"
],
[
"נ"
],
[
"מ"
],
[
"צ",
"צ׳"
],
[
"ת",
"ת׳"
],
[
"ץ",
"ץ׳"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₪",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±",
"﬩"
],
[
"(",
">",
"}",
"]"
],
[
")",
"<",
"{",
"["
]
],
[
[
"*",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
",",
"!"
],
[
".",
"?"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≥",
"»"
],
[
">",
"",
"≤",
"«"
],
[
" "
],
[
",",
"!"
],
[
".",
"?"
]
]
]
}
],
"locale": "he",
"name": "Hebrew"
}

View File

@ -0,0 +1,439 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"◌ौ"
],
[
"◌ै"
],
[
"◌ा"
],
[
"◌ी"
],
[
"◌ू"
],
[
"ब",
"ब॒",
"%"
],
[
"ह"
],
[
"ग",
"ज्ञ",
"ग़",
"ग॒",
"%"
],
[
"द"
],
[
"ज",
"ज॒",
"ज्ञ",
"ज़",
"%"
],
[
"ड",
"ड॒",
"ड़"
]
],
[
[
"◌ो"
],
[
"◌े"
],
[
"◌्"
],
[
"◌ि"
],
[
"◌ु"
],
[
"प"
],
[
"र",
"ऋ",
"ऱ",
"ॠ"
],
[
"क",
"क़"
],
[
"त",
"त्र"
],
[
"च"
],
[
"ट"
]
],
[
[
"◌ॉ"
],
[
"◌ं"
],
[
"म",
"ॐ"
],
[
"न",
"ञ",
"ङ",
"ऩ"
],
[
"व"
],
[
"ल",
"ऌ",
"ॡ"
],
[
"स"
],
[
"य",
"य़"
],
[
"◌़"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"१",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"२",
"²",
"⅔"
],
[
"३",
"³",
"¾",
"⅜"
],
[
"४",
"⁴"
],
[
"५",
"⅝"
],
[
"६"
],
[
"७",
"⅞"
],
[
"८"
],
[
"९"
],
[
"",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₹",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "hi",
"name": "Hindi"
}

495
data/osk-layouts/ir.json Normal file
View File

@ -0,0 +1,495 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ض"
],
[
"ص"
],
[
"ث"
],
[
"ق",
"ڨ"
],
[
"ف",
"ڤ",
"ڢ",
"ڥ"
],
[
"غ"
],
[
"ع"
],
[
"ه",
"ه"
],
[
"خ"
],
[
"ح"
],
[
"ج",
"چ"
]
],
[
[
"ش",
"ڜ"
],
[
"س"
],
[
"ي",
"ئ",
"ى"
],
[
"ب",
"پ"
],
[
"ل",
"لا",
"لأ",
"لإ",
"لآ"
],
[
"ا",
"آ",
"ء",
"أ",
"إ",
"ٱ"
],
[
"ت"
],
[
"ن"
],
[
"م"
],
[
"ك",
"گ",
"ک"
],
[
"ط"
]
],
[
[
"ذ"
],
[
"ء"
],
[
"ؤ"
],
[
"ر"
],
[
"ى",
"ئ"
],
[
"ة"
],
[
"و"
],
[
"ز",
"ژ"
],
[
"ظ"
],
[
"د"
]
],
[
[
"،"
],
[
" "
],
[
" "
],
[
".",
"\"",
"'",
"#",
"-",
":",
"!",
"،",
"؟",
"@",
"&",
"%",
"+",
"؛",
"/",
")",
"("
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"۱",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"۲",
"²",
"⅔"
],
[
"۳",
"³",
"¾",
"⅜"
],
[
"۴",
"⁴"
],
[
"۵",
"⅝"
],
[
"۶"
],
[
"۷",
"⅞"
],
[
"۸"
],
[
"۹"
],
[
"۰",
"ⁿ",
"∅"
]
],
[
[
"٬",
"@"
],
[
"٫",
"#"
],
[
"﷼",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"٪",
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"﴿",
">",
"}",
"]"
],
[
")",
"",
"<",
"{",
"["
]
],
[
[
"*",
"★",
"٭"
],
[
"«",
"“",
"”",
"«",
"»"
],
[
"»",
"",
"",
"",
""
],
[
":"
],
[
"؛",
";"
],
[
"!",
"¡"
],
[
"؟",
"?"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
"،",
":",
"!",
"؟",
"؛",
"-",
"/",
"»",
"«"
],
[
".",
"ٕ",
"ٔ",
"ْ",
"ٍ",
"ٌ",
"ً",
"ّ",
"ٖ",
"ٰ",
"ٓ",
"ِ",
"ُ",
"َ",
"ـ"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"«",
"",
"≥",
">"
],
[
"»",
"",
"≤",
"<"
],
[
" "
],
[
"،",
":",
"!",
"؟",
"؛",
"-",
"/",
"»",
"«"
],
[
".",
"ٕ",
"ٔ",
"ْ",
"ٍ",
"ٌ",
"ً",
"ّ",
"ٖ",
"ٰ",
"ٓ",
"ِ",
"ُ",
"َ",
"ـ"
]
]
]
}
],
"locale": "fa",
"name": "Persian"
}

583
data/osk-layouts/is.json Normal file
View File

@ -0,0 +1,583 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ë",
"è",
"ê",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t",
"þ"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
],
[
"i",
"í",
"ï",
"î",
"ì",
"į",
"ī"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"ä",
"æ",
"å",
"à",
"â",
"ã",
"ā"
],
[
"s"
],
[
"d",
"ð"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ë",
"È",
"Ê",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T",
"Þ"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
],
[
"I",
"Í",
"Ï",
"Î",
"Ì",
"Į",
"Ī"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"Ä",
"Æ",
"Å",
"À",
"Â",
"Ã",
"Ā"
],
[
"S"
],
[
"D",
"Ð"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "is",
"name": "Icelandic"
}

580
data/osk-layouts/it.json Normal file
View File

@ -0,0 +1,580 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ê",
"ë",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ù",
"ú",
"û",
"ü",
"ū"
],
[
"i",
"ì",
"í",
"î",
"ï",
"į",
"ī"
],
[
"o",
"ò",
"ó",
"ô",
"ö",
"õ",
"œ",
"ø",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ê",
"Ë",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ù",
"Ú",
"Û",
"Ü",
"Ū"
],
[
"I",
"Ì",
"Í",
"Î",
"Ï",
"Į",
"Ī"
],
[
"O",
"Ò",
"Ó",
"Ô",
"Ö",
"Õ",
"Œ",
"Ø",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "it",
"name": "Italian"
}

577
data/osk-layouts/ke.json Normal file
View File

@ -0,0 +1,577 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ê",
"ë",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"û",
"ü",
"ù",
"ú",
"ū"
],
[
"i",
"î",
"ï",
"í",
"ī",
"ì"
],
[
"o",
"ô",
"ö",
"ò",
"ó",
"œ",
"ø",
"ō",
"õ"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"ß"
],
[
"d"
],
[
"f"
],
[
"g",
"g'"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ê",
"Ë",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Û",
"Ü",
"Ù",
"Ú",
"Ū"
],
[
"I",
"Î",
"Ï",
"Í",
"Ī",
"Ì"
],
[
"O",
"Ô",
"Ö",
"Ò",
"Ó",
"Œ",
"Ø",
"Ō",
"Õ"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"SS"
],
[
"D"
],
[
"F"
],
[
"G",
"G'"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "sw",
"name": "Swahili"
}

547
data/osk-layouts/kg.json Normal file
View File

@ -0,0 +1,547 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"й"
],
[
"ц"
],
[
"у",
"ү"
],
[
"к"
],
[
"е",
"ё"
],
[
"н",
"ң"
],
[
"г"
],
[
"ш"
],
[
"щ"
],
[
"з"
],
[
"х"
]
],
[
[
"ф"
],
[
"ы"
],
[
"в"
],
[
"а"
],
[
"п"
],
[
"р"
],
[
"о",
"ө"
],
[
"л"
],
[
"д"
],
[
"ж"
],
[
"э"
]
],
[
[
"я"
],
[
"ч"
],
[
"с"
],
[
"м"
],
[
"и"
],
[
"т"
],
[
"ь",
"ъ"
],
[
"б"
],
[
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Й"
],
[
"Ц"
],
[
"У",
"Ү"
],
[
"К"
],
[
"Е",
"Ё"
],
[
"Н",
"Ң"
],
[
"Г"
],
[
"Ш"
],
[
"Щ"
],
[
"З"
],
[
"Х"
]
],
[
[
"Ф"
],
[
"Ы"
],
[
"В"
],
[
"А"
],
[
"П"
],
[
"Р"
],
[
"О",
"Ө"
],
[
"Л"
],
[
"Д"
],
[
"Ж"
],
[
"Э"
]
],
[
[
"Я"
],
[
"Ч"
],
[
"С"
],
[
"М"
],
[
"И"
],
[
"Т"
],
[
"Ь",
"Ъ"
],
[
"Б"
],
[
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ky",
"name": "Kirghiz"
}

481
data/osk-layouts/kh.json Normal file
View File

@ -0,0 +1,481 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"១",
"៱"
],
[
"២",
"៲"
],
[
"៣",
"៳"
],
[
"៤",
"៴"
],
[
"៥",
"៵"
],
[
"៦",
"៶"
],
[
"៧",
"៷"
],
[
"៨",
"៸"
],
[
"៩",
"៹"
],
[
"០",
"៰"
],
[
"ឥ",
"",
"ឦ"
],
[
"ឲ",
"ឱ"
]
],
[
[
"ឆ"
],
[
"ឹ"
],
[
"េ"
],
[
"រ"
],
[
"ត"
],
[
"យ"
],
[
"ុ"
],
[
"ិ"
],
[
"ោ"
],
[
"ផ"
],
[
"ៀ"
],
[
"ឪ",
"ឧ",
"ឱ",
"ឳ",
"ឩ",
"ឨ"
]
],
[
[
"ា"
],
[
"ស"
],
[
"ដ"
],
[
"ថ"
],
[
"ង"
],
[
"ហ"
],
[
"្"
],
[
"ក"
],
[
"ល"
],
[
"ើ"
],
[
"់"
],
[
"ឮ",
"ឭ",
"ឰ"
]
],
[
[
"ឋ"
],
[
"ខ"
],
[
"ច"
],
[
"វ"
],
[
"ប"
],
[
"ន"
],
[
"ម"
],
[
"ុំ"
],
[
"។"
],
[
"៊"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"៛",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "km",
"name": "Khmer"
}

472
data/osk-layouts/la.json Normal file
View File

@ -0,0 +1,472 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ຢ",
"໑"
],
[
"ຟ",
"໒"
],
[
"ໂ",
"໓"
],
[
"ຖ",
"໔"
],
[
"ຸ"
],
[
"ູ"
],
[
"ຄ",
"໕"
],
[
"ຕ",
"໖"
],
[
"ຈ",
"໗"
],
[
"ຂ",
"໘"
],
[
"ຊ",
"໙"
],
[
"ໍ"
]
],
[
[
"ົ"
],
[
"ໄ",
""
],
[
"ຳ"
],
[
"ພ"
],
[
"ະ"
],
[
"ິ"
],
[
"ີ"
],
[
"ຮ"
],
[
"ນ"
],
[
"ຍ"
],
[
"ບ"
],
[
"ລ"
]
],
[
[
"ັ"
],
[
"ຫ"
],
[
"ກ"
],
[
"ດ"
],
[
"ເ"
],
[
"້"
],
[
"່"
],
[
"າ"
],
[
"ສ"
],
[
"ວ"
],
[
"ງ"
],
[
"“"
]
],
[
[
"ຜ"
],
[
"ປ"
],
[
"ແ"
],
[
"ອ"
],
[
"ຶ"
],
[
"ື"
],
[
"ທ"
],
[
"ມ"
],
[
"ໃ"
],
[
"ຝ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₭",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "lo",
"name": "Lao"
}

603
data/osk-layouts/latam.json Normal file
View File

@ -0,0 +1,603 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ë",
"ê",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ú",
"ü",
"ù",
"û",
"ū"
],
[
"i",
"í",
"ï",
"ì",
"î",
"į",
"ī"
],
[
"o",
"ó",
"ò",
"ö",
"ô",
"õ",
"ø",
"œ",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"á",
"à",
"ä",
"â",
"ã",
"å",
"ą",
"æ",
"ā",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
],
[
"ñ"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
";",
"!",
",",
"?",
":",
"¡",
"@",
"¿"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ë",
"Ê",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ú",
"Ü",
"Ù",
"Û",
"Ū"
],
[
"I",
"Í",
"Ï",
"Ì",
"Î",
"Į",
"Ī"
],
[
"O",
"Ó",
"Ò",
"Ö",
"Ô",
"Õ",
"Ø",
"Œ",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"Á",
"À",
"Ä",
"Â",
"Ã",
"Å",
"Ą",
"Æ",
"Ā",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
],
[
"Ñ"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
";",
"!",
",",
"?",
":",
"¡",
"@",
"¿"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
",",
"!",
"¡"
],
[
".",
"?",
"¿"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
",",
"!",
"¡"
],
[
".",
"?",
"¿"
]
]
]
}
],
"locale": "es-US",
"name": "Spanish United States"
}

647
data/osk-layouts/lt.json Normal file
View File

@ -0,0 +1,647 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"ė",
"ę",
"ē",
"è",
"é",
"ê",
"ë",
"ě"
],
[
"r",
"ŗ",
"ř",
"ŕ"
],
[
"t",
"ţ",
"ť"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ū",
"ų",
"ü",
"ū",
"ù",
"ú",
"û",
"ů",
"ű"
],
[
"i",
"į",
"ī",
"ì",
"í",
"î",
"ï",
"ı"
],
[
"o",
"ö",
"õ",
"ò",
"ó",
"ô",
"œ",
"ő",
"ø"
],
[
"p"
]
],
[
[
"a",
"ą",
"ä",
"ā",
"à",
"á",
"â",
"ã",
"å",
"æ"
],
[
"s",
"š",
"ß",
"ś",
"ş"
],
[
"d",
"ď"
],
[
"f"
],
[
"g",
"ģ",
"ğ"
],
[
"h"
],
[
"j"
],
[
"k",
"ķ"
],
[
"l",
"ļ",
"ł",
"ĺ",
"ľ"
]
],
[
[
"z",
"ž",
"ż",
"ź"
],
[
"x"
],
[
"c",
"č",
"ç",
"ć"
],
[
"v"
],
[
"b"
],
[
"n",
"ņ",
"ñ",
"ń",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"Ė",
"Ę",
"Ē",
"È",
"É",
"Ê",
"Ë",
"Ě"
],
[
"R",
"Ŗ",
"Ř",
"Ŕ"
],
[
"T",
"Ţ",
"Ť"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ū",
"Ų",
"Ü",
"Ū",
"Ù",
"Ú",
"Û",
"Ů",
"Ű"
],
[
"I",
"Į",
"Ī",
"Ì",
"Í",
"Î",
"Ï",
"I"
],
[
"O",
"Ö",
"Õ",
"Ò",
"Ó",
"Ô",
"Œ",
"Ő",
"Ø"
],
[
"P"
]
],
[
[
"A",
"Ą",
"Ä",
"Ā",
"À",
"Á",
"Â",
"Ã",
"Å",
"Æ"
],
[
"S",
"Š",
"SS",
"Ś",
"Ş"
],
[
"D",
"Ď"
],
[
"F"
],
[
"G",
"Ģ",
"Ğ"
],
[
"H"
],
[
"J"
],
[
"K",
"Ķ"
],
[
"L",
"Ļ",
"Ł",
"Ĺ",
"Ľ"
]
],
[
[
"Z",
"Ž",
"Ż",
"Ź"
],
[
"X"
],
[
"C",
"Č",
"Ç",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N",
"Ņ",
"Ñ",
"Ń",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "lt",
"name": "Lithuanian"
}

645
data/osk-layouts/lv.json Normal file
View File

@ -0,0 +1,645 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"ē",
"ė",
"è",
"é",
"ê",
"ë",
"ę",
"ě"
],
[
"r",
"ŗ",
"ř",
"ŕ"
],
[
"t",
"ţ",
"ť"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ū",
"ų",
"ù",
"ú",
"û",
"ü",
"ů",
"ű"
],
[
"i",
"ī",
"į",
"ì",
"í",
"î",
"ï",
"ı"
],
[
"o",
"ò",
"ó",
"ô",
"õ",
"ö",
"œ",
"ő",
"ø"
],
[
"p"
]
],
[
[
"a",
"ā",
"à",
"á",
"â",
"ã",
"ä",
"å",
"æ",
"ą"
],
[
"s",
"š",
"ß",
"ś",
"ş"
],
[
"d",
"ď"
],
[
"f"
],
[
"g",
"ģ",
"ğ"
],
[
"h"
],
[
"j"
],
[
"k",
"ķ"
],
[
"l",
"ļ",
"ł",
"ĺ",
"ľ"
]
],
[
[
"z",
"ž",
"ż",
"ź"
],
[
"x"
],
[
"c",
"č",
"ç",
"ć"
],
[
"v"
],
[
"b"
],
[
"n",
"ņ",
"ñ",
"ń",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"Ē",
"Ė",
"È",
"É",
"Ê",
"Ë",
"Ę",
"Ě"
],
[
"R",
"Ŗ",
"Ř",
"Ŕ"
],
[
"T",
"Ţ",
"Ť"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ū",
"Ų",
"Ù",
"Ú",
"Û",
"Ü",
"Ů",
"Ű"
],
[
"I",
"Ī",
"Į",
"Ì",
"Í",
"Î",
"Ï",
"I"
],
[
"O",
"Ò",
"Ó",
"Ô",
"Õ",
"Ö",
"Œ",
"Ő",
"Ø"
],
[
"P"
]
],
[
[
"A",
"Ā",
"À",
"Á",
"Â",
"Ã",
"Ä",
"Å",
"Æ",
"Ą"
],
[
"S",
"Š",
"SS",
"Ś",
"Ş"
],
[
"D",
"Ď"
],
[
"F"
],
[
"G",
"Ģ",
"Ğ"
],
[
"H"
],
[
"J"
],
[
"K",
"Ķ"
],
[
"L",
"Ļ",
"Ł",
"Ĺ",
"Ľ"
]
],
[
[
"Z",
"Ž",
"Ż",
"Ź"
],
[
"X"
],
[
"C",
"Č",
"Ç",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N",
"Ņ",
"Ñ",
"Ń",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "lv",
"name": "Latvian"
}

541
data/osk-layouts/mk.json Normal file
View File

@ -0,0 +1,541 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"љ"
],
[
"њ"
],
[
"е",
"ѐ"
],
[
"р"
],
[
"т"
],
[
"ѕ"
],
[
"у"
],
[
"и",
"ѝ"
],
[
"о"
],
[
"п"
],
[
"ш"
]
],
[
[
"а"
],
[
"с"
],
[
"д"
],
[
"ф"
],
[
"г"
],
[
"х"
],
[
"ј"
],
[
"к"
],
[
"л"
],
[
"ч"
],
[
"ќ"
]
],
[
[
"з"
],
[
"џ"
],
[
"ц"
],
[
"в"
],
[
"б"
],
[
"н"
],
[
"м"
],
[
"ѓ"
],
[
"ж"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Љ"
],
[
"Њ"
],
[
"Е",
"Ѐ"
],
[
"Р"
],
[
"Т"
],
[
"Ѕ"
],
[
"У"
],
[
"И",
"Ѝ"
],
[
"О"
],
[
"П"
],
[
"Ш"
]
],
[
[
"А"
],
[
"С"
],
[
"Д"
],
[
"Ф"
],
[
"Г"
],
[
"Х"
],
[
"Ј"
],
[
"К"
],
[
"Л"
],
[
"Ч"
],
[
"Ќ"
]
],
[
[
"З"
],
[
"Џ"
],
[
"Ц"
],
[
"В"
],
[
"Б"
],
[
"Н"
],
[
"М"
],
[
"Ѓ"
],
[
"Ж"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "mk",
"name": "Macedonian"
}

547
data/osk-layouts/mn.json Normal file
View File

@ -0,0 +1,547 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ф"
],
[
"ц"
],
[
"у"
],
[
"ж"
],
[
"э"
],
[
"н"
],
[
"г"
],
[
"ш",
"щ"
],
[
"ү"
],
[
"з"
],
[
"к"
]
],
[
[
"й"
],
[
"ы"
],
[
"б"
],
[
"ө"
],
[
"а"
],
[
"х"
],
[
"р"
],
[
"о"
],
[
"л"
],
[
"д"
],
[
"п"
]
],
[
[
"я"
],
[
"ч"
],
[
"ё",
"е"
],
[
"с"
],
[
"м"
],
[
"и"
],
[
"т"
],
[
"ь",
"ъ"
],
[
"в",
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Ф"
],
[
"Ц"
],
[
"У"
],
[
"Ж"
],
[
"Э"
],
[
"Н"
],
[
"Г"
],
[
"Ш",
"Щ"
],
[
"Ү"
],
[
"З"
],
[
"К"
]
],
[
[
"Й"
],
[
"Ы"
],
[
"Б"
],
[
"Ө"
],
[
"А"
],
[
"Х"
],
[
"Р"
],
[
"О"
],
[
"Л"
],
[
"Д"
],
[
"П"
]
],
[
[
"Я"
],
[
"Ч"
],
[
"Ё",
"Е"
],
[
"С"
],
[
"М"
],
[
"И"
],
[
"Т"
],
[
"Ь",
"Ъ"
],
[
"В",
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₮",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "mn",
"name": "Mongolian"
}

507
data/osk-layouts/my.json Normal file
View File

@ -0,0 +1,507 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ms",
"name": "Malay"
}

584
data/osk-layouts/nl.json Normal file
View File

@ -0,0 +1,584 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ë",
"ê",
"è",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y",
"ij"
],
[
"u",
"ú",
"ü",
"û",
"ù",
"ū"
],
[
"i",
"í",
"ï",
"ì",
"î",
"į",
"ī",
"ij"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"ä",
"â",
"à",
"æ",
"ã",
"å",
"ā"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ë",
"Ê",
"È",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y",
"IJ"
],
[
"U",
"Ú",
"Ü",
"Û",
"Ù",
"Ū"
],
[
"I",
"Í",
"Ï",
"Ì",
"Î",
"Į",
"Ī",
"IJ"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"Ä",
"Â",
"À",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "nl",
"name": "Dutch"
}

507
data/osk-layouts/no.json Normal file
View File

@ -0,0 +1,507 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "nb",
"name": "Norwegian Bokmål"
}

507
data/osk-layouts/ph.json Normal file
View File

@ -0,0 +1,507 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "fil",
"name": "Filipino"
}

579
data/osk-layouts/pl.json Normal file
View File

@ -0,0 +1,579 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"ę",
"è",
"é",
"ê",
"ë",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o",
"ó",
"ö",
"ô",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"ą",
"á",
"à",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"ś",
"ß",
"š"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l",
"ł"
]
],
[
[
"z",
"ż",
"ź",
"ž"
],
[
"x"
],
[
"c",
"ć",
"ç",
"č"
],
[
"v"
],
[
"b"
],
[
"n",
"ń",
"ñ"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"Ę",
"È",
"É",
"Ê",
"Ë",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O",
"Ó",
"Ö",
"Ô",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Ą",
"Á",
"À",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"Ś",
"SS",
"Š"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L",
"Ł"
]
],
[
[
"Z",
"Ż",
"Ź",
"Ž"
],
[
"X"
],
[
"C",
"Ć",
"Ç",
"Č"
],
[
"V"
],
[
"B"
],
[
"N",
"Ń",
"Ñ"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "pl",
"name": "Polish"
}

584
data/osk-layouts/pt.json Normal file
View File

@ -0,0 +1,584 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ê",
"è",
"ę",
"ė",
"ē",
"ë"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ú",
"ü",
"ù",
"û",
"ū"
],
[
"i",
"í",
"î",
"ì",
"ï",
"į",
"ī"
],
[
"o",
"ó",
"õ",
"ô",
"ò",
"ö",
"œ",
"ø",
"ō",
"º"
],
[
"p"
]
],
[
[
"a",
"á",
"ã",
"à",
"â",
"ä",
"å",
"æ",
"ª"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"č",
"ć"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ê",
"È",
"Ę",
"Ė",
"Ē",
"Ë"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ú",
"Ü",
"Ù",
"Û",
"Ū"
],
[
"I",
"Í",
"Î",
"Ì",
"Ï",
"Į",
"Ī"
],
[
"O",
"Ó",
"Õ",
"Ô",
"Ò",
"Ö",
"Œ",
"Ø",
"Ō",
"º"
],
[
"P"
]
],
[
[
"A",
"Á",
"Ã",
"À",
"Â",
"Ä",
"Å",
"Æ",
"ª"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Č",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "pt-PT",
"name": "Portuguese Portugal"
}

547
data/osk-layouts/ro.json Normal file
View File

@ -0,0 +1,547 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t",
"ț"
],
[
"y"
],
[
"u"
],
[
"i",
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
[
"o"
],
[
"p"
]
],
[
[
"a",
"â",
"ã",
"ă",
"à",
"á",
"ä",
"æ",
"å",
"ā"
],
[
"s",
"ș",
"ß",
"ś",
"š"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T",
"Ț"
],
[
"Y"
],
[
"U"
],
[
"I",
"Î",
"Ï",
"Ì",
"Í",
"Į",
"Ī"
],
[
"O"
],
[
"P"
]
],
[
[
"A",
"Â",
"Ã",
"Ă",
"À",
"Á",
"Ä",
"Æ",
"Å",
"Ā"
],
[
"S",
"Ș",
"SS",
"Ś",
"Š"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ro",
"name": "Romanian"
}

541
data/osk-layouts/rs.json Normal file
View File

@ -0,0 +1,541 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"љ"
],
[
"њ"
],
[
"е",
"ѐ"
],
[
"р"
],
[
"т"
],
[
"з"
],
[
"у"
],
[
"и",
"ѝ"
],
[
"о"
],
[
"п"
],
[
"ш"
]
],
[
[
"а"
],
[
"с"
],
[
"д"
],
[
"ф"
],
[
"г"
],
[
"х"
],
[
"ј"
],
[
"к"
],
[
"л"
],
[
"ч"
],
[
"ћ"
]
],
[
[
"ѕ"
],
[
"џ"
],
[
"ц"
],
[
"в"
],
[
"б"
],
[
"н"
],
[
"м"
],
[
"ђ"
],
[
"ж"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Љ"
],
[
"Њ"
],
[
"Е",
"Ѐ"
],
[
"Р"
],
[
"Т"
],
[
"З"
],
[
"У"
],
[
"И",
"Ѝ"
],
[
"О"
],
[
"П"
],
[
"Ш"
]
],
[
[
"А"
],
[
"С"
],
[
"Д"
],
[
"Ф"
],
[
"Г"
],
[
"Х"
],
[
"Ј"
],
[
"К"
],
[
"Л"
],
[
"Ч"
],
[
"Ћ"
]
],
[
[
"Ѕ"
],
[
"Џ"
],
[
"Ц"
],
[
"В"
],
[
"Б"
],
[
"Н"
],
[
"М"
],
[
"Ђ"
],
[
"Ж"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "sr",
"name": "Serbian"
}

541
data/osk-layouts/ru.json Normal file
View File

@ -0,0 +1,541 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"й"
],
[
"ц"
],
[
"у"
],
[
"к"
],
[
"е",
"ё"
],
[
"н"
],
[
"г"
],
[
"ш"
],
[
"щ"
],
[
"з"
],
[
"х"
]
],
[
[
"ф"
],
[
"ы"
],
[
"в"
],
[
"а"
],
[
"п"
],
[
"р"
],
[
"о"
],
[
"л"
],
[
"д"
],
[
"ж"
],
[
"э"
]
],
[
[
"я"
],
[
"ч"
],
[
"с"
],
[
"м"
],
[
"и"
],
[
"т"
],
[
"ь",
"ъ"
],
[
"б"
],
[
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Й"
],
[
"Ц"
],
[
"У"
],
[
"К"
],
[
"Е",
"Ё"
],
[
"Н"
],
[
"Г"
],
[
"Ш"
],
[
"Щ"
],
[
"З"
],
[
"Х"
]
],
[
[
"Ф"
],
[
"Ы"
],
[
"В"
],
[
"А"
],
[
"П"
],
[
"Р"
],
[
"О"
],
[
"Л"
],
[
"Д"
],
[
"Ж"
],
[
"Э"
]
],
[
[
"Я"
],
[
"Ч"
],
[
"С"
],
[
"М"
],
[
"И"
],
[
"Т"
],
[
"Ь",
"Ъ"
],
[
"Б"
],
[
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "ru",
"name": "Russian"
}

624
data/osk-layouts/se.json Normal file
View File

@ -0,0 +1,624 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"ę"
],
[
"r",
"ř"
],
[
"t",
"ť",
"þ"
],
[
"y",
"ý",
"ÿ",
"ü"
],
[
"u",
"ü",
"ú",
"ù",
"û",
"ū"
],
[
"i",
"í",
"ì",
"î",
"ï"
],
[
"o",
"ó",
"ò",
"ô",
"õ",
"ō"
],
[
"p"
],
[
"å"
]
],
[
[
"a",
"á",
"à",
"â",
"ą",
"ã"
],
[
"s",
"ś",
"š",
"ş",
"ß"
],
[
"d",
"ð",
"ď"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l",
"ł"
],
[
"ö",
"ø",
"œ"
],
[
"ä",
"æ"
]
],
[
[
"z",
"ź",
"ž",
"ż"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n",
"ń",
"ñ",
"ň"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"Ę"
],
[
"R",
"Ř"
],
[
"T",
"Ť",
"Þ"
],
[
"Y",
"Ý",
"Ÿ",
"Ü"
],
[
"U",
"Ü",
"Ú",
"Ù",
"Û",
"Ū"
],
[
"I",
"Í",
"Ì",
"Î",
"Ï"
],
[
"O",
"Ó",
"Ò",
"Ô",
"Õ",
"Ō"
],
[
"P"
],
[
"Å"
]
],
[
[
"A",
"Á",
"À",
"Â",
"Ą",
"Ã"
],
[
"S",
"Ś",
"Š",
"Ş",
"SS"
],
[
"D",
"Ð",
"Ď"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L",
"Ł"
],
[
"Ö",
"Ø",
"Œ"
],
[
"Ä",
"Æ"
]
],
[
[
"Z",
"Ź",
"Ž",
"Ż"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N",
"Ń",
"Ñ",
"Ň"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "sv",
"name": "Swedish"
}

518
data/osk-layouts/si.json Normal file
View File

@ -0,0 +1,518 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u"
],
[
"i"
],
[
"o"
],
[
"p"
]
],
[
[
"a"
],
[
"s",
"š"
],
[
"d",
"đ"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z",
"ž"
],
[
"x"
],
[
"c",
"č",
"ć"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U"
],
[
"I"
],
[
"O"
],
[
"P"
]
],
[
[
"A"
],
[
"S",
"Š"
],
[
"D",
"Đ"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z",
"Ž"
],
[
"X"
],
[
"C",
"Č",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "sl",
"name": "Slovenian"
}

648
data/osk-layouts/sk.json Normal file
View File

@ -0,0 +1,648 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"ě",
"ē",
"ė",
"è",
"ê",
"ë",
"ę"
],
[
"r",
"ŕ",
"ř",
"ŗ"
],
[
"t",
"ť",
"ţ"
],
[
"y",
"ý",
"ÿ"
],
[
"u",
"ú",
"ů",
"ü",
"ū",
"ų",
"ù",
"û",
"ű"
],
[
"i",
"í",
"ī",
"į",
"ì",
"î",
"ï",
"ı"
],
[
"o",
"ô",
"ó",
"ö",
"ò",
"õ",
"œ",
"ő",
"ø"
],
[
"p"
]
],
[
[
"a",
"á",
"ä",
"ā",
"à",
"â",
"ã",
"å",
"æ",
"ą"
],
[
"s",
"š",
"ß",
"ś",
"ş"
],
[
"d",
"ď"
],
[
"f"
],
[
"g",
"ģ",
"ğ"
],
[
"h"
],
[
"j"
],
[
"k",
"ķ"
],
[
"l",
"ľ",
"ĺ",
"ļ",
"ł"
]
],
[
[
"z",
"ž",
"ż",
"ź"
],
[
"x"
],
[
"c",
"č",
"ç",
"ć"
],
[
"v"
],
[
"b"
],
[
"n",
"ň",
"ņ",
"ñ",
"ń",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"Ě",
"Ē",
"Ė",
"È",
"Ê",
"Ë",
"Ę"
],
[
"R",
"Ŕ",
"Ř",
"Ŗ"
],
[
"T",
"Ť",
"Ţ"
],
[
"Y",
"Ý",
"Ÿ"
],
[
"U",
"Ú",
"Ů",
"Ü",
"Ū",
"Ų",
"Ù",
"Û",
"Ű"
],
[
"I",
"Í",
"Ī",
"Į",
"Ì",
"Î",
"Ï",
"I"
],
[
"O",
"Ô",
"Ó",
"Ö",
"Ò",
"Õ",
"Œ",
"Ő",
"Ø"
],
[
"P"
]
],
[
[
"A",
"Á",
"Ä",
"Ā",
"À",
"Â",
"Ã",
"Å",
"Æ",
"Ą"
],
[
"S",
"Š",
"SS",
"Ś",
"Ş"
],
[
"D",
"Ď"
],
[
"F"
],
[
"G",
"Ģ",
"Ğ"
],
[
"H"
],
[
"J"
],
[
"K",
"Ķ"
],
[
"L",
"Ľ",
"Ĺ",
"Ļ",
"Ł"
]
],
[
[
"Z",
"Ž",
"Ż",
"Ź"
],
[
"X"
],
[
"C",
"Č",
"Ç",
"Ć"
],
[
"V"
],
[
"B"
],
[
"N",
"Ň",
"Ņ",
"Ñ",
"Ń",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "sk",
"name": "Slovak"
}

472
data/osk-layouts/th.json Normal file
View File

@ -0,0 +1,472 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"ๅ"
],
[
"/",
"๑"
],
[
"_",
"๒"
],
[
"ภ",
"๓"
],
[
"ถ",
"๔"
],
[
"ุ"
],
[
"ึ"
],
[
"ค",
"๕"
],
[
"ต",
"๖"
],
[
"จ",
"๗"
],
[
"ข",
"๘"
],
[
"ช",
"๙"
]
],
[
[
"ๆ",
""
],
[
"ไ"
],
[
"ำ"
],
[
"พ"
],
[
"ะ"
],
[
"ั"
],
[
"ี"
],
[
"ร"
],
[
"น"
],
[
"ย"
],
[
"บ"
],
[
"ล"
]
],
[
[
"ฟ"
],
[
"ห"
],
[
"ก"
],
[
"ด"
],
[
"เ"
],
[
"้"
],
[
"่"
],
[
"า"
],
[
"ส"
],
[
"ว"
],
[
"ง"
],
[
"ฃ"
]
],
[
[
"ผ"
],
[
"ป"
],
[
"แ"
],
[
"อ"
],
[
"ิ"
],
[
"ื"
],
[
"ท"
],
[
"ม"
],
[
"ใ"
],
[
"ฝ"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"฿",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "th",
"name": "Thai"
}

566
data/osk-layouts/tr.json Normal file
View File

@ -0,0 +1,566 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"ü",
"û",
"ù",
"ú",
"ū"
],
[
"i",
"ı",
"î",
"ï",
"ì",
"í",
"į",
"ī"
],
[
"o",
"ö",
"ô",
"œ",
"ò",
"ó",
"õ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"â"
],
[
"s",
"ş",
"ß",
"ś",
"š"
],
[
"d"
],
[
"f"
],
[
"g",
"ğ"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç",
"ć",
"č"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Ü",
"Û",
"Ù",
"Ú",
"Ū"
],
[
"İ",
"I",
"Î",
"Ï",
"Ì",
"Í",
"Į",
"Ī"
],
[
"O",
"Ö",
"Ô",
"Œ",
"Ò",
"Ó",
"Õ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Â"
],
[
"S",
"Ş",
"SS",
"Ś",
"Š"
],
[
"D"
],
[
"F"
],
[
"G",
"Ğ"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç",
"Ć",
"Č"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"€",
"¢",
"£",
"$",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "tr",
"name": "Turkish"
}

545
data/osk-layouts/ua.json Normal file
View File

@ -0,0 +1,545 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"й"
],
[
"ц"
],
[
"у"
],
[
"к"
],
[
"е"
],
[
"н"
],
[
"г",
"ґ"
],
[
"ш"
],
[
"щ"
],
[
"з"
],
[
"х"
]
],
[
[
"ф"
],
[
"і",
"ї"
],
[
"в"
],
[
"а"
],
[
"п"
],
[
"р"
],
[
"о"
],
[
"л"
],
[
"д"
],
[
"ж"
],
[
"є"
]
],
[
[
"я"
],
[
"ч"
],
[
"с"
],
[
"м"
],
[
"и"
],
[
"т"
],
[
"ь",
"ъ"
],
[
"б"
],
[
"ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Й"
],
[
"Ц"
],
[
"У"
],
[
"К"
],
[
"Е"
],
[
"Н"
],
[
"Г",
"Ґ"
],
[
"Ш"
],
[
"Щ"
],
[
"З"
],
[
"Х"
]
],
[
[
"Ф"
],
[
"І",
"Ї"
],
[
"В"
],
[
"А"
],
[
"П"
],
[
"Р"
],
[
"О"
],
[
"Л"
],
[
"Д"
],
[
"Ж"
],
[
"Є"
]
],
[
[
"Я"
],
[
"Ч"
],
[
"С"
],
[
"М"
],
[
"И"
],
[
"Т"
],
[
"Ь",
"Ъ"
],
[
"Б"
],
[
"Ю"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₴",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "uk",
"name": "Ukrainian"
}

576
data/osk-layouts/uk.json Normal file
View File

@ -0,0 +1,576 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ê",
"ë",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"û",
"ü",
"ù",
"ú",
"ū"
],
[
"i",
"î",
"ï",
"í",
"ī",
"ì"
],
[
"o",
"ô",
"ö",
"ò",
"ó",
"œ",
"ø",
"ō",
"õ"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"ß"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ê",
"Ë",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Û",
"Ü",
"Ù",
"Ú",
"Ū"
],
[
"I",
"Î",
"Ï",
"Í",
"Ī",
"Ì"
],
[
"O",
"Ô",
"Ö",
"Ò",
"Ó",
"Œ",
"Ø",
"Ō",
"Õ"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"SS"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"£",
"¢",
"$",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"€"
],
[
"¥"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "en-GB",
"name": "English Great Britain"
}

575
data/osk-layouts/us.json Normal file
View File

@ -0,0 +1,575 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ê",
"ë",
"ē"
],
[
"r"
],
[
"t"
],
[
"y"
],
[
"u",
"û",
"ü",
"ù",
"ú",
"ū"
],
[
"i",
"î",
"ï",
"í",
"ī",
"ì"
],
[
"o",
"ô",
"ö",
"ò",
"ó",
"œ",
"ø",
"ō",
"õ"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"â",
"ä",
"æ",
"ã",
"å",
"ā"
],
[
"s",
"ß"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c",
"ç"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ê",
"Ë",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y"
],
[
"U",
"Û",
"Ü",
"Ù",
"Ú",
"Ū"
],
[
"I",
"Î",
"Ï",
"Í",
"Ī",
"Ì"
],
[
"O",
"Ô",
"Ö",
"Ò",
"Ó",
"Œ",
"Ø",
"Ō",
"Õ"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Â",
"Ä",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S",
"SS"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C",
"Ç"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "en",
"name": "English United States"
}

643
data/osk-layouts/vn.json Normal file
View File

@ -0,0 +1,643 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"è",
"é",
"ẻ",
"ẽ",
"ẹ",
"ê",
"ề",
"ế",
"ể",
"ễ",
"ệ"
],
[
"r"
],
[
"t"
],
[
"y",
"ỳ",
"ý",
"ỷ",
"ỹ",
"ỵ"
],
[
"u",
"ù",
"ú",
"ủ",
"ũ",
"ụ",
"ư",
"ừ",
"ứ",
"ử",
"ữ",
"ự"
],
[
"i",
"ì",
"í",
"ỉ",
"ĩ",
"ị"
],
[
"o",
"ò",
"ó",
"ỏ",
"õ",
"ọ",
"ô",
"ồ",
"ố",
"ổ",
"ỗ",
"ộ",
"ơ",
"ờ",
"ớ",
"ở",
"ỡ",
"ợ"
],
[
"p"
]
],
[
[
"a",
"à",
"á",
"ả",
"ã",
"ạ",
"ă",
"ằ",
"ắ",
"ẳ",
"ẵ",
"ặ",
"â",
"ầ",
"ấ",
"ẩ",
"ẫ",
"ậ"
],
[
"s"
],
[
"d",
"đ"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"È",
"É",
"Ẻ",
"Ẽ",
"Ẹ",
"Ê",
"Ề",
"Ế",
"Ể",
"Ễ",
"Ệ"
],
[
"R"
],
[
"T"
],
[
"Y",
"Ỳ",
"Ý",
"Ỷ",
"Ỹ",
"Ỵ"
],
[
"U",
"Ù",
"Ú",
"Ủ",
"Ũ",
"Ụ",
"Ư",
"Ừ",
"Ứ",
"Ử",
"Ữ",
"Ự"
],
[
"I",
"Ì",
"Í",
"Ỉ",
"Ĩ",
"Ị"
],
[
"O",
"Ò",
"Ó",
"Ỏ",
"Õ",
"Ọ",
"Ô",
"Ồ",
"Ố",
"Ổ",
"Ỗ",
"Ộ",
"Ơ",
"Ờ",
"Ớ",
"Ở",
"Ỡ",
"Ợ"
],
[
"P"
]
],
[
[
"A",
"À",
"Á",
"Ả",
"Ã",
"Ạ",
"Ă",
"Ằ",
"Ắ",
"Ẳ",
"Ẵ",
"Ặ",
"Â",
"Ầ",
"Ấ",
"Ẩ",
"Ẫ",
"Ậ"
],
[
"S"
],
[
"D",
"Đ"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"₫",
"$",
"¢",
"€",
"£",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"€"
],
[
"$",
"¢"
],
[
"¢"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "vi",
"name": "Vietnamese"
}

589
data/osk-layouts/za.json Normal file
View File

@ -0,0 +1,589 @@
{
"levels": [
{
"level": "",
"mode": "default",
"rows": [
[
[
"q"
],
[
"w"
],
[
"e",
"é",
"è",
"ê",
"ë",
"ę",
"ė",
"ē"
],
[
"r"
],
[
"t"
],
[
"y",
"ý",
"ŷ",
"ÿ",
"ij"
],
[
"u",
"ú",
"û",
"ü",
"ù",
"ū"
],
[
"i",
"í",
"ì",
"ï",
"î",
"į",
"ī",
"ij"
],
[
"o",
"ó",
"ô",
"ö",
"ò",
"õ",
"œ",
"ø",
"ō"
],
[
"p"
]
],
[
[
"a",
"á",
"â",
"ä",
"à",
"æ",
"ã",
"å",
"ā"
],
[
"s"
],
[
"d"
],
[
"f"
],
[
"g"
],
[
"h"
],
[
"j"
],
[
"k"
],
[
"l"
]
],
[
[
"z"
],
[
"x"
],
[
"c"
],
[
"v"
],
[
"b"
],
[
"n",
"ñ",
"ń"
],
[
"m"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "shift",
"mode": "latched",
"rows": [
[
[
"Q"
],
[
"W"
],
[
"E",
"É",
"È",
"Ê",
"Ë",
"Ę",
"Ė",
"Ē"
],
[
"R"
],
[
"T"
],
[
"Y",
"Ý",
"Ŷ",
"Ÿ",
"IJ"
],
[
"U",
"Ú",
"Û",
"Ü",
"Ù",
"Ū"
],
[
"I",
"Í",
"Ì",
"Ï",
"Î",
"Į",
"Ī",
"IJ"
],
[
"O",
"Ó",
"Ô",
"Ö",
"Ò",
"Õ",
"Œ",
"Ø",
"Ō"
],
[
"P"
]
],
[
[
"A",
"Á",
"Â",
"Ä",
"À",
"Æ",
"Ã",
"Å",
"Ā"
],
[
"S"
],
[
"D"
],
[
"F"
],
[
"G"
],
[
"H"
],
[
"J"
],
[
"K"
],
[
"L"
]
],
[
[
"Z"
],
[
"X"
],
[
"C"
],
[
"V"
],
[
"B"
],
[
"N",
"Ñ",
"Ń"
],
[
"M"
]
],
[
[
","
],
[
" "
],
[
".",
"#",
"!",
",",
"?",
"-",
":",
"'",
"@"
]
]
]
},
{
"level": "opt",
"mode": "locked",
"rows": [
[
[
"1",
"¹",
"½",
"⅓",
"¼",
"⅛"
],
[
"2",
"²",
"⅔"
],
[
"3",
"³",
"¾",
"⅜"
],
[
"4",
"⁴"
],
[
"5",
"⅝"
],
[
"6"
],
[
"7",
"⅞"
],
[
"8"
],
[
"9"
],
[
"0",
"ⁿ",
"∅"
]
],
[
[
"@"
],
[
"#"
],
[
"$",
"¢",
"£",
"€",
"¥",
"₱"
],
[
"%",
"‰"
],
[
"&"
],
[
"-",
"_",
"",
"—",
"·"
],
[
"+",
"±"
],
[
"(",
"<",
"{",
"["
],
[
")",
">",
"}",
"]"
]
],
[
[
"*",
"†",
"‡",
"★"
],
[
"\"",
"“",
"”",
"«",
"»"
],
[
"'",
"",
"",
"",
""
],
[
":"
],
[
";"
],
[
"!",
"¡"
],
[
"?",
"¿"
]
],
[
[
"_"
],
[
"/"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
},
{
"level": "opt+shift",
"mode": "locked",
"rows": [
[
[
"~"
],
[
"`"
],
[
"|"
],
[
"•",
"♪",
"♥",
"♠",
"♦",
"♣"
],
[
"√"
],
[
"Π",
"π"
],
[
"÷"
],
[
"×"
],
[
"¶",
"§"
],
[
"∆"
]
],
[
[
"£"
],
[
"¢"
],
[
"€"
],
[
"¥"
],
[
"^",
"↑",
"↓",
"←",
"→"
],
[
"°",
"",
"″"
],
[
"=",
"≠",
"≈",
"∞"
],
[
"{"
],
[
"}"
]
],
[
[
"\\"
],
[
"©"
],
[
"®"
],
[
"™"
],
[
"℅"
],
[
"["
],
[
"]"
]
],
[
[
"<",
"",
"≤",
"«"
],
[
">",
"",
"≥",
"»"
],
[
" "
],
[
","
],
[
".",
"…"
]
]
]
}
],
"locale": "af",
"name": "Afrikaans"
}

View File

@ -647,7 +647,7 @@ StScrollBar {
border: 1px solid #215d9c; }
.tile-preview-left.on-primary {
border-radius: 6px 6px 0 0; }
border-radius: 6px 0 0 0; }
.tile-preview-right.on-primary {
border-radius: 0 6px 0 0; }
@ -736,7 +736,7 @@ StScrollBar {
#panel.solid .panel-button {
color: #ccc;
text-shadow: none; }
#panel.solid .panel-button:hover {
#panel.solid .panel-button:hover, #panel.solid .panel-button:active, #panel.solid .panel-button:overview, #panel.solid .panel-button:focus, #panel.solid .panel-button:checked {
color: white; }
#panel.solid .system-status-icon,
#panel.solid .app-menu-icon > StIcon,
@ -987,6 +987,14 @@ StScrollBar {
min-width: 21em; }
.aggregate-menu .popup-menu-icon {
padding: 0 4px; }
.aggregate-menu .popup-sub-menu .popup-menu-item :first-child:ltr {
/* 12px spacing + 2*4px padding */
padding-left: 20px;
margin-left: 1.09em; }
.aggregate-menu .popup-sub-menu .popup-menu-item :first-child:rtl {
/* 12px spacing + 2*4px padding */
padding-right: 20px;
margin-right: 1.09em; }
.system-menu-action {
color: #fff;
@ -1339,6 +1347,10 @@ StScrollBar {
border-radius: 9px 0 0 9px; }
.workspace-thumbnails:rtl {
border-radius: 0 9px 9px 0; }
.workspace-thumbnails .placeholder {
background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
background-size: contain;
height: 24px; }
.workspace-thumbnail-indicator {
border: 4px solid #215d9c;
@ -1491,30 +1503,26 @@ StScrollBar {
border-width: 0; }
/* On-screen Keyboard */
.word-suggestions {
font-size: 14pt;
spacing: 12px;
min-height: 20pt; }
#keyboard {
background-color: rgba(46, 52, 54, 0.7); }
.keyboard-layout {
spacing: 10px;
padding: 10px; }
.keyboard-row {
spacing: 15px; }
.key-container {
padding: 4px;
spacing: 4px; }
.keyboard-key {
color: #eeeeec;
background-color: #2e3436;
border-color: rgba(0, 0, 0, 0.7);
box-shadow: inset 0 1px #454f52;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
background-color: #393f3f;
min-height: 2em;
min-width: 2em;
font-size: 14pt;
font-weight: bold;
border-radius: 5px;
border: 1px solid black;
color: white; }
border-radius: 3px;
border: 1px solid #464d4d;
color: #e5e5e5; }
.keyboard-key:focus {
color: #eeeeec;
text-shadow: 0 1px black;
@ -1538,6 +1546,12 @@ StScrollBar {
background-color: #2e3436;
color: #eeeeec;
border-color: rgba(0, 0, 0, 0.7); }
.keyboard-key.default-key {
border-color: #2d3232;
background-color: #1d2020; }
.keyboard-key.enter-key {
border-color: #005684;
background-color: #006098; }
.keyboard-subkeys {
color: white;

View File

@ -647,7 +647,7 @@ StScrollBar {
border: 1px solid #215d9c; }
.tile-preview-left.on-primary {
border-radius: 6px 6px 0 0; }
border-radius: 6px 0 0 0; }
.tile-preview-right.on-primary {
border-radius: 0 6px 0 0; }
@ -736,7 +736,7 @@ StScrollBar {
#panel.solid .panel-button {
color: #ccc;
text-shadow: none; }
#panel.solid .panel-button:hover {
#panel.solid .panel-button:hover, #panel.solid .panel-button:active, #panel.solid .panel-button:overview, #panel.solid .panel-button:focus, #panel.solid .panel-button:checked {
color: white; }
#panel.solid .system-status-icon,
#panel.solid .app-menu-icon > StIcon,
@ -987,6 +987,14 @@ StScrollBar {
min-width: 21em; }
.aggregate-menu .popup-menu-icon {
padding: 0 4px; }
.aggregate-menu .popup-sub-menu .popup-menu-item :first-child:ltr {
/* 12px spacing + 2*4px padding */
padding-left: 20px;
margin-left: 1.09em; }
.aggregate-menu .popup-sub-menu .popup-menu-item :first-child:rtl {
/* 12px spacing + 2*4px padding */
padding-right: 20px;
margin-right: 1.09em; }
.system-menu-action {
color: #eeeeec;
@ -1339,6 +1347,10 @@ StScrollBar {
border-radius: 9px 0 0 9px; }
.workspace-thumbnails:rtl {
border-radius: 0 9px 9px 0; }
.workspace-thumbnails .placeholder {
background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
background-size: contain;
height: 24px; }
.workspace-thumbnail-indicator {
border: 4px solid #215d9c;
@ -1491,30 +1503,26 @@ StScrollBar {
border-width: 0; }
/* On-screen Keyboard */
.word-suggestions {
font-size: 14pt;
spacing: 12px;
min-height: 20pt; }
#keyboard {
background-color: rgba(46, 52, 54, 0.7); }
.keyboard-layout {
spacing: 10px;
padding: 10px; }
.keyboard-row {
spacing: 15px; }
.key-container {
padding: 4px;
spacing: 4px; }
.keyboard-key {
color: #eeeeec;
background-color: #2e3436;
border-color: rgba(0, 0, 0, 0.7);
box-shadow: inset 0 1px #454f52;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
background-color: #393f3f;
min-height: 2em;
min-width: 2em;
font-size: 14pt;
font-weight: bold;
border-radius: 5px;
border: 1px solid #1c1f1f;
color: white; }
border-radius: 3px;
border: 1px solid #464d4d;
color: #e5e5e5; }
.keyboard-key:focus {
color: #eeeeec;
text-shadow: 0 1px black;
@ -1538,6 +1546,12 @@ StScrollBar {
background-color: #2e3436;
color: #eeeeec;
border-color: rgba(0, 0, 0, 0.7); }
.keyboard-key.default-key {
border-color: #2d3232;
background-color: #1d2020; }
.keyboard-key.enter-key {
border-color: #005684;
background-color: #006098; }
.keyboard-subkeys {
color: white;

48
data/update-osk-layouts.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/env bash
CLDR_LAYOUTS_TARBALL="http://www.unicode.org/Public/cldr/latest/keyboards.zip"
CLDR2JSON_GIT="git://repo.or.cz/cldr2json.git"
WORKDIR=".osk-layout-workbench"
CLDR2JSON="$WORKDIR/cldr2json/cldr2json.py"
SRCDIR="$WORKDIR/keyboards/android"
DESTDIR="osk-layouts"
GRESOURCE_FILE="gnome-shell-osk-layouts.gresource.xml"
TMP_GRESOURCE_FILE=".$GRESOURCE_FILE.tmp"
cd `dirname $0`
# Ensure work/dest dirs
rm -rf $WORKDIR
mkdir -p $WORKDIR
mkdir -p "osk-layouts"
# Download stuff on the work dir
pushd $WORKDIR
gio copy $CLDR_LAYOUTS_TARBALL .
git clone $CLDR2JSON_GIT
unzip keyboards.zip
popd
# Transform to JSON files
$CLDR2JSON $SRCDIR $DESTDIR
# Generate new gresources xml file
cat >$TMP_GRESOURCE_FILE <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/shell/osk-layouts">
EOF
for f in $DESTDIR/*.json
do
echo " <file>$(basename $f)</file>" >>$TMP_GRESOURCE_FILE
done
cat >>$TMP_GRESOURCE_FILE <<EOF
</gresource>
</gresources>
EOF
# Rewrite old gresources xml
mv $TMP_GRESOURCE_FILE $GRESOURCE_FILE

View File

@ -17,6 +17,7 @@
<file>misc/gnomeSession.js</file>
<file>misc/history.js</file>
<file>misc/ibusManager.js</file>
<file>misc/inputMethod.js</file>
<file>misc/jsParse.js</file>
<file>misc/keyboardManager.js</file>
<file>misc/loginManager.js</file>
@ -61,6 +62,7 @@
<file>ui/ibusCandidatePopup.js</file>
<file>ui/iconGrid.js</file>
<file>ui/inhibitShortcutsDialog.js</file>
<file>ui/kbdA11yDialog.js</file>
<file>ui/keyboard.js</file>
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
@ -130,5 +132,6 @@
<file>ui/status/bluetooth.js</file>
<file>ui/status/screencast.js</file>
<file>ui/status/system.js</file>
<file>ui/status/thunderbolt.js</file>
</gresource>
</gresources>

View File

@ -14,6 +14,6 @@ var GETTEXT_PACKAGE = '@GETTEXT_PACKAGE@';
var LOCALEDIR = '@datadir@/locale';
/* other standard directories */
var LIBEXECDIR = '@libexecdir@';
var SYSCONFDIR = '@sysconfdir@';
var VPNDIR = '@vpndir@';
/* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

@ -6,15 +6,11 @@ const Lang = imports.lang;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
let IBusCandidatePopup;
try {
var IBus = imports.gi.IBus;
_checkIBusVersion(1, 5, 2);
IBusCandidatePopup = imports.ui.ibusCandidatePopup;
} catch (e) {
var IBus = null;
log(e);
}
const IBus = imports.gi.IBus;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
// Ensure runtime version matches
_checkIBusVersion(1, 5, 2);
let _ibusManager = null;
@ -45,9 +41,6 @@ var IBusManager = new Lang.Class({
_PRELOAD_ENGINES_DELAY_TIME: 30, // sec
_init: function() {
if (!IBus)
return;
IBus.init();
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
@ -190,7 +183,7 @@ var IBusManager = new Lang.Class({
},
getEngineDesc: function(id) {
if (!IBus || !this._ready || !this._engines.hasOwnProperty(id))
if (!this._ready || !this._engines.hasOwnProperty(id))
return null;
return this._engines[id];
@ -200,7 +193,7 @@ var IBusManager = new Lang.Class({
// Send id even if id == this._currentEngineName
// because 'properties-registered' signal can be emitted
// while this._ibusSources == null on a lock screen.
if (!IBus || !this._ready) {
if (!this._ready) {
if (callback)
callback();
return;
@ -211,7 +204,7 @@ var IBusManager = new Lang.Class({
},
preloadEngines: function(ids) {
if (!IBus || !this._ibus || ids.length == 0)
if (!this._ibus || ids.length == 0)
return;
if (this._preloadEnginesId != 0) {

214
js/misc/inputMethod.js Normal file
View File

@ -0,0 +1,214 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Clutter = imports.gi.Clutter;
const IBus = imports.gi.IBus;
const Keyboard = imports.ui.status.keyboard;
const Lang = imports.lang;
const Signals = imports.signals;
var InputMethod = new Lang.Class({
Name: 'InputMethod',
Extends: Clutter.InputMethod,
_init: function() {
this.parent();
this._hints = 0;
this._purpose = 0;
this._enabled = true;
this._currentFocus = null;
this._ibus = IBus.Bus.new_async();
this._ibus.connect('connected', Lang.bind(this, this._onConnected));
this._ibus.connect('disconnected', Lang.bind(this, this._clear));
this.connect('notify::can-show-preedit', Lang.bind(this, this._updateCapabilities));
this._inputSourceManager = Keyboard.getInputSourceManager();
this._sourceChangedId = this._inputSourceManager.connect('current-source-changed',
Lang.bind(this, this._onSourceChanged));
this._currentSource = this._inputSourceManager.currentSource;
if (this._ibus.is_connected())
this._onConnected();
},
get currentFocus() {
return this._currentFocus;
},
_updateCapabilities: function() {
let caps = 0;
if (this.can_show_preedit)
caps |= IBus.Capabilite.PREEDIT_TEXT;
if (this._currentFocus)
caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
else
caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT | IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY;
if (this._context)
this._context.set_capabilities(caps);
},
_onSourceChanged: function() {
this._currentSource = this._inputSourceManager.currentSource;
},
_onConnected: function() {
this._ibus.create_input_context_async ('gnome-shell', -1, null,
Lang.bind(this, this._setContext));
},
_setContext: function(bus, res) {
this._context = this._ibus.create_input_context_async_finish(res);
this._context.connect('enabled', Lang.bind(this, function () { this._enabled = true }));
this._context.connect('disabled', Lang.bind(this, function () { this._enabled = false }));
this._context.connect('commit-text', Lang.bind(this, this._onCommitText));
this._context.connect('delete-surrounding-text', Lang.bind(this, this._onDeleteSurroundingText));
this._context.connect('update-preedit-text', Lang.bind(this, this._onUpdatePreeditText));
this._updateCapabilities();
},
_clear: function() {
this._context = null;
this._hints = 0;
this._purpose = 0;
this._enabled = false;
},
_emitRequestSurrounding: function() {
if (this._context.needs_surrounding_text())
this.emit('request-surrounding');
},
_onCommitText: function(context, text) {
this.commit(text.get_text());
},
_onDeleteSurroundingText: function (context) {
this.delete_surrounding();
},
_onUpdatePreeditText: function (context, text, pos, visible) {
let str = null;
if (visible && text != null)
str = text.get_text();
this.set_preedit_text(str, pos);
},
vfunc_focus_in: function(focus) {
this._currentFocus = focus;
if (this._context) {
this._context.focus_in();
this._updateCapabilities();
this._emitRequestSurrounding();
}
},
vfunc_focus_out: function() {
this._currentFocus = null;
if (this._context) {
this._context.focus_out();
this._updateCapabilities();
}
// Unset any preedit text
this.set_preedit_text(null, 0);
},
vfunc_reset: function() {
if (this._context) {
this._context.reset();
this._emitRequestSurrounding();
}
// Unset any preedit text
this.set_preedit_text(null, 0);
},
vfunc_set_cursor_location: function(rect) {
if (this._context) {
this._context.set_cursor_location(rect.get_x(), rect.get_y(),
rect.get_width(), rect.get_height());
this._emitRequestSurrounding();
}
},
vfunc_set_surrounding: function(text, cursor, anchor) {
if (this._context)
this._context.set_surrounding_text(text, cursor, anchor);
},
vfunc_update_content_hints: function(hints) {
let ibusHints = 0;
if (hints & Clutter.InputContentHintFlags.COMPLETION)
ibusHints |= IBus.InputHints.WORD_COMPLETION;
if (hints & Clutter.InputContentHintFlags.SPELLCHECK)
ibusHints |= IBus.InputHints.SPELLCHECK;
if (hints & Clutter.InputContentHintFlags.AUTO_CAPITALIZATION)
ibusHints |= IBus.InputHints.UPPERCASE_SENTENCES;
if (hints & Clutter.InputContentHintFlags.LOWERCASE)
ibusHints |= IBus.InputHints.LOWERCASE;
if (hints & Clutter.InputContentHintFlags.UPPERCASE)
ibusHints |= IBus.InputHints.UPPERCASE_CHARS;
if (hints & Clutter.InputContentHintFlags.TITLECASE)
ibusHints |= IBus.InputHints.UPPERCASE_WORDS;
this._hints = ibusHints;
if (this._context)
this._context.set_content_type(this._purpose, this._hints);
},
vfunc_update_content_purpose: function(purpose) {
let ibusPurpose = 0;
if (purpose == Clutter.InputContentPurpose.NORMAL)
ibusPurpose = IBus.InputPurpose.FREE_FORM;
else if (purpose == Clutter.InputContentPurpose.ALPHA)
ibusPurpose = IBus.InputPurpose.ALPHA;
else if (purpose == Clutter.InputContentPurpose.DIGITS)
ibusPurpose = IBus.InputPurpose.DIGITS;
else if (purpose == Clutter.InputContentPurpose.NUMBER)
ibusPurpose = IBus.InputPurpose.NUMBER;
else if (purpose == Clutter.InputContentPurpose.PHONE)
ibusPurpose = IBus.InputPurpose.PHONE;
else if (purpose == Clutter.InputContentPurpose.URL)
ibusPurpose = IBus.InputPurpose.URL;
else if (purpose == Clutter.InputContentPurpose.EMAIL)
ibusPurpose = IBus.InputPurpose.EMAIL;
else if (purpose == Clutter.InputContentPurpose.NAME)
ibusPurpose = IBus.InputPurpose.NAME;
else if (purpose == Clutter.InputContentPurpose.PASSWORD)
ibusPurpose = IBus.InputPurpose.PASSWORD;
this._purpose = ibusPurpose;
if (this._context)
this._context.set_content_type(this._purpose, this._hints);
},
vfunc_filter_key_event: function(event) {
if (!this._context || !this._enabled)
return false;
if (!this._currentSource ||
this._currentSource.type == Keyboard.INPUT_SOURCE_TYPE_XKB)
return false;
let state = event.get_state();
if (state & IBus.ModifierType.IGNORED_MASK)
return false;
if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK;
this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, null,
Lang.bind(this, (context, res) => {
try {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);
} catch (e) {
log('Error processing key on IM: ' + e.message);
}
}));
return true;
},
});

View File

@ -7,7 +7,7 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir)
jsconf.set('sysconfdir', sysconfdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file(
input: 'config.js.in',

View File

@ -2,7 +2,7 @@
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const NMGtk = imports.gi.NMGtk;
const NMA = imports.gi.NMA;
const Signals = imports.signals;
// _getMobileProvidersDatabase:
@ -14,7 +14,7 @@ let _mpd;
function _getMobileProvidersDatabase() {
if (_mpd == null) {
try {
_mpd = new NMGtk.MobileProvidersDatabase();
_mpd = new NMA.MobileProvidersDatabase();
_mpd.init(null);
} catch (e) {
log(e.message);

View File

@ -96,21 +96,21 @@ const SystemActions = new Lang.Class({
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID,
{ // Translators: The name of the power-off action in search
name: C_("search-result", "Power off"),
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown").split(';'),
keywords: _("power off;shutdown;reboot;restart").split(';'),
available: false });
this._actions.set(LOCK_SCREEN_ACTION_ID,
{ // Translators: The name of the lock screen action in search
name: C_("search-result", "Lock screen"),
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(';'),
available: false });
this._actions.set(LOGOUT_ACTION_ID,
{ // Translators: The name of the logout action in search
name: C_("search-result", "Log out"),
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;sign off").split(';'),
@ -124,17 +124,17 @@ const SystemActions = new Lang.Class({
available: false });
this._actions.set(SWITCH_USER_ACTION_ID,
{ // Translators: The name of the switch user action in search
name: C_("search-result", "Switch user"),
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(';'),
available: false });
this._actions.set(LOCK_ORIENTATION_ACTION_ID,
{ // Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock orientation"),
name: C_("search-result", "Lock Orientation"),
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation").split(';'),
keywords: _("lock orientation;screen;rotation").split(';'),
available: false });
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });

View File

@ -156,6 +156,26 @@ var AppSwitcherPopup = new Lang.Class({
this._items[this._selectedIndex].cachedWindows.length);
},
_closeAppWindow: function(appIndex, windowIndex) {
let appIcon = this._items[appIndex];
if (!appIcon)
return;
let window = appIcon.cachedWindows[windowIndex];
if (!window)
return;
window.delete(global.get_current_time());
},
_quitApplication: function(appIndex) {
let appIcon = this._items[appIndex];
if (!appIcon)
return;
appIcon.app.request_quit();
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_GROUP) {
if (!this._thumbnailsFocused)
@ -168,6 +188,8 @@ var AppSwitcherPopup = new Lang.Class({
this._select(this._next());
} else if (action == Meta.KeyBindingAction.SWITCH_APPLICATIONS_BACKWARD) {
this._select(this._previous());
} else if (keysym == Clutter.q) {
this._quitApplication(this._selectedIndex);
} else if (this._thumbnailsFocused) {
if (keysym == Clutter.Left)
this._select(this._selectedIndex, this._previousWindow());
@ -175,6 +197,8 @@ var AppSwitcherPopup = new Lang.Class({
this._select(this._selectedIndex, this._nextWindow());
else if (keysym == Clutter.Up)
this._select(this._selectedIndex, null, true);
else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeAppWindow(this._selectedIndex, this._currentWindow);
else
return Clutter.EVENT_PROPAGATE;
} else {
@ -248,11 +272,22 @@ var AppSwitcherPopup = new Lang.Class({
this._select(this._selectedIndex, n);
},
_windowRemoved : function(thumbnailList, n) {
let appIcon = this._items[this._selectedIndex];
if (!appIcon)
return;
if (appIcon.cachedWindows.length > 0) {
let newIndex = Math.min(n, appIcon.cachedWindows.length - 1);
this._select(this._selectedIndex, newIndex);
}
},
_finish : function(timestamp) {
let appIcon = this._items[this._selectedIndex];
if (this._currentWindow < 0)
appIcon.app.activate_window(appIcon.cachedWindows[0], timestamp);
else
else if (appIcon.cachedWindows[this._currentWindow])
Main.activateWindow(appIcon.cachedWindows[this._currentWindow], timestamp);
this.parent();
@ -343,13 +378,19 @@ var AppSwitcherPopup = new Lang.Class({
})
});
this._thumbnails = null;
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
if (this._switcherList._items[this._selectedIndex])
this._switcherList._items[this._selectedIndex].remove_accessible_state (Atk.StateType.EXPANDED);
},
_createThumbnails : function() {
this._thumbnails = new ThumbnailList (this._items[this._selectedIndex].cachedWindows);
this._thumbnails.connect('item-activated', Lang.bind(this, this._windowActivated));
this._thumbnails.connect('item-entered', Lang.bind(this, this._windowEntered));
this._thumbnails.connect('item-removed', Lang.bind(this, this._windowRemoved));
this._thumbnails.actor.connect('destroy', () => {
this._thumbnails = null;
this._thumbnailsFocused = false;
});
this.actor.add_actor(this._thumbnails.actor);
@ -535,6 +576,14 @@ var WindowSwitcherPopup = new Lang.Class({
return getWindows(workspace);
},
_closeWindow: function(windowIndex) {
let windowIcon = this._items[windowIndex];
if (!windowIcon)
return;
windowIcon.window.delete(global.get_current_time());
},
_keyPressHandler: function(keysym, action) {
if (action == Meta.KeyBindingAction.SWITCH_WINDOWS) {
this._select(this._next());
@ -545,6 +594,8 @@ var WindowSwitcherPopup = new Lang.Class({
this._select(this._previous());
else if (keysym == Clutter.Right)
this._select(this._next());
else if (keysym == Clutter.w || keysym == Clutter.F4)
this._closeWindow(this._selectedIndex);
else
return Clutter.EVENT_PROPAGATE;
}
@ -645,6 +696,10 @@ var AppSwitcher = new Lang.Class({
_onDestroy: function() {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId);
});
},
_setIconSize: function() {
@ -745,7 +800,7 @@ var AppSwitcher = new Lang.Class({
// show a dim arrow, but show a bright arrow when they are
// highlighted.
highlight : function(n, justOutline) {
if (this._curApp != -1) {
if (this.icons[this._curApp]) {
if (this.icons[this._curApp].cachedWindows.length == 1)
this._arrows[this._curApp].hide();
else
@ -767,6 +822,11 @@ var AppSwitcher = new Lang.Class({
this.icons.push(appIcon);
let item = this.addItem(appIcon.actor, appIcon.label);
appIcon._stateChangedId = appIcon.app.connect('notify::state', app => {
if (app.state != Shell.AppState.RUNNING)
this._removeIcon(app);
});
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', function() { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
@ -777,7 +837,18 @@ var AppSwitcher = new Lang.Class({
arrow.hide();
else
item.add_accessible_state (Atk.StateType.EXPANDABLE);
}
},
_removeIcon: function(app) {
let index = this.icons.findIndex(icon => {
return icon.app == app;
});
if (index === -1)
return;
this.icons.splice(index, 1);
this.removeItem(index);
},
});
var ThumbnailList = new Lang.Class({
@ -816,6 +887,8 @@ var ThumbnailList = new Lang.Class({
}
}
this.actor.connect('destroy', this._onDestroy.bind(this));
},
addClones : function (availHeight) {
@ -840,12 +913,38 @@ var ThumbnailList = new Lang.Class({
let clone = _createWindowClone(mutterWindow, thumbnailSize);
this._thumbnailBins[i].set_height(binHeight);
this._thumbnailBins[i].add_actor(clone);
clone._destroyId = mutterWindow.connect('destroy', Lang.bind(this, this._removeThumbnail, clone));
this._clones.push(clone);
}
// Make sure we only do this once
this._thumbnailBins = new Array();
}
},
_removeThumbnail: function(source, clone) {
let index = this._clones.indexOf(clone);
if (index === -1)
return;
this._clones.splice(index, 1);
this._windows.splice(index, 1);
this._labels.splice(index, 1);
this.removeItem(index);
if (this._clones.length > 0)
this.highlight(SwitcherPopup.mod(index, this._clones.length));
else
this.actor.destroy();
},
_onDestroy: function() {
this._clones.forEach(clone => {
if (clone.source)
clone.source.disconnect(clone._destroyId);
});
},
});
var WindowIcon = new Lang.Class({
@ -925,7 +1024,19 @@ var WindowList = new Lang.Class({
this.addItem(icon.actor, icon.label);
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
this._removeWindow(window)
});
}
this.actor.connect('destroy', () => { this._onDestroy(); });
},
_onDestroy: function() {
this.icons.forEach(icon => {
icon.window.disconnect(icon._unmanagedSignalId);
});
},
_getPreferredHeight: function(actor, forWidth, alloc) {
@ -954,5 +1065,16 @@ var WindowList = new Lang.Class({
this.parent(index, justOutline);
this._label.set_text(index == -1 ? '' : this.icons[index].label.text);
},
_removeWindow: function(window) {
let index = this.icons.findIndex(icon => {
return icon.window == window;
});
if (index === -1)
return;
this.icons.splice(index, 1);
this.removeItem(index);
}
});

View File

@ -1872,11 +1872,14 @@ var AppIconMenu = new Lang.Class({
this.actor.add_style_class_name('app-well-menu');
// Chain our visibility and lifecycle to that of the source
source.actor.connect('notify::mapped', Lang.bind(this, function () {
this._sourceMappedId = source.actor.connect('notify::mapped', () => {
if (!source.actor.mapped)
this.close();
}));
source.actor.connect('destroy', Lang.bind(this, this.destroy));
});
source.actor.connect('destroy', () => {
source.actor.disconnect(this._sourceMappedId);
this.destroy();
});
Main.uiGroup.add_actor(this.actor);
},

View File

@ -289,6 +289,8 @@ var Background = new Lang.Class({
this._clock.disconnect(this._timezoneChangedId);
this._timezoneChangedId = 0;
this._clock = null;
if (this._prepareForSleepId != 0)
LoginManager.getLoginManager().disconnect(this._prepareForSleepId);
this._prepareForSleepId = 0;

View File

@ -7,7 +7,6 @@ const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const St = imports.gi.St;
const Signals = imports.signals;
const Gettext_gtk30 = imports.gettext.domain('gtk30');
const Shell = imports.gi.Shell;
const Main = imports.ui.main;
@ -22,8 +21,6 @@ var ELLIPSIS_CHAR = '\u2026';
var MESSAGE_ICON_SIZE = -1; // pick up from CSS
// alias to prevent xgettext from picking up strings translated in GTK+
const gtk30_ = Gettext_gtk30.gettext;
var NC_ = function(context, str) { return context + '\u0004' + str; };
function sameYear(dateA, dateB) {
@ -376,20 +373,23 @@ var Calendar = new Lang.Class({
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, Lang.bind(this, this._onSettingsChange));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
// Find the ordering for month/year in the calendar heading
this._headerFormatWithoutYear = '%B';
switch (gtk30_('calendar:MY')) {
case 'calendar:MY':
this._headerFormat = '%B %Y';
break;
case 'calendar:YM':
this._headerFormat = '%Y %B';
break;
default:
log('Translation of "calendar:MY" in GTK+ is not correct');
this._headerFormat = '%B %Y';
break;
}
/**
* Translators: The header displaying just the month name
* standalone, when this is a month of the current year.
* "%OB" is the new format specifier introduced in glibc 2.27,
* in most cases you should not change it.
*/
this._headerFormatWithoutYear = _('%OB');
/**
* Translators: The header displaying the month name and the year
* number, when this is a month of a different year. You can
* reorder the format specifiers or add other modifications
* according to the requirements of your language.
* "%OB" is the new format specifier introduced in glibc 2.27,
* in most cases you should not use the old "%B" here unless you
* absolutely know what you are doing.
*/
this._headerFormat = _('%OB %Y');
// Start off with the current date
this._selectedDate = new Date();

View File

@ -5,10 +5,10 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const NetworkManager = imports.gi.NetworkManager;
const NMClient = imports.gi.NMClient;
const NM = imports.gi.NM;
const Pango = imports.gi.Pango;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const St = imports.gi.St;
const Config = imports.misc.config;
@ -173,7 +173,7 @@ var NetworkSecretDialog = new Lang.Class({
_validateStaticWep: function(secret) {
let value = secret.value;
if (secret.wep_key_type == NetworkManager.WepKeyType.KEY) {
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
@ -189,7 +189,7 @@ var NetworkSecretDialog = new Lang.Class({
}
} else
return false;
} else if (secret.wep_key_type == NetworkManager.WepKeyType.PASSPHRASE) {
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64)
return false;
}
@ -288,7 +288,7 @@ var NetworkSecretDialog = new Lang.Class({
switch (connectionType) {
case '802-11-wireless':
wirelessSetting = this._connection.get_setting_wireless();
ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
content.title = _("Authentication required by wireless network");
content.message = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
this._getWirelessSecrets(content.secrets, wirelessSetting);
@ -351,9 +351,9 @@ var VPNRequestHandler = new Lang.Class({
];
if (authHelper.externalUIMode)
argv.push('--external-ui-mode');
if (flags & NMClient.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
argv.push('-i');
if (flags & NMClient.SecretAgentGetSecretsFlags.REQUEST_NEW)
if (flags & NM.SecretAgentGetSecretsFlags.REQUEST_NEW)
argv.push('-r');
if (authHelper.supportsHints) {
for (let i = 0; i < hints.length; i++) {
@ -414,7 +414,9 @@ var VPNRequestHandler = new Lang.Class({
if (this._destroyed)
return;
GLib.source_remove(this._childWatch);
this.emit('destroy');
if (this._childWatch)
GLib.source_remove(this._childWatch);
this._stdin.close(null);
// Stdout is closed when we finish reading from it
@ -541,6 +543,7 @@ var VPNRequestHandler = new Lang.Class({
logError(e, 'error while reading VPN plugin output keyfile');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
this.destroy();
return;
}
}
@ -551,6 +554,7 @@ var VPNRequestHandler = new Lang.Class({
this._shellDialog.open(global.get_current_time());
} else {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
this.destroy();
}
},
@ -571,23 +575,26 @@ var VPNRequestHandler = new Lang.Class({
logError(e, 'internal error while writing connection to helper');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
this.destroy();
}
},
});
Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = new Lang.Class({
Name: 'NetworkAgent',
_init: function() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NMClient.SecretAgentCapabilities.VPN_HINTS
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false
});
this._dialogs = { };
this._vpnRequests = { };
this._notifications = { };
this._pluginDir = Gio.file_new_for_path(GLib.build_filenamev([Config.SYSCONFDIR, 'NetworkManager/VPN']));
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => { this._vpnCacheBuilt = false; });
@ -597,12 +604,21 @@ var NetworkAgent = new Lang.Class({
this._native.connect('new-request', Lang.bind(this, this._newRequest));
this._native.connect('cancel-request', Lang.bind(this, this._cancelRequest));
this._enabled = false;
try {
this._native.init(null);
} catch(e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
},
enable: function() {
this._enabled = true;
if (!this._native)
return;
this._native.auto_register = true;
if (!this._native.registered)
this._native.register_async(null, null);
},
disable: function() {
@ -620,7 +636,12 @@ var NetworkAgent = new Lang.Class({
this._notifications[requestId].destroy();
this._notifications = { };
this._enabled = false;
if (!this._native)
return;
this._native.auto_register = false;
if (this._native.registered)
this._native.unregister_async(null, null);
},
_showNotification: function(requestId, connection, settingName, hints, flags) {
@ -634,7 +655,7 @@ var NetworkAgent = new Lang.Class({
switch (connectionType) {
case '802-11-wireless':
let wirelessSetting = connection.get_setting_wireless();
let ssid = NetworkManager.utils_ssid_to_utf8(wirelessSetting.get_ssid());
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid());
title = _("Authentication required by wireless network");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break;
@ -684,12 +705,7 @@ var NetworkAgent = new Lang.Class({
},
_newRequest: function(agent, requestId, connection, settingName, hints, flags) {
if (!this._enabled) {
agent.respond(requestId, Shell.NetworkAgentResponse.USER_CANCELED);
return;
}
if (!(flags & NMClient.SecretAgentGetSecretsFlags.USER_REQUESTED))
if (!(flags & NM.SecretAgentGetSecretsFlags.USER_REQUESTED))
this._showNotification(requestId, connection, settingName, hints, flags);
else
this._handleRequest(requestId, connection, settingName, hints, flags);
@ -735,7 +751,11 @@ var NetworkAgent = new Lang.Class({
return;
}
this._vpnRequests[requestId] = new VPNRequestHandler(this._native, requestId, binary, serviceType, connection, hints, flags);
let vpnRequest = new VPNRequestHandler(this._native, requestId, binary, serviceType, connection, hints, flags);
vpnRequest.connect('destroy', Lang.bind(this, function() {
delete this._vpnRequests[requestId];
}));
this._vpnRequests[requestId] = vpnRequest;
},
_buildVPNServiceCache: function() {

View File

@ -50,6 +50,10 @@ var DashItemContainer = new Lang.Class({
this._childScale = 0;
this._childOpacity = 0;
this.animatingOut = false;
this.connect('destroy', () => {
this.label.destroy();
});
},
vfunc_allocate: function(box, flags) {
@ -177,16 +181,8 @@ var DashItemContainer = new Lang.Class({
});
},
destroy: function() {
if (this.label)
this.label.destroy();
this.parent();
},
animateOutAndDestroy: function() {
if (this.label)
this.label.destroy();
this.label.hide();
if (this.child == null) {
this.destroy();

View File

@ -132,8 +132,11 @@ var WorldClocksSection = new Lang.Class({
let world = GWeather.Location.get_world();
let clocks = settings.get_value('world-clocks').deep_unpack();
for (let i = 0; i < clocks.length; i++) {
if (!clocks[i].location)
continue;
let l = world.deserialize(clocks[i].location);
this._locations.push({ location: l });
if (l)
this._locations.push({ location: l });
}
this._locations.sort(function(a, b) {

View File

@ -16,6 +16,7 @@ var Dialog = new Lang.Class({
this.connect('destroy', Lang.bind(this, this._onDestroy));
this._initialKeyFocus = null;
this._initialKeyFocusDestroyId = 0;
this._pressedKey = null;
this._buttonKeys = {};
this._createDialog();
@ -87,6 +88,18 @@ var Dialog = new Lang.Class({
return Clutter.EVENT_PROPAGATE;
},
_setInitialKeyFocus: function(actor) {
if (this._initialKeyFocus)
this._initialKeyFocus.disconnect(this._initialKeyFocusDestroyId);
this._initialKeyFocus = actor;
this._initialKeyFocusDestroyId = actor.connect('destroy', () => {
this._initialKeyFocus = null;
this._initialKeyFocusDestroyId = 0;
});
},
get initialKeyFocus() {
return this._initialKeyFocus || this;
},
@ -122,7 +135,7 @@ var Dialog = new Lang.Class({
button.add_style_pseudo_class('default');
if (this._initialKeyFocus == null || isDefault)
this._initialKeyFocus = button;
this._setInitialKeyFocus(button);
for (let i in keys)
this._buttonKeys[keys[i]] = buttonInfo;

View File

@ -583,7 +583,7 @@ var _Draggable = new Lang.Class({
_restoreDragActor: function(eventTime) {
this._dragInProgress = false;
[restoreX, restoreY, restoreScale] = this._getRestoreLocation();
let [restoreX, restoreY, restoreScale] = this._getRestoreLocation();
// fade the actor back in at its original location
this._dragActor.set_position(restoreX, restoreY);

View File

@ -233,7 +233,9 @@ var InstallExtensionDialog = new Lang.Class({
let dir = Gio.File.new_for_path(GLib.build_filenamev([global.userdatadir, 'extensions', uuid]));
let invocation = this._invocation;
function errback(code, message) {
invocation.return_dbus_error('org.gnome.Shell.' + code, message ? message.toString() : '');
let msg = message ? message.toString() : '';
log('Error while installing %s: %s (%s)'.format(uuid, code, msg));
invocation.return_dbus_error('org.gnome.Shell.' + code, msg);
}
function callback() {

View File

@ -253,10 +253,18 @@ var CandidatePopup = new Lang.Class({
for (let i = 0; indexLabel = lookupTable.get_label(i); ++i)
indexes.push(indexLabel.get_text());
Main.keyboard.resetSuggestions();
let candidates = [];
for (let i = startIndex; i < endIndex; ++i)
for (let i = startIndex; i < endIndex; ++i) {
candidates.push(lookupTable.get_candidate(i).get_text());
Main.keyboard.addSuggestion(lookupTable.get_candidate(i).get_text(), Lang.bind(this, function() {
let index = i;
this._panelService.candidate_clicked(index, 1, 0);
}));
}
this._candidateArea.setCandidates(indexes,
candidates,
cursorPos % pageSize,
@ -277,6 +285,7 @@ var CandidatePopup = new Lang.Class({
panelService.connect('focus-out',
Lang.bind(this, function(ps) {
this._boxPointer.hide(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
}));
},
@ -287,9 +296,10 @@ var CandidatePopup = new Lang.Class({
},
_updateVisibility: function() {
let isVisible = (this._preeditText.visible ||
this._auxText.visible ||
this._candidateArea.actor.visible);
let isVisible = (!Main.keyboard.visible &&
(this._preeditText.visible ||
this._auxText.visible ||
this._candidateArea.actor.visible));
if (isVisible) {
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);

77
js/ui/kbdA11yDialog.js Normal file
View File

@ -0,0 +1,77 @@
const Clutter = imports.gi.Clutter;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Lang = imports.lang;
const Dialog = imports.ui.dialog;
const ModalDialog = imports.ui.modalDialog;
const KEYBOARD_A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const KEY_STICKY_KEYS_ENABLED = 'stickykeys-enable';
const KEY_SLOW_KEYS_ENABLED = 'slowkeys-enable';
var KbdA11yDialog = new Lang.Class({
Name: 'KbdA11yDialog',
Extends: GObject.Object,
_init: function() {
this._a11ySettings = new Gio.Settings({ schema_id: KEYBOARD_A11Y_SCHEMA });
let deviceManager = Clutter.DeviceManager.get_default();
deviceManager.connect('kbd-a11y-flags-changed',
Lang.bind(this, this._showKbdA11yDialog));
},
_showKbdA11yDialog: function(deviceManager, newFlags, whatChanged) {
let dialog = new ModalDialog.ModalDialog();
let title, body;
let key, enabled;
if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) ? true : false;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
body = _("You just held down the Shift key for 8 seconds. This is the shortcut " +
"for the Slow Keys feature, which affects the way your keyboard works.");
} else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) ? true : false;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");
body = enabled ?
_("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.") :
_("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
} else {
return;
}
let icon = new Gio.ThemedIcon({ name: 'preferences-desktop-accessibility-symbolic' });
let contentParams = { icon, title, body, styleClass: 'access-dialog' };
let content = new Dialog.MessageDialogContent(contentParams);
dialog.contentLayout.add_actor(content);
dialog.addButton({ label: enabled ? _("Leave On") : _("Turn On"),
action: () => {
this._a11ySettings.set_boolean(key, true);
dialog.close();
},
default: enabled,
key: !enabled ? Clutter.Escape : null });
dialog.addButton({ label: enabled ? _("Turn Off") : _("Leave Off"),
action: () => {
this._a11ySettings.set_boolean(key, false);
dialog.close();
},
default: !enabled,
key: enabled ? Clutter.Escape : null });
dialog.open();
}
});

File diff suppressed because it is too large Load Diff

View File

@ -351,6 +351,9 @@ var LayoutManager = new Lang.Class({
this._loadBackground();
this._pendingLoadBackground = false;
}
} else {
this.primaryMonitor = null;
this.bottomMonitor = null;
}
},

View File

@ -19,6 +19,7 @@ const EndSessionDialog = imports.ui.endSessionDialog;
const Environment = imports.ui.environment;
const ExtensionSystem = imports.ui.extensionSystem;
const ExtensionDownloader = imports.ui.extensionDownloader;
const InputMethod = imports.misc.inputMethod;
const Keyboard = imports.ui.keyboard;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
@ -44,6 +45,7 @@ const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler;
const Util = imports.misc.util;
const KbdA11yDialog = imports.ui.kbdA11yDialog;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
@ -78,11 +80,14 @@ var magnifier = null;
var xdndHandler = null;
var keyboard = null;
var layoutManager = null;
var kbdA11yDialog = null;
var inputMethod = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
let _a11ySettings = null;
let _themeResource = null;
let _oskResource = null;
function _sessionUpdated() {
if (sessionMode.isPrimary)
@ -146,6 +151,7 @@ function _initializeUI() {
Shell.AppUsage.get_default();
reloadThemeResource();
_loadOskLayouts();
_loadDefaultStylesheet();
// Setup the stage hierarchy early
@ -163,11 +169,15 @@ function _initializeUI() {
osdWindowManager = new OsdWindow.OsdWindowManager();
osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
overview = new Overview.Overview();
kbdA11yDialog = new KbdA11yDialog.KbdA11yDialog();
wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier();
if (LoginManager.canLock())
screenShield = new ScreenShield.ScreenShield();
inputMethod = new InputMethod.InputMethod();
Clutter.get_default_backend().set_input_method(inputMethod);
messageTray = new MessageTray.MessageTray();
panel = new Panel.Panel();
keyboard = new Keyboard.Keyboard();
@ -306,6 +316,11 @@ function reloadThemeResource() {
_themeResource._register();
}
function _loadOskLayouts() {
_oskResource = Gio.Resource.load(global.datadir + '/gnome-shell-osk-layouts.gresource');
_oskResource._register();
}
/**
* loadTheme:
*

View File

@ -215,7 +215,7 @@ var ModalDialog = new Lang.Class({
else
this._savedKeyFocus = null;
Main.popModal(this._group, timestamp);
global.gdk_screen.get_display().sync();
Gdk.Display.get_default().sync();
this._hasModal = false;
if (!this._shellReactive)

View File

@ -417,7 +417,7 @@ var Overview = new Lang.Class({
beginItemDrag: function(source) {
this.emit('item-drag-begin');
this._inDrag = true;
this._inItemDrag = true;
},
cancelledItemDrag: function(source) {
@ -425,13 +425,15 @@ var Overview = new Lang.Class({
},
endItemDrag: function(source) {
if (!this._inItemDrag)
return;
this.emit('item-drag-end');
this._inDrag = false;
this._inItemDrag = false;
},
beginWindowDrag: function(window) {
this.emit('window-drag-begin', window);
this._inDrag = true;
this._inWindowDrag = true;
},
cancelledWindowDrag: function(window) {
@ -439,8 +441,10 @@ var Overview = new Lang.Class({
},
endWindowDrag: function(window) {
if (!this._inWindowDrag)
return;
this.emit('window-drag-end', window);
this._inDrag = false;
this._inWindowDrag = false;
},
focusSearch: function() {
@ -484,7 +488,7 @@ var Overview = new Lang.Class({
shouldToggleByCornerOrButton: function() {
if (this.animationInProgress)
return false;
if (this._inDrag)
if (this._inItemDrag || this._inWindowDrag)
return false;
if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
return true;

View File

@ -977,12 +977,12 @@ var PadOsdService = new Lang.Class({
let padDevice = null;
devices.forEach(Lang.bind(this, function(device) {
if (deviceNode == device.get_device_node())
if (deviceNode == device.get_device_node() &&
device.get_device_type() == Clutter.InputDeviceType.PAD_DEVICE)
padDevice = device;
}));
if (padDevice == null ||
padDevice.get_device_type() != Clutter.InputDeviceType.PAD_DEVICE) {
if (padDevice == null) {
invocation.return_error_literal(Gio.IOErrorEnum,
Gio.IOErrorEnum.CANCELLED,
"Invalid params");

View File

@ -720,7 +720,9 @@ var AggregateMenu = new Lang.Class({
this._screencast = new imports.ui.status.screencast.Indicator();
this._location = new imports.ui.status.location.Indicator();
this._nightLight = new imports.ui.status.nightLight.Indicator();
this._thunderbolt = new imports.ui.status.thunderbolt.Indicator();
this._indicators.add_child(this._thunderbolt.indicators);
this._indicators.add_child(this._screencast.indicators);
this._indicators.add_child(this._location.indicators);
this._indicators.add_child(this._nightLight.indicators);
@ -763,7 +765,6 @@ const PANEL_ITEM_IMPLEMENTATIONS = {
'appMenu': AppMenuButton,
'dateMenu': imports.ui.dateMenu.DateMenuButton,
'a11y': imports.ui.status.accessibility.ATIndicator,
'a11yGreeter': imports.ui.status.accessibility.ATGreeterIndicator,
'keyboard': imports.ui.status.keyboard.InputSourceIndicator,
};
@ -798,6 +799,7 @@ var Panel = new Lang.Class({
this.actor.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this.actor.connect('allocate', Lang.bind(this, this._allocate));
this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
this.actor.connect('key-press-event', Lang.bind(this, this._onKeyPress));
Main.overview.connect('showing', Lang.bind(this, function () {
this.actor.add_style_pseudo_class('overview');
@ -819,6 +821,7 @@ var Panel = new Lang.Class({
global.window_group.connect('actor-removed', Lang.bind(this, this._onWindowActorRemoved));
global.window_manager.connect('switch-workspace', Lang.bind(this, this._updateSolidStyle));
global.screen.connect('workareas-changed', () => { this.actor.queue_relayout(); });
this._updatePanel();
},
@ -865,7 +868,16 @@ var Panel = new Lang.Class({
let sideWidth, centerWidth;
centerWidth = centerNaturalWidth;
sideWidth = Math.max(0, (allocWidth - centerWidth) / 2);
// get workspace area and center date entry relative to it
let monitor = Main.layoutManager.findMonitorForActor(actor);
let centerOffset = 0;
if (monitor) {
let workArea = Main.layoutManager.getWorkAreaForMonitor(monitor.index);
centerOffset = 2 * (workArea.x - monitor.x) + workArea.width - monitor.width;
}
sideWidth = Math.max(0, (allocWidth - centerWidth + centerOffset) / 2);
let childBox = new Clutter.ActorBox();
@ -965,6 +977,16 @@ var Panel = new Lang.Class({
return Clutter.EVENT_STOP;
},
_onKeyPress: function(actor, event) {
let symbol = event.get_key_symbol();
if (symbol == Clutter.KEY_Escape) {
global.screen.focus_default_window(event.get_time());
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
},
_toggleMenu: function(indicator) {
if (!indicator) // menu not supported by current session mode
return;

View File

@ -405,7 +405,7 @@ var PopupImageMenuItem = new Lang.Class({
setIcon: function(icon) {
// The 'icon' parameter can be either a Gio.Icon or a string.
if (GObject.type_is_a(icon, Gio.Icon))
if (icon instanceof GObject.Object && GObject.type_is_a(icon, Gio.Icon))
this._icon.gicon = icon;
else
this._icon.icon_name = icon;

View File

@ -1283,7 +1283,10 @@ var ScreenShield = new Lang.Class({
this._resetLockScreen({ animateLockScreen: animate,
fadeToBlack: true });
global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true));
// On wayland, a crash brings down the entire session, so we don't
// need to defend against being restarted unlocked
if (!Meta.is_wayland_compositor())
global.set_runtime_state(LOCKED_STATE_STR, GLib.Variant.new('b', true));
// We used to set isActive and emit active-changed here,
// but now we do that from lockScreenShown, which means

View File

@ -49,7 +49,7 @@ const _modes = {
panel: {
left: [],
center: ['dateMenu'],
right: ['a11yGreeter', 'keyboard', 'aggregateMenu'],
right: ['a11y', 'keyboard', 'aggregateMenu']
},
panelStyle: 'login-screen'
},

View File

@ -212,12 +212,3 @@ var ATIndicator = new Lang.Class({
return widget;
}
});
var ATGreeterIndicator = new Lang.Class({
Name: 'ATGreeterIndicator',
Extends: ATIndicator,
// Override visibility handling to be always visible
_syncMenuVisibility: function() { },
_queueSyncMenuVisibility: function() { }
});

View File

@ -15,6 +15,7 @@ const RfkillManagerInterface = '<node> \
<interface name="org.gnome.SettingsDaemon.Rfkill"> \
<property name="BluetoothAirplaneMode" type="b" access="readwrite" /> \
<property name="BluetoothHasAirplaneMode" type="b" access="read" /> \
<property name="BluetoothHardwareAirplaneMode" type="b" access="readwrite" /> \
</interface> \
</node>';

View File

@ -457,7 +457,7 @@ var InputSourceManager = new Lang.Class({
this._changePerWindowSource();
},
_activateInputSource: function(is, interactive) {
activateInputSource: function(is, interactive) {
KeyboardManager.holdKeyboard();
this._keyboardManager.apply(is.xkbId);
@ -529,6 +529,7 @@ var InputSourceManager = new Lang.Class({
let sources = this._settings.inputSources;
let nSources = sources.length;
this._currentSource = null;
this._inputSources = {};
this._ibusSources = {};
@ -577,7 +578,7 @@ var InputSourceManager = new Lang.Class({
infosList[i].displayName,
infosList[i].shortName,
i);
is.connect('activate', Lang.bind(this, this._activateInputSource));
is.connect('activate', Lang.bind(this, this.activateInputSource));
if (!(is.shortName in inputSourcesByShortName))
inputSourcesByShortName[is.shortName] = [];
@ -827,6 +828,9 @@ var InputSourceIndicator = new Lang.Class({
for (let i in this._indicatorLabels)
this._indicatorLabels[i].destroy();
this._menuItems = {};
this._indicatorLabels = {};
let menuIndex = 0;
for (let i in this._inputSourceManager.inputSources) {
let is = this._inputSourceManager.inputSources[i];

View File

@ -321,7 +321,7 @@ var AppAuthorizer = new Lang.Class({
_userAuthorizeApp: function() {
let name = this._app.get_name();
let appInfo = this._app.get_app_info();
let reason = appInfo.get_string("X-Geoclue-Reason");
let reason = appInfo.get_locale_string("X-Geoclue-Reason");
this._showAppAuthDialog(name, reason);
},

View File

@ -6,9 +6,7 @@ const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
const NetworkManager = imports.gi.NetworkManager;
const NMClient = imports.gi.NMClient;
const NMGtk = imports.gi.NMGtk;
const NM = imports.gi.NM;
const Signals = imports.signals;
const Shell = imports.gi.Shell;
const St = imports.gi.St;
@ -43,9 +41,9 @@ const NMAccessPointSecurity = {
var MAX_DEVICE_ITEMS = 4;
// small optimization, to avoid using [] all the time
const NM80211Mode = NetworkManager['80211Mode'];
const NM80211ApFlags = NetworkManager['80211ApFlags'];
const NM80211ApSecurityFlags = NetworkManager['80211ApSecurityFlags'];
const NM80211Mode = NM['80211Mode'];
const NM80211ApFlags = NM['80211ApFlags'];
const NM80211ApSecurityFlags = NM['80211ApSecurityFlags'];
var PortalHelperResult = {
CANCELLED: 0,
@ -74,18 +72,6 @@ const PortalHelperIface = '<node> \
</node>';
const PortalHelperProxy = Gio.DBusProxy.makeProxyWrapper(PortalHelperIface);
function ssidCompare(one, two) {
if (!one || !two)
return false;
if (one.length != two.length)
return false;
for (let i = 0; i < one.length; i++) {
if (one[i] != two[i])
return false;
}
return true;
}
function signalToIcon(value) {
if (value > 80)
return 'excellent';
@ -99,16 +85,14 @@ function signalToIcon(value) {
}
function ssidToLabel(ssid) {
let label = NetworkManager.utils_ssid_to_utf8(ssid);
let label = NM.utils_ssid_to_utf8(ssid.get_data());
if (!label)
label = _("<unknown>");
return label;
}
function ensureActiveConnectionProps(active, settings) {
if (!active._connection) {
active._connection = settings.get_connection_by_path(active.connection);
function ensureActiveConnectionProps(active, client) {
if (!active._primaryDevice) {
// This list is guaranteed to have only one device in it.
let device = active.get_devices()[0]._delegate;
active._primaryDevice = device;
@ -162,7 +146,7 @@ var NMConnectionItem = new Lang.Class({
if (this._activeConnection == null)
return false;
return this._activeConnection.state <= NetworkManager.ActiveConnectionState.ACTIVATED;
return this._activeConnection.state <= NM.ActiveConnectionState.ACTIVATED;
},
_sync: function() {
@ -346,10 +330,9 @@ var NMConnectionDevice = new Lang.Class({
Extends: NMConnectionSection,
Abstract: true,
_init: function(client, device, settings) {
_init: function(client, device) {
this.parent(client);
this._device = device;
this._settings = settings;
this._description = '';
this._autoConnectItem = this.item.menu.addAction(_("Connect"), Lang.bind(this, this._autoConnect));
@ -363,12 +346,12 @@ var NMConnectionDevice = new Lang.Class({
if (this._client.primary_connection != this._device.active_connection)
return true;
return this._client.connectivity == NetworkManager.ConnectivityState.FULL;
return this._client.connectivity == NM.ConnectivityState.FULL;
},
_autoConnect: function() {
let connection = new NetworkManager.Connection();
this._client.add_and_activate_connection(connection, this._device, null, null);
let connection = new NM.SimpleConnection();
this._client.add_and_activate_connection_async(connection, this._device, null, null, null);
},
destroy: function() {
@ -386,17 +369,12 @@ var NMConnectionDevice = new Lang.Class({
_activeConnectionChanged: function() {
if (this._activeConnection) {
let item = this._connectionItems.get(this._activeConnection._connection.get_uuid());
let item = this._connectionItems.get(this._activeConnection.connection.get_uuid());
item.setActiveConnection(null);
this._activeConnection = null;
}
this._activeConnection = this._device.active_connection;
if (this._activeConnection) {
ensureActiveConnectionProps(this._activeConnection, this._settings);
let item = this._connectionItems.get(this._activeConnection._connection.get_uuid());
item.setActiveConnection(this._activeConnection);
}
this._sync();
},
_deviceStateChanged: function(device, newstate, oldstate, reason) {
@ -408,8 +386,8 @@ var NMConnectionDevice = new Lang.Class({
/* Emit a notification if activation fails, but don't do it
if the reason is no secrets, as that indicates the user
cancelled the agent dialog */
if (newstate == NetworkManager.DeviceState.FAILED &&
reason != NetworkManager.DeviceStateReason.NO_SECRETS) {
if (newstate == NM.DeviceState.FAILED &&
reason != NM.DeviceStateReason.NO_SECRETS) {
this.emit('activation-failed', reason);
}
@ -421,7 +399,7 @@ var NMConnectionDevice = new Lang.Class({
},
activateConnection: function(connection) {
this._client.activate_connection(connection, this._device, null, null);
this._client.activate_connection_async(connection, this._device, null, null, null);
},
deactivateConnection: function(activeConnection) {
@ -440,7 +418,18 @@ var NMConnectionDevice = new Lang.Class({
_sync: function() {
let nItems = this._connectionItems.size;
this._autoConnectItem.actor.visible = (nItems == 0);
this._deactivateItem.actor.visible = this._device.state > NetworkManager.DeviceState.DISCONNECTED;
this._deactivateItem.actor.visible = this._device.state > NM.DeviceState.DISCONNECTED;
if (this._activeConnection == null) {
this._activeConnection = this._device.active_connection;
if (this._activeConnection) {
ensureActiveConnectionProps(this._activeConnection, this._client);
let item = this._connectionItems.get(this._activeConnection.connection.get_uuid());
item.setActiveConnection(this._activeConnection);
}
}
this.parent();
},
@ -449,31 +438,31 @@ var NMConnectionDevice = new Lang.Class({
return '';
switch(this._device.state) {
case NetworkManager.DeviceState.DISCONNECTED:
case NM.DeviceState.DISCONNECTED:
/* Translators: %s is a network identifier */
return _("%s Off").format(this._getDescription());
case NetworkManager.DeviceState.ACTIVATED:
case NM.DeviceState.ACTIVATED:
/* Translators: %s is a network identifier */
return _("%s Connected").format(this._getDescription());
case NetworkManager.DeviceState.UNMANAGED:
case NM.DeviceState.UNMANAGED:
/* Translators: this is for network devices that are physically present but are not
under NetworkManager's control (and thus cannot be used in the menu);
%s is a network identifier */
return _("%s Unmanaged").format(this._getDescription());
case NetworkManager.DeviceState.DEACTIVATING:
case NM.DeviceState.DEACTIVATING:
/* Translators: %s is a network identifier */
return _("%s Disconnecting").format(this._getDescription());
case NetworkManager.DeviceState.PREPARE:
case NetworkManager.DeviceState.CONFIG:
case NetworkManager.DeviceState.IP_CONFIG:
case NetworkManager.DeviceState.IP_CHECK:
case NetworkManager.DeviceState.SECONDARIES:
case NM.DeviceState.PREPARE:
case NM.DeviceState.CONFIG:
case NM.DeviceState.IP_CONFIG:
case NM.DeviceState.IP_CHECK:
case NM.DeviceState.SECONDARIES:
/* Translators: %s is a network identifier */
return _("%s Connecting").format(this._getDescription());
case NetworkManager.DeviceState.NEED_AUTH:
case NM.DeviceState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password; %s is a network identifier */
return _("%s Requires Authentication").format(this._getDescription());
case NetworkManager.DeviceState.UNAVAILABLE:
case NM.DeviceState.UNAVAILABLE:
// This state is actually a compound of various states (generically unavailable,
// firmware missing), that are exposed by different properties (whose state may
// or may not updated when we receive state-changed).
@ -485,7 +474,7 @@ var NMConnectionDevice = new Lang.Class({
/* Translators: this is for a network device that cannot be activated (for example it
is disabled by rfkill, or it has no coverage; %s is a network identifier */
return _("%s Unavailable").format(this._getDescription());
case NetworkManager.DeviceState.FAILED:
case NM.DeviceState.FAILED:
/* Translators: %s is a network identifier */
return _("%s Connection Failed").format(this._getDescription());
default:
@ -500,14 +489,14 @@ var NMDeviceWired = new Lang.Class({
Extends: NMConnectionDevice,
category: NMConnectionCategory.WIRED,
_init: function(client, device, settings) {
this.parent(client, device, settings);
_init: function(client, device) {
this.parent(client, device);
this.item.menu.addSettingsAction(_("Wired Settings"), 'gnome-network-panel.desktop');
},
_hasCarrier: function() {
if (this._device instanceof NMClient.DeviceEthernet)
if (this._device instanceof NM.DeviceEthernet)
return this._device.carrier;
else
return true;
@ -522,9 +511,9 @@ var NMDeviceWired = new Lang.Class({
if (this._device.active_connection) {
let state = this._device.active_connection.state;
if (state == NetworkManager.ActiveConnectionState.ACTIVATING) {
if (state == NM.ActiveConnectionState.ACTIVATING) {
return 'network-wired-acquiring-symbolic';
} else if (state == NetworkManager.ActiveConnectionState.ACTIVATED) {
} else if (state == NM.ActiveConnectionState.ACTIVATED) {
if (this._canReachInternet())
return 'network-wired-symbolic';
else
@ -542,8 +531,8 @@ var NMDeviceModem = new Lang.Class({
Extends: NMConnectionDevice,
category: NMConnectionCategory.WWAN,
_init: function(client, device, settings) {
this.parent(client, device, settings);
_init: function(client, device) {
this.parent(client, device);
this.item.menu.addSettingsAction(_("Mobile Broadband Settings"), 'gnome-network-panel.desktop');
@ -552,11 +541,11 @@ var NMDeviceModem = new Lang.Class({
let capabilities = device.current_capabilities;
if (device.udi.indexOf('/org/freedesktop/ModemManager1/Modem') == 0)
this._mobileDevice = new ModemManager.BroadbandModem(device.udi, capabilities);
else if (capabilities & NetworkManager.DeviceModemCapabilities.GSM_UMTS)
else if (capabilities & NM.DeviceModemCapabilities.GSM_UMTS)
this._mobileDevice = new ModemManager.ModemGsm(device.udi);
else if (capabilities & NetworkManager.DeviceModemCapabilities.CDMA_EVDO)
else if (capabilities & NM.DeviceModemCapabilities.CDMA_EVDO)
this._mobileDevice = new ModemManager.ModemCdma(device.udi);
else if (capabilities & NetworkManager.DeviceModemCapabilities.LTE)
else if (capabilities & NM.DeviceModemCapabilities.LTE)
this._mobileDevice = new ModemManager.ModemGsm(device.udi);
if (this._mobileDevice) {
@ -593,7 +582,7 @@ var NMDeviceModem = new Lang.Class({
/* Translators: this is for a network device that cannot be activated
because it's disabled by rfkill (airplane mode); %s is a network identifier */
return _("%s Disabled").format(this._getDescription());
else if (this._device.state == NetworkManager.DeviceState.ACTIVATED &&
else if (this._device.state == NM.DeviceState.ACTIVATED &&
this._mobileDevice && this._mobileDevice.operator_name)
return this._mobileDevice.operator_name;
else
@ -602,7 +591,7 @@ var NMDeviceModem = new Lang.Class({
getIndicatorIcon: function() {
if (this._device.active_connection) {
if (this._device.active_connection.state == NetworkManager.ActiveConnectionState.ACTIVATING)
if (this._device.active_connection.state == NM.ActiveConnectionState.ACTIVATING)
return 'network-cellular-acquiring-symbolic';
return this._getSignalIcon();
@ -621,8 +610,8 @@ var NMDeviceBluetooth = new Lang.Class({
Extends: NMConnectionDevice,
category: NMConnectionCategory.WWAN,
_init: function(client, device, settings) {
this.parent(client, device, settings);
_init: function(client, device) {
this.parent(client, device);
this.item.menu.addSettingsAction(_("Bluetooth Settings"), 'gnome-network-panel.desktop');
},
@ -638,9 +627,9 @@ var NMDeviceBluetooth = new Lang.Class({
getIndicatorIcon: function() {
if (this._device.active_connection) {
let state = this._device.active_connection.state;
if (state == NetworkManager.ActiveConnectionState.ACTIVATING)
if (state == NM.ActiveConnectionState.ACTIVATING)
return 'network-cellular-acquiring-symbolic';
else if (state == NetworkManager.ActiveConnectionState.ACTIVATED)
else if (state == NM.ActiveConnectionState.ACTIVATED)
return 'network-cellular-connected-symbolic';
else
return 'network-cellular-signal-none-symbolic';
@ -719,7 +708,7 @@ var NMWirelessDialog = new Lang.Class({
Name: 'NMWirelessDialog',
Extends: ModalDialog.ModalDialog,
_init: function(client, device, settings) {
_init: function(client, device) {
this.parent({ styleClass: 'nm-dialog' });
this._client = client;
@ -735,7 +724,7 @@ var NMWirelessDialog = new Lang.Class({
this._networks = [];
this._buildLayout();
let connections = settings.list_connections();
let connections = client.get_connections();
this._connections = connections.filter(Lang.bind(this, function(connection) {
return device.connection_valid(connection);
}));
@ -799,7 +788,7 @@ var NMWirelessDialog = new Lang.Class({
},
_onScanTimeout: function() {
this._device.request_scan_simple(null);
this._device.request_scan_async(null, null);
return GLib.SOURCE_CONTINUE;
},
@ -944,18 +933,18 @@ var NMWirelessDialog = new Lang.Class({
let network = this._selectedNetwork;
if (network.connections.length > 0) {
let connection = network.connections[0];
this._client.activate_connection(connection, this._device, null, null);
this._client.activate_connection_async(connection, this._device, null, null, null);
} else {
let accessPoints = network.accessPoints;
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
// 802.1x-enabled APs require further configuration, so they're
// handled in gnome-control-center
Util.spawn(['gnome-control-center', 'network', 'connect-8021x-wifi',
this._device.get_path(), accessPoints[0].dbus_path]);
Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi',
this._device.get_path(), accessPoints[0].path]);
} else {
let connection = new NetworkManager.Connection();
this._client.add_and_activate_connection(connection, this._device, accessPoints[0].dbus_path, null)
let connection = new NM.SimpleConnection();
this._client.add_and_activate_connection_async(connection, this._device, accessPoints[0].path, null, null)
}
}
@ -1035,7 +1024,7 @@ var NMWirelessDialog = new Lang.Class({
},
_networkCompare: function(network, accessPoint) {
if (!ssidCompare(network.ssid, accessPoint.get_ssid()))
if (!network.ssid.equal (accessPoint.get_ssid()))
return false;
if (network.mode != accessPoint.mode)
return false;
@ -1180,10 +1169,9 @@ var NMDeviceWireless = new Lang.Class({
Name: 'NMDeviceWireless',
category: NMConnectionCategory.WIRELESS,
_init: function(client, device, settings) {
_init: function(client, device) {
this._client = client;
this._device = device;
this._settings = settings;
this._description = '';
@ -1252,8 +1240,8 @@ var NMDeviceWireless = new Lang.Class({
/* Emit a notification if activation fails, but don't do it
if the reason is no secrets, as that indicates the user
cancelled the agent dialog */
if (newstate == NetworkManager.DeviceState.FAILED &&
reason != NetworkManager.DeviceStateReason.NO_SECRETS) {
if (newstate == NM.DeviceState.FAILED &&
reason != NM.DeviceStateReason.NO_SECRETS) {
this.emit('activation-failed', reason);
}
@ -1265,7 +1253,7 @@ var NMDeviceWireless = new Lang.Class({
},
_showDialog: function() {
this._dialog = new NMWirelessDialog(this._client, this._device, this._settings);
this._dialog = new NMWirelessDialog(this._client, this._device);
this._dialog.connect('closed', Lang.bind(this, this._dialogClosed));
this._dialog.open();
},
@ -1314,8 +1302,8 @@ var NMDeviceWireless = new Lang.Class({
if (this._isHotSpotMaster())
/* Translators: %s is a network identifier */
return _("%s Hotspot Active").format(this._description);
else if (this._device.state >= NetworkManager.DeviceState.PREPARE &&
this._device.state < NetworkManager.DeviceState.ACTIVATED)
else if (this._device.state >= NM.DeviceState.PREPARE &&
this._device.state < NM.DeviceState.ACTIVATED)
/* Translators: %s is a network identifier */
return _("%s Connecting").format(this._description);
else if (ap)
@ -1326,7 +1314,7 @@ var NMDeviceWireless = new Lang.Class({
else if (!this._client.wireless_enabled)
/* Translators: %s is a network identifier */
return _("%s Off").format(this._description);
else if (this._device.state == NetworkManager.DeviceState.DISCONNECTED)
else if (this._device.state == NM.DeviceState.DISCONNECTED)
/* Translators: %s is a network identifier */
return _("%s Not Connected").format(this._description);
else
@ -1344,18 +1332,14 @@ var NMDeviceWireless = new Lang.Class({
if (this._client.primary_connection != this._device.active_connection)
return true;
return this._client.connectivity == NetworkManager.ConnectivityState.FULL;
return this._client.connectivity == NM.ConnectivityState.FULL;
},
_isHotSpotMaster: function() {
if (!this._device.active_connection)
return false;
let connectionPath = this._device.active_connection.connection;
if (!connectionPath)
return false;
let connection = this._settings.get_connection_by_path(connectionPath);
let connection = this._device.active_connection.connection;
if (!connection)
return false;
@ -1363,13 +1347,13 @@ var NMDeviceWireless = new Lang.Class({
if (!ip4config)
return false;
return ip4config.get_method() == NetworkManager.SETTING_IP4_CONFIG_METHOD_SHARED;
return ip4config.get_method() == NM.SETTING_IP4_CONFIG_METHOD_SHARED;
},
getIndicatorIcon: function() {
if (this._device.state < NetworkManager.DeviceState.PREPARE)
if (this._device.state < NM.DeviceState.PREPARE)
return 'network-wireless-disconnected-symbolic';
if (this._device.state < NetworkManager.DeviceState.ACTIVATED)
if (this._device.state < NM.DeviceState.ACTIVATED)
return 'network-wireless-acquiring-symbolic';
if (this._isHotSpotMaster())
@ -1394,15 +1378,15 @@ var NMDeviceWireless = new Lang.Class({
});
Signals.addSignalMethods(NMDeviceWireless.prototype);
var NMVPNConnectionItem = new Lang.Class({
Name: 'NMVPNConnectionItem',
var NMVpnConnectionItem = new Lang.Class({
Name: 'NMVpnConnectionItem',
Extends: NMConnectionItem,
isActive: function() {
if (this._activeConnection == null)
return false;
return this._activeConnection.vpn_state != NetworkManager.VPNConnectionState.DISCONNECTED;
return this._activeConnection.vpn_state != NM.VpnConnectionState.DISCONNECTED;
},
_buildUI: function() {
@ -1426,17 +1410,17 @@ var NMVPNConnectionItem = new Lang.Class({
return null;
switch(this._activeConnection.vpn_state) {
case NetworkManager.VPNConnectionState.DISCONNECTED:
case NetworkManager.VPNConnectionState.ACTIVATED:
case NM.VpnConnectionState.DISCONNECTED:
case NM.VpnConnectionState.ACTIVATED:
return null;
case NetworkManager.VPNConnectionState.PREPARE:
case NetworkManager.VPNConnectionState.CONNECT:
case NetworkManager.VPNConnectionState.IP_CONFIG_GET:
case NM.VpnConnectionState.PREPARE:
case NM.VpnConnectionState.CONNECT:
case NM.VpnConnectionState.IP_CONFIG_GET:
return _("connecting…");
case NetworkManager.VPNConnectionState.NEED_AUTH:
case NM.VpnConnectionState.NEED_AUTH:
/* Translators: this is for network connections that require some kind of key or password */
return _("authentication required");
case NetworkManager.VPNConnectionState.FAILED:
case NM.VpnConnectionState.FAILED:
return _("connection failed");
default:
return 'invalid';
@ -1444,11 +1428,11 @@ var NMVPNConnectionItem = new Lang.Class({
},
_connectionStateChanged: function(ac, newstate, reason) {
if (newstate == NetworkManager.VPNConnectionState.FAILED &&
reason != NetworkManager.VPNConnectionStateReason.NO_SECRETS) {
if (newstate == NM.VpnConnectionState.FAILED &&
reason != NM.VpnConnectionStateReason.NO_SECRETS) {
// FIXME: if we ever want to show something based on reason,
// we need to convert from NetworkManager.VPNConnectionStateReason
// to NetworkManager.DeviceStateReason
// we need to convert from NM.VpnConnectionStateReason
// to NM.DeviceStateReason
this.emit('activation-failed', reason);
}
@ -1473,7 +1457,7 @@ var NMVPNConnectionItem = new Lang.Class({
getIndicatorIcon: function() {
if (this._activeConnection) {
if (this._activeConnection.vpn_state < NetworkManager.VPNConnectionState.ACTIVATED)
if (this._activeConnection.vpn_state < NM.VpnConnectionState.ACTIVATED)
return 'network-vpn-acquiring-symbolic';
else
return 'network-vpn-symbolic';
@ -1483,8 +1467,8 @@ var NMVPNConnectionItem = new Lang.Class({
},
});
var NMVPNSection = new Lang.Class({
Name: 'NMVPNSection',
var NMVpnSection = new Lang.Class({
Name: 'NMVpnSection',
Extends: NMConnectionSection,
category: NMConnectionCategory.VPN,
@ -1492,6 +1476,15 @@ var NMVPNSection = new Lang.Class({
this.parent(client);
this.item.menu.addSettingsAction(_("VPN Settings"), 'gnome-network-panel.desktop');
this._sync();
},
_sync: function() {
let nItems = this._connectionItems.size;
this.item.actor.visible = (nItems > 0);
this.parent();
},
_getDescription: function() {
@ -1513,11 +1506,11 @@ var NMVPNSection = new Lang.Class({
},
activateConnection: function(connection) {
this._client.activate_connection(connection, null, null, null);
this._client.activate_connection_async(connection, null, null, null, null);
},
deactivateConnection: function(activeConnection) {
this._client.deactivate_connection(activeConnection);
this._client.deactivate_connection(activeConnection, null);
},
setActiveConnections: function(vpnConnections) {
@ -1526,15 +1519,15 @@ var NMVPNSection = new Lang.Class({
item.setActiveConnection(null);
}
vpnConnections.forEach(Lang.bind(this, function(a) {
if (a._connection) {
let item = this._connectionItems.get(a._connection.get_uuid());
if (a.connection) {
let item = this._connectionItems.get(a.connection.get_uuid());
item.setActiveConnection(a);
}
}));
},
_makeConnectionItem: function(connection) {
return new NMVPNConnectionItem(this, connection);
return new NMVpnConnectionItem(this, connection);
},
getIndicatorIcon: function() {
@ -1547,7 +1540,7 @@ var NMVPNSection = new Lang.Class({
return '';
},
});
Signals.addSignalMethods(NMVPNSection.prototype);
Signals.addSignalMethods(NMVpnSection.prototype);
var DeviceCategory = new Lang.Class({
Name: 'DeviceCategory',
@ -1628,40 +1621,25 @@ var NMApplet = new Lang.Class({
// Device types
this._dtypes = { };
this._dtypes[NetworkManager.DeviceType.ETHERNET] = NMDeviceWired;
this._dtypes[NetworkManager.DeviceType.WIFI] = NMDeviceWireless;
this._dtypes[NetworkManager.DeviceType.MODEM] = NMDeviceModem;
this._dtypes[NetworkManager.DeviceType.BT] = NMDeviceBluetooth;
// TODO: WiMax support
this._dtypes[NM.DeviceType.ETHERNET] = NMDeviceWired;
this._dtypes[NM.DeviceType.WIFI] = NMDeviceWireless;
this._dtypes[NM.DeviceType.MODEM] = NMDeviceModem;
this._dtypes[NM.DeviceType.BT] = NMDeviceBluetooth;
// Connection types
this._ctypes = { };
this._ctypes[NetworkManager.SETTING_WIRED_SETTING_NAME] = NMConnectionCategory.WIRED;
this._ctypes[NetworkManager.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
this._ctypes[NetworkManager.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NetworkManager.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
this._ctypes[NM.SETTING_WIRED_SETTING_NAME] = NMConnectionCategory.WIRED;
this._ctypes[NM.SETTING_WIRELESS_SETTING_NAME] = NMConnectionCategory.WIRELESS;
this._ctypes[NM.SETTING_BLUETOOTH_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_CDMA_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_GSM_SETTING_NAME] = NMConnectionCategory.WWAN;
this._ctypes[NM.SETTING_VPN_SETTING_NAME] = NMConnectionCategory.VPN;
NMClient.Client.new_async(null, Lang.bind(this, this._clientGot));
NMClient.RemoteSettings.new_async(null, null, Lang.bind(this, this._remoteSettingsGot));
NM.Client.new_async(null, Lang.bind(this, this._clientGot));
},
_clientGot: function(obj, result) {
this._client = NMClient.Client.new_finish(result);
this._tryLateInit();
},
_remoteSettingsGot: function(obj, result) {
this._settings = NMClient.RemoteSettings.new_finish(result);
this._tryLateInit();
},
_tryLateInit: function() {
if (!this._client || !this._settings)
return;
this._client = NM.Client.new_finish(result);
this._activeConnections = [ ];
this._connections = [ ];
@ -1684,7 +1662,7 @@ var NMApplet = new Lang.Class({
this.menu.addMenuItem(this._devices[category]);
}
this._vpnSection = new NMVPNSection(this._client);
this._vpnSection = new NMVpnSection(this._client);
this._vpnSection.connect('activation-failed', Lang.bind(this, this._onActivationFailed));
this._vpnSection.connect('icon-changed', Lang.bind(this, this._updateIcon));
this.menu.addMenuItem(this._vpnSection.item);
@ -1693,18 +1671,19 @@ var NMApplet = new Lang.Class({
this._readDevices();
this._syncNMState();
this._syncMainConnection();
this._syncVPNConnections();
this._syncVpnConnections();
this._client.connect('notify::manager-running', Lang.bind(this, this._syncNMState));
this._client.connect('notify::nm-running', Lang.bind(this, this._syncNMState));
this._client.connect('notify::networking-enabled', Lang.bind(this, this._syncNMState));
this._client.connect('notify::state', Lang.bind(this, this._syncNMState));
this._client.connect('notify::primary-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::activating-connection', Lang.bind(this, this._syncMainConnection));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVPNConnections));
this._client.connect('notify::active-connections', Lang.bind(this, this._syncVpnConnections));
this._client.connect('notify::connectivity', Lang.bind(this, this._syncConnectivity));
this._client.connect('device-added', Lang.bind(this, this._deviceAdded));
this._client.connect('device-removed', Lang.bind(this, this._deviceRemoved));
this._settings.connect('new-connection', Lang.bind(this, this._newConnection));
this._client.connect('connection-added', Lang.bind(this, this._connectionAdded));
this._client.connect('connection-removed', Lang.bind(this, this._connectionRemoved));
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
this._sessionUpdated();
@ -1762,7 +1741,7 @@ var NMApplet = new Lang.Class({
},
_syncDeviceNames: function() {
let names = NMGtk.utils_disambiguate_device_names(this._nmDevices);
let names = NM.Device.disambiguate_names(this._nmDevices);
for (let i = 0; i < this._nmDevices.length; i++) {
let device = this._nmDevices[i];
let description = names[i];
@ -1779,7 +1758,7 @@ var NMApplet = new Lang.Class({
let wrapperClass = this._dtypes[device.get_device_type()];
if (wrapperClass) {
let wrapper = new wrapperClass(this._client, device, this._settings);
let wrapper = new wrapperClass(this._client, device);
device._delegate = wrapper;
this._addDeviceWrapper(wrapper);
@ -1836,13 +1815,13 @@ var NMApplet = new Lang.Class({
connection = this._client.get_primary_connection();
if (connection) {
ensureActiveConnectionProps(connection, this._settings);
ensureActiveConnectionProps(connection, this._client);
return connection;
}
connection = this._client.get_activating_connection();
if (connection) {
ensureActiveConnectionProps(connection, this._settings);
ensureActiveConnectionProps(connection, this._client);
return connection;
}
@ -1873,13 +1852,13 @@ var NMApplet = new Lang.Class({
this._syncConnectivity();
},
_syncVPNConnections: function() {
_syncVpnConnections: function() {
let activeConnections = this._client.get_active_connections() || [];
let vpnConnections = activeConnections.filter(function(a) {
return (a instanceof NMClient.VPNConnection);
return (a instanceof NM.VpnConnection);
});
vpnConnections.forEach(Lang.bind(this, function(a) {
ensureActiveConnectionProps(a, this._settings);
ensureActiveConnectionProps(a, this._client);
}));
this._vpnSection.setActiveConnections(vpnConnections);
@ -1887,7 +1866,7 @@ var NMApplet = new Lang.Class({
},
_mainConnectionStateChanged: function() {
if (this._mainConnection.state == NetworkManager.ActiveConnectionState.ACTIVATED && this._notification)
if (this._mainConnection.state == NM.ActiveConnectionState.ACTIVATED && this._notification)
this._notification.destroy();
},
@ -1911,23 +1890,22 @@ var NMApplet = new Lang.Class({
return;
}
connection._removedId = connection.connect('removed', Lang.bind(this, this._connectionRemoved));
connection._updatedId = connection.connect('updated', Lang.bind(this, this._updateConnection));
connection._updatedId = connection.connect('changed', Lang.bind(this, this._updateConnection));
this._updateConnection(connection);
this._connections.push(connection);
},
_readConnections: function() {
let connections = this._settings.list_connections();
let connections = this._client.get_connections();
connections.forEach(Lang.bind(this, this._addConnection));
},
_newConnection: function(settings, connection) {
_connectionAdded: function(client, connection) {
this._addConnection(connection);
},
_connectionRemoved: function(connection) {
_connectionRemoved: function(client, connection) {
let pos = this._connections.indexOf(connection);
if (pos != -1)
this._connections.splice(pos, 1);
@ -1947,13 +1925,12 @@ var NMApplet = new Lang.Class({
}
}
connection.disconnect(connection._removedId);
connection.disconnect(connection._updatedId);
connection._removedId = connection._updatedId = 0;
connection._updatedId = 0;
},
_updateConnection: function(connection) {
let connectionSettings = connection.get_setting_by_name(NetworkManager.SETTING_CONNECTION_SETTING_NAME);
let connectionSettings = connection.get_setting_by_name(NM.SETTING_CONNECTION_SETTING_NAME);
connection._type = connectionSettings.type;
connection._section = this._ctypes[connection._type] || NMConnectionCategory.INVALID;
@ -1974,7 +1951,7 @@ var NMApplet = new Lang.Class({
},
_syncNMState: function() {
this.indicators.visible = this._client.manager_running;
this.indicators.visible = this._client.nm_running;
this.menu.actor.visible = this._client.networking_enabled;
this._syncConnectivity();
@ -2015,7 +1992,7 @@ var NMApplet = new Lang.Class({
this._client.check_connectivity_async(null, Lang.bind(this, function(client, result) {
try {
let state = client.check_connectivity_finish(result);
if (state >= NetworkManager.ConnectivityState.FULL)
if (state >= NM.ConnectivityState.FULL)
this._closeConnectivityCheck(path);
} catch(e) { }
}));
@ -2026,19 +2003,19 @@ var NMApplet = new Lang.Class({
_syncConnectivity: function() {
if (this._mainConnection == null ||
this._mainConnection.state != NetworkManager.ActiveConnectionState.ACTIVATED) {
this._mainConnection.state != NM.ActiveConnectionState.ACTIVATED) {
this._flushConnectivityQueue();
return;
}
let isPortal = this._client.connectivity == NetworkManager.ConnectivityState.PORTAL;
let isPortal = this._client.connectivity == NM.ConnectivityState.PORTAL;
// For testing, allow interpreting any value != FULL as PORTAL, because
// LIMITED (no upstream route after the default gateway) is easy to obtain
// with a tethered phone
// NONE is also possible, with a connection configured to force no default route
// (but in general we should only prompt a portal if we know there is a portal)
if (GLib.getenv('GNOME_SHELL_CONNECTIVITY_TEST') != null)
isPortal = isPortal || this._client.connectivity < NetworkManager.ConnectivityState.FULL;
isPortal = isPortal || this._client.connectivity < NM.ConnectivityState.FULL;
if (!isPortal || Main.sessionMode.isGreeter)
return;
@ -2078,12 +2055,12 @@ var NMApplet = new Lang.Class({
dev = this._mainConnection._primaryDevice;
let state = this._client.get_state();
let connected = state == NetworkManager.State.CONNECTED_GLOBAL;
let connected = state == NM.State.CONNECTED_GLOBAL;
this._primaryIndicator.visible = (dev != null) || connected;
if (dev) {
this._primaryIndicator.icon_name = dev.getIndicatorIcon();
} else if (connected) {
if (this._client.connectivity == NetworkManager.ConnectivityState.FULL)
if (this._client.connectivity == NM.ConnectivityState.FULL)
this._primaryIndicator.icon_name = 'network-wired-symbolic';
else
this._primaryIndicator.icon_name = 'network-wired-no-route-symbolic';

341
js/ui/status/thunderbolt.js Normal file
View File

@ -0,0 +1,341 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
// the following is a modified version of bolt/contrib/js/client.js
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Lang = imports.lang;
const Shell = imports.gi.Shell;
const Signals = imports.signals;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const PanelMenu = imports.ui.panelMenu;
/* Keep in sync with data/org.freedesktop.bolt.xml */
const BoltClientInterface = '<node> \
<interface name="org.freedesktop.bolt1.Manager"> \
<property name="Probing" type="b" access="read"></property> \
<method name="EnrollDevice"> \
<arg type="s" name="uid" direction="in"> </arg> \
<arg type="u" name="policy" direction="in"> </arg> \
<arg type="u" name="flags" direction="in"> </arg> \
<arg name="device" direction="out" type="o"> </arg> \
</method> \
<signal name="DeviceAdded"> \
<arg name="device" type="o"> </arg> \
</signal> \
</interface> \
</node>';
const BoltDeviceInterface = '<node> \
<interface name="org.freedesktop.bolt1.Device"> \
<property name="Uid" type="s" access="read"></property> \
<property name="Name" type="s" access="read"></property> \
<property name="Vendor" type="s" access="read"></property> \
<property name="Status" type="u" access="read"></property> \
<property name="SysfsPath" type="s" access="read"></property> \
<property name="Security" type="u" access="read"></property> \
<property name="Parent" type="s" access="read"></property> \
<property name="Stored" type="b" access="read"></property> \
<property name="Policy" type="u" access="read"></property> \
<property name="Key" type="u" access="read"></property> \
</interface> \
</node>';
const BoltClientProxy = Gio.DBusProxy.makeProxyWrapper(BoltClientInterface);
const BoltDeviceProxy = Gio.DBusProxy.makeProxyWrapper(BoltDeviceInterface);
/* */
var Status = {
DISCONNECTED: 0,
CONNECTED: 1,
AUTHORIZING: 2,
AUTH_ERROR: 3,
AUTHORIZED: 4,
AUTHORIZED_SECURE: 5,
AUTHORIZED_NEWKY: 6
};
var Policy = {
DEFAULT: 0,
MANUAL: 1,
AUTO:2
};
var AuthFlags = {
NONE: 0,
};
const BOLT_DBUS_NAME = 'org.freedesktop.bolt';
const BOLT_DBUS_PATH = '/org/freedesktop/bolt';
var Client = new Lang.Class({
Name: 'BoltClient',
_init: function() {
this._proxy = null;
new BoltClientProxy(
Gio.DBus.system,
BOLT_DBUS_NAME,
BOLT_DBUS_PATH,
Lang.bind(this, this._onProxyReady)
);
this.probing = false;
},
_onProxyReady: function(proxy, error) {
if (error !== null) {
log('error creating bolt proxy: %s'.format(error.message));
return;
}
this._proxy = proxy;
this._propsChangedId = this._proxy.connect('g-properties-changed', Lang.bind(this, this._onPropertiesChanged));
this._deviceAddedId = this._proxy.connectSignal('DeviceAdded', Lang.bind(this, this._onDeviceAdded), true);
this.probing = this._proxy.Probing;
if (this.probing)
this.emit('probing-changed', this.probing);
},
_onPropertiesChanged: function(proxy, properties) {
let unpacked = properties.deep_unpack();
if (!('Probing' in unpacked))
return;
this.probing = this._proxy.Probing;
this.emit('probing-changed', this.probing);
},
_onDeviceAdded: function(proxy, emitter, params) {
let [path] = params;
let device = new BoltDeviceProxy(Gio.DBus.system,
BOLT_DBUS_NAME,
path);
this.emit('device-added', device);
},
/* public methods */
close: function() {
if (!this._proxy)
return;
this._proxy.disconnectSignal(this._deviceAddedId);
this._proxy.disconnect(this._propsChangedId);
this._proxy = null;
},
enrollDevice: function(id, policy, callback) {
this._proxy.EnrollDeviceRemote(id, policy, AuthFlags.NONE,
Lang.bind(this, function (res, error) {
if (error) {
callback(null, error);
return;
}
let [path] = res;
let device = new BoltDeviceProxy(Gio.DBus.system,
BOLT_DBUS_NAME,
path);
callback(device, null);
}));
}
});
Signals.addSignalMethods(Client.prototype);
/* helper class to automatically authorize new devices */
var AuthRobot = new Lang.Class({
Name: 'BoltAuthRobot',
_init: function(client) {
this._client = client;
this._devicesToEnroll = [];
this._enrolling = false;
this._client.connect('device-added', Lang.bind(this, this._onDeviceAdded));
},
close: function() {
this.disconnectAll();
this._client = null;
},
/* the "device-added" signal will be emitted by boltd for every
* device that is not currently stored in the database. We are
* only interested in those devices, because all known devices
* will be handled by the user himself */
_onDeviceAdded: function(cli, dev) {
if (dev.Status !== Status.CONNECTED)
return;
/* check if we should enroll the device */
let res = [false];
this.emit('enroll-device', dev, res);
if (res[0] !== true)
return;
/* ok, we should authorize the device, add it to the back
* of the list */
this._devicesToEnroll.push(dev);
this._enrollDevices();
},
/* The enrollment queue:
* - new devices will be added to the end of the array.
* - an idle callback will be scheduled that will keep
* calling itself as long as there a devices to be
* enrolled.
*/
_enrollDevices: function() {
if (this._enrolling)
return;
this.enrolling = true;
GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._enrollDevicesIdle));
},
_onEnrollDone: function(device, error) {
if (error)
this.emit('enroll-failed', error, device);
/* TODO: scan the list of devices to be authorized for children
* of this device and remove them (and their children and
* their children and ....) from the device queue
*/
this._enrolling = this._devicesToEnroll.length > 0;
if (this._enrolling)
GLib.idle_add(GLib.PRIORITY_DEFAULT,
Lang.bind(this, this._enrollDevicesIdle));
},
_enrollDevicesIdle: function() {
let devices = this._devicesToEnroll;
let dev = devices.shift();
if (dev === undefined)
return GLib.SOURCE_REMOVE;
this._client.enrollDevice(dev.Uid,
Policy.DEFAULT,
Lang.bind(this, this._onEnrollDone));
return GLib.SOURCE_REMOVE;
}
});
Signals.addSignalMethods(AuthRobot.prototype);
/* eof client.js */
var Indicator = new Lang.Class({
Name: 'ThunderboltIndicator',
Extends: PanelMenu.SystemIndicator,
_init: function() {
this.parent();
this._indicator = this._addIndicator();
this._indicator.icon_name = 'thunderbolt-symbolic';
this._client = new Client();
this._client.connect('probing-changed', Lang.bind(this, this._onProbing));
this._robot = new AuthRobot(this._client);
this._robot.connect('enroll-device', Lang.bind(this, this._onEnrollDevice));
this._robot.connect('enroll-failed', Lang.bind(this, this._onEnrollFailed));
Main.sessionMode.connect('updated', Lang.bind(this, this._sync));
this._sync();
this._source = null;
},
_onDestroy: function() {
this._robot.close();
this._client.close();
},
_ensureSource: function() {
if (!this._source) {
this._source = new MessageTray.Source(_("Thunderbolt"),
'thunderbolt-symbolic');
this._source.connect('destroy', Lang.bind(this, function() {
this._source = null;
}));
Main.messageTray.add(this._source);
}
return this._source;
},
_notify: function(title, body) {
if (this._notification)
this._notification.destroy();
let source = this._ensureSource();
this._notification = new MessageTray.Notification(source, title, body);
this._notification.setUrgency(MessageTray.Urgency.HIGH);
this._notification.connect('destroy', function() {
this._notification = null;
});
this._notification.connect('activated', () => {
let app = Shell.AppSystem.get_default().lookup_app('gnome-thunderbolt-panel.desktop');
if (app)
app.activate();
});
this._source.notify(this._notification);
},
/* Session callbacks */
_sync: function() {
let active = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
this._indicator.visible = active && this._client.probing;
},
/* Bolt.Client callbacks */
_onProbing: function(cli, probing) {
if (probing)
this._indicator.icon_name = 'thunderbolt-acquiring-symbolic';
else
this._indicator.icon_name = 'thunderbolt-symbolic';
this._sync();
},
/* AuthRobot callbacks */
_onEnrollDevice: function(obj, device, policy) {
let auth = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
policy[0] = auth;
log("thunderbolt: [%s] auto enrollment: %s".format(device.Name, auth ? 'yes' : 'no'));
if (auth)
return; /* we are done */
const title = _('Unknown Thunderbolt device');
const body = _('New device has been detected while you were away. Please disconnect and reconnect the device to start using it.');
this._notify(title, body);
},
_onEnrollFailed: function (obj, device, error) {
const title = _('Thunderbolt authorization error');
const body = _('Could not authorize the thunderbolt device: %s'.format(error.message));
this._notify(title, body);
}
});

View File

@ -133,6 +133,7 @@ var SwitcherPopup = new Lang.Class({
this.actor.add_actor(this._switcherList.actor);
this._switcherList.connect('item-activated', Lang.bind(this, this._itemActivated));
this._switcherList.connect('item-entered', Lang.bind(this, this._itemEntered));
this._switcherList.connect('item-removed', Lang.bind(this, this._itemRemoved));
// Need to force an allocation so we can figure out whether we
// need to scroll when selecting
@ -247,6 +248,19 @@ var SwitcherPopup = new Lang.Class({
this._itemEnteredHandler(n);
},
_itemRemovedHandler: function(n) {
if (this._items.length > 0) {
let newIndex = Math.min(n, this._items.length - 1);
this._select(newIndex);
} else {
this.actor.destroy();
}
},
_itemRemoved: function(switcher, n) {
this._itemRemovedHandler(n);
},
_disableHover: function() {
this.mouseActive = false;
@ -418,6 +432,12 @@ var SwitcherList = new Lang.Class({
return bbox;
},
removeItem: function(index) {
let item = this._items.splice(index, 1);
item[0].destroy();
this.emit('item-removed', index);
},
_onItemClicked: function (index) {
this._itemActivated(index);
},
@ -432,20 +452,20 @@ var SwitcherList = new Lang.Class({
},
highlight: function(index, justOutline) {
if (this._highlighted != -1) {
if (this._items[this._highlighted]) {
this._items[this._highlighted].remove_style_pseudo_class('outlined');
this._items[this._highlighted].remove_style_pseudo_class('selected');
}
this._highlighted = index;
if (this._highlighted != -1) {
if (this._items[index]) {
if (justOutline)
this._items[this._highlighted].add_style_pseudo_class('outlined');
this._items[index].add_style_pseudo_class('outlined');
else
this._items[this._highlighted].add_style_pseudo_class('selected');
this._items[index].add_style_pseudo_class('selected');
}
this._highlighted = index;
let adjustment = this._scrollView.hscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let [absItemX, absItemY] = this._items[index].get_transformed_position();

View File

@ -606,6 +606,15 @@ var ViewSelector = new Lang.Class({
// - cancel the search
this.reset();
}
} else if (!this._text.has_key_focus() &&
(event.type() == Clutter.EventType.KEY_PRESS ||
event.type() == Clutter.EventType.KEY_RELEASE)) {
let unichar = event.get_key_unicode();
if (GLib.unichar_isprint(unichar)) {
this._text.grab_key_focus();
return this._text.event(event, false);
}
}
return Clutter.EVENT_PROPAGATE;

View File

@ -79,6 +79,15 @@ var Source = new Lang.Class({
this.signalIDs = [];
},
_createPolicy: function() {
if (this._app && this._app.get_app_info()) {
let id = this._app.get_id().replace(/\.desktop$/,'');
return new MessageTray.NotificationApplicationPolicy(id);
} else {
return new MessageTray.NotificationGenericPolicy();
}
},
createIcon : function(size) {
return this._app.create_icon_texture(size);
},

Some files were not shown because too many files have changed in this diff Show More