-
-
Notifications
You must be signed in to change notification settings - Fork 709
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modules: Keyboard Layout #85
Conversation
@Alexays please review |
I tested it by running: |
Doesn't work for me. When I hit keyboard layout switch shortcut, label of module does not change (input layout changes though). Also, would be nice to set it to output only short language code as 'en' or 'de' instead of full layout name. |
@eternal-sorrow Thanks for trying!
Okay, I am a bit confused here. I don't change keyboard layouts, so I am not very familiar with the topic. On the issues page, I was referred to https://github.com/swaywm/sway/wiki#input-configuration which contains documentation of how to change the input configuration.
Okay, will check if the library provides short names. |
I use sway 1.0 beta1. To switch keyboard layout, i've set up input section in my sway config like this:
And so, I switch layout with |
@eternal-sorrow Could you also paste the |
also, by layout are you also referring to the qwerty/dvorak schemes? |
No such line in my config.
no, just Russian/English layout |
Thanks, got it. let me check. |
@@ -9,6 +10,7 @@ class IModule { | |||
virtual ~IModule() = default; | |||
virtual auto update() -> void = 0; | |||
virtual operator Gtk::Widget &() = 0; | |||
virtual void handleSeat(struct wl_seat*, uint32_t) {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this way of doing it, why can't we use the existing dp.emit when we get the seat?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, agreed. This is a RFC patch. I was just trying out to see if we can get the keyboard layout.
Could you please explain how we can use the dp.emit() call to send the seat details?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can store the seat in the bar and pass bar as parameters to the module like sway workspaces and so when emit is called in the module, you just need to access the variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, got it.
I am actually currently discussing with the folks on the #sway IRC, on how to receive the layout change event when the xkb_options key combination is used. I am not sure on how to receive the event without the client actually focused. Do you have any idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll look into it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I searched for a solution. looks like this can be achieved only with a new protocol (or maybe there is an existing one?).
The compositor currently sends modifier events only to the client which has the focus. The keyboard layout group is sent as part of the modifier event. We would need a new protocol to register for such modifier events so that we can change the layout based on the received event.
@Alexays Were you able to find something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the way to go for now is polling then? Kind of sucks to have a delay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
poll what? unless we receive the modifiers from the compositor we will never know of the layout change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is one request in layer shell interface to set keyboard interactivity. Unfortunately, on setting it, all the keyboard events are sent only to the bar as it is the topmost :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
poll what? unless we receive the modifiers from the compositor we will never know of the layout change.
Ah, okay, my assumption was that the information about the current layout could be queried somewhere, but upon further reading it appears that it's managed by Sway and, right now, isn't exposed at all. Bummer.
I have added a new request to wlroots's layer shell v1 interface (patch available here.) This request informs the compositor of our intent to receive keyboard modifiers. When we receive the modifiers, we update our xkb state (specifically the group state) and then call emit. When we query for the layout in the update, it will show the new layout. |
Also, I am yet to incorporate your reviews in the patch. Will do that once I have a proper plan on the solution (either via the protocol or something different) |
Wow such a contribution thank you <3 |
Signed-off-by: Harish Krupo <[email protected]>
This patch adds a new module to show the current keyboard layout. Signed-off-by: Harish Krupo <[email protected]>
Update: Discussions about the new protocol are still ongoing. |
@eternal-sorrow If you need it now, then update to the latest sway and add this script to a custom module:
Replace "1241:5890:USB_Keyboard" with your keyboard identifier and install jq. |
I'll wait till beta.2 release. |
Adjusted the script slightly: #!/usr/bin/env bash
while true; do
x="`swaymsg -t get_inputs | jq --raw-output '[.[] | select(.type == "keyboard") | .xkb_active_layout_name | select(contains("English (US)") | not)] | first'`"
if [[ "${x}" == "null" ]]; then
echo English
else
echo "${x}"
fi
sleep 1
done Drops the need to hardcode your keyboard ID, and also a bit more efficient than having Waybar launch a shell every N seconds. Change "English (US)" to your default. Used like so: "custom/layout": {
"exec": "path/to/script/above"
} No interval. Sharing this for copy-pasting. Edit: Looked into registering on-click/on-scroll layout switching, but Sway's current state of the art is this: swaymsg -t 'command' 'input <device_id> xkb_layout <layout_name>' Can't even set it back to a comma-separated list. So you must maintain your own keyboard-layout-managing script, which takes care of finding out what is the currently active keyboard, what layouts are needed, and what layout to switch to. Basically what XKB does, way too much ad hoc code. |
Sway 1.2 (released 5 hours ago) brings this goodie (thanks, @RedSoxFan!), allowing us to finally get rid of polling (props to @asahaf for spotting this here). It makes the script slightly more complicated: #!/usr/bin/env bash
swaymsg \
--type get_inputs | \
jq \
--raw-output \ '
[
.[] |
select(.type == "keyboard") |
.xkb_active_layout_name |
select(contains("English (US)") | not)
] |
first // "English"
'
swaymsg \
--type subscribe \
--monitor \
--raw \
'["input"]' | \
jq \
--raw-output \
--unbuffered \ '
select(.change == "xkb_layout") |
.input.xkb_active_layout_name |
sub(" \\(US\\)"; "")
' ... but is so worth it! No more electronic ink feel. As before, adjust accordingly if |
here's my python variant (you'll need i3ipc-python >=2.2.1) #!/usr/bin/env -S python3 -u
# vi:syntax=python
import i3ipc
sway = i3ipc.Connection()
# this script works with only one keyboard. we find it's ID.
# it should have more than one layout
for input_dev in sway.get_inputs():
if input_dev.type == 'keyboard' and len(input_dev.xkb_layout_names) > 1:
keyboard = input_dev.identifier
print(input_dev.xkb_active_layout_name[:2].upper())
break
def on_input(sway, event):
if event.input.identifier == keyboard:
print(event.input.xkb_active_layout_name[:2].upper())
sway.on('input::xkb_layout', on_input)
sway.main() |
Thanks @jeremejevs. Here is my variant:
Module (Note: you can replace
Usage (pass identifier as argument):
|
Thanks @jeremejevs and @M1s4k1. Made a little change to show emoji flags #!/usr/bin/env fish
set icons '["🇺🇸", "🇷🇺"]'
swaymsg -t get_inputs | jq -rcM --argjson icons $icons \
"first(.[] | select(.identifier == \"$argv[1]\" and .type == \"keyboard\")) \
| \$icons[.xkb_active_layout_index]"
swaymsg -mrt subscribe '["input"]' | jq -rcM --unbuffered --argjson icons $icons \
"select(.change == \"xkb_layout\")
| .input
| select(.identifier == \"$argv[1]\" and .type == \"keyboard\") \
| \$icons[.xkb_active_layout_index]"
I also tried to return '{"percentage": 0}' (and 1) from jq with config:
but it doesn't get updates from PS, don't forget to add |
Superseded by #659 |
This patch adds a new module to show the current keyboard layout.
Signed-off-by: Harish Krupo [email protected]