raexera/yoru

Keyboard Layout in Wibar [Feature Req]

Closed this issue · 5 comments

Well, I appreciate what you have done. I have literally become a fan of yours. Currently, I'm learning Lua to get started. I desperately need one feature for now. In a wibar I expect to see the current keyboard layout. I'm multilinugal, and I need to often switch my keyboard layout. I have googled on internet, but still couldn't setup myself as I am very noob in ricing.

Lastly, thank you for your all these work.

Well, I appreciate what you have done. I have literally become a fan of yours. Currently, I'm learning Lua to get started. I desperately need one feature for now. In a wibar I expect to see the current keyboard layout. I'm multilinugal, and I need to often switch my keyboard layout. I have googled on internet, but still couldn't setup myself as I am very noob in ricing.

Lastly, thank you for your all these work.

im so glad you love my works, alright for this widgets will be on my todo list, will working on it if i had free time ofc. also instead only showing current kblayout i'll make you can change kblayout directly from the widgets it self!

I'm also missing this feature BADLY!
Btw also love your work, keep it up.

I have done it in very simple (non aesthetic) way. You can use it if you need it badly for now.
In file config/awesome/ui/panels/bottom-panel/init.lua, add this
s.keyboard = awful.widget.keyboardlayout() in line 18
s.keyboard in line 64.
You can change the positions if you want.

Here is a simple and aesthetic solution:

1660517812 screensht

  1. clone keyboard_layout
cd ~/.config/awesome/modules
git clone https://github.com/echuraev/keyboard_layout
  1. edit the init of keyboard_layout

replace require("keyboard_layout.kbdcfg") with require("modules.keyboard_layout.kbdcfg")

  1. edit the bottom-panel

cd ~/.config/awesome/ui/panels/bottom-panel

add this to the init.lua after line 10 and change the keyboard layout and the keybinding as needed:

local keyboard_layout = require("modules.keyboard_layout")

local kbdcfg = keyboard_layout.kbdcfg({type = "tui", remember_layout = true})

kbdcfg.add_primary_layout("English", "US", "us")

kbdcfg.add_primary_layout("Deutsch",  "DE", "de(qwerty)")
kbdcfg.bind()

kbdcfg.widget:buttons(
  awful.util.table.join(awful.button({ }, 1, function () kbdcfg.switch_next() end))
)

awful.keyboard.append_global_keybindings({
  awful.key({"Shift", "Mod4"}, "l", function () kbdcfg.switch_next() end, { description = "switch keyboard layout", group = "WM" })
})

Now add the widget at around line 280. It should look something like this:

layout = wibox.layout.align.horizontal,
expand = "none",
s.clock,
tag_list(s),
{
  system_tray(),
  kbdcfg.widget,
  s.battery,
  s.network,
  notif_panel(),
  layoutbox(),
  layout = wibox.layout.fixed.horizontal,
},

Full init.lua:

local awful = require("awful")
local gears = require("gears")
local wibox = require("wibox")
local beautiful = require("beautiful")
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi
local helpers = require("helpers")
local widgets = require("ui.widgets")
local wbutton = require("ui.widgets.button")
local animation = require("modules.animation")

local keyboard_layout = require("modules.keyboard_layout")

local kbdcfg = keyboard_layout.kbdcfg({type = "tui", remember_layout = true})

kbdcfg.add_primary_layout("English", "US", "us")

kbdcfg.add_primary_layout("Deutsch",  "DE", "de(qwerty)")
kbdcfg.bind()

kbdcfg.widget:buttons(
  awful.util.table.join(awful.button({ }, 1, function () kbdcfg.switch_next() end))
)

awful.keyboard.append_global_keybindings({
  awful.key({"Shift", "Mod4"}, "l", function () kbdcfg.switch_next() end, { description = "switch keyboard layout", group = "WM" })
})

--- Modern Bottom Panel
--- ~~~~~~~~~~~~~~~~~~~

return function(s)
        --- Widgets
        --- ~~~~~~~~~~
        s.clock = require("ui.panels.bottom-panel.clock")(s)
        s.battery = require("ui.panels.bottom-panel.battery")()
        s.network = require("ui.panels.bottom-panel.network")()

        --- Animated tag list
        --- ~~~~~~~~~~~~~~~~~

        --- Taglist buttons
        local modkey = "Mod4"
        local taglist_buttons = gears.table.join(
                awful.button({}, 1, function(t)
                        t:view_only()
                end),
                awful.button({ modkey }, 1, function(t)
                        if client.focus then
                                client.focus:move_to_tag(t)
                        end
                end),
                awful.button({}, 3, awful.tag.viewtoggle),
                awful.button({ modkey }, 3, function(t)
                        if client.focus then
                                client.focus:toggle_tag(t)
                        end
                end),
                awful.button({}, 4, function(t)
                        awful.tag.viewnext(t.screen)
                end),
                awful.button({}, 5, function(t)
                        awful.tag.viewprev(t.screen)
                end)
        )

        local function tag_list(s)
                local taglist = awful.widget.taglist({
                        screen = s,
                        filter = awful.widget.taglist.filter.all,
                        layout = { layout = wibox.layout.fixed.horizontal },
                        widget_template = {
                                widget = wibox.container.margin,
                                forced_width = dpi(40),
                                forced_height = dpi(40),
                                create_callback = function(self, c3, _)
                                        local indicator = wibox.widget({
                                                widget = wibox.container.place,
                                                valign = "center",
                                                {
                                                        widget = wibox.container.background,
                                                        forced_height = dpi(8),
                                                        shape = gears.shape.rounded_bar,
                                                },
                                        })

                                        self.indicator_animation = animation:new({
                                                duration = 0.125,
                                                easing = animation.easing.linear,
                                                update = function(self, pos)
                                                        indicator.children[1].forced_width = pos
                                                end,
                                        })

                                        self:set_widget(indicator)

                                        if c3.selected then
                                                self.widget.children[1].bg = beautiful.accent
                                                self.indicator_animation:set(dpi(32))
                                        elseif #c3:clients() == 0 then
                                                self.widget.children[1].bg = beautiful.color8
                                                self.indicator_animation:set(dpi(8))
                                        else
                                                self.widget.children[1].bg = beautiful.accent
                                                self.indicator_animation:set(dpi(16))
                                        end

                                        --- Tag preview
                                        self:connect_signal("mouse::enter", function()
                                                if #c3:clients() > 0 then
                                                        awesome.emit_signal("bling::tag_preview::update", c3)
                                                        awesome.emit_signal("bling::tag_preview::visibility", s, true)
                                                end
                                        end)

                                        self:connect_signal("mouse::leave", function()
                                                awesome.emit_signal("bling::tag_preview::visibility", s, false)
                                        end)
                                end,
                                update_callback = function(self, c3, _)
                                        if c3.selected then
                                                self.widget.children[1].bg = beautiful.accent
                                                self.indicator_animation:set(dpi(32))
                                        elseif #c3:clients() == 0 then
                                                self.widget.children[1].bg = beautiful.color8
                                                self.indicator_animation:set(dpi(8))
                                        else
                                                self.widget.children[1].bg = beautiful.accent
                                                self.indicator_animation:set(dpi(16))
                                        end
                                end,
                        },
                        buttons = taglist_buttons,
                })

                local widget = widgets.button.elevated.state({
                        normal_bg = beautiful.widget_bg,
                        normal_shape = gears.shape.rounded_bar,
                        child = {
                                taglist,
                                margins = { left = dpi(10), right = dpi(10) },
                                widget = wibox.container.margin,
                        },
                        on_release = function()
                                awesome.emit_signal("central_panel::toggle", s)
                        end,
                })

                return wibox.widget({
                        widget,
                        margins = dpi(5),
                        widget = wibox.container.margin,
                })
        end

        --- Systray
        --- ~~~~~~~
        local function system_tray()
                local mysystray = wibox.widget.systray()
                mysystray.base_size = beautiful.systray_icon_size

                local widget = wibox.widget({
                        widget = wibox.container.constraint,
                        strategy = "max",
                        width = dpi(0),
                        {
                                widget = wibox.container.margin,
                                margins = dpi(10),
                                mysystray,
                        },
                })

                local system_tray_animation = animation:new({
                        easing = animation.easing.linear,
                        duration = 0.125,
                        update = function(self, pos)
                                widget.width = pos
                        end,
                })

                local arrow = wbutton.text.state({
                        text_normal_bg = beautiful.accent,
                        normal_bg = beautiful.wibar_bg,
                        font = beautiful.icon_font .. "Round ",
                        size = 18,
                        text = "",
                        on_turn_on = function(self)
                                system_tray_animation:set(400)
                                self:set_text("")
                        end,
                        on_turn_off = function(self)
                                system_tray_animation:set(0)
                                self:set_text("")
                        end,
                })

                return wibox.widget({
                        layout = wibox.layout.fixed.horizontal,
                        arrow,
                        widget,
                })
        end

        --- Notif panel
        --- ~~~~~~~~~~~
        local function notif_panel()
                local icon = wibox.widget({
                        markup = helpers.ui.colorize_text("", beautiful.accent),
                        align = "center",
                        valign = "center",
                        font = beautiful.icon_font .. "Round 18",
                        widget = wibox.widget.textbox,
                })

                local widget = wbutton.elevated.state({
                        child = icon,
                        normal_bg = beautiful.wibar_bg,
                        on_release = function()
                                awesome.emit_signal("notification_panel::toggle", s)
                        end,
                })

                return widget
        end

        --- Layoutbox
        --- ~~~~~~~~~
        local function layoutbox()
                local layoutbox_buttons = gears.table.join(
                        --- Left click
                        awful.button({}, 1, function(c)
                                awful.layout.inc(1)
                        end),

                        --- Right click
                        awful.button({}, 3, function(c)
                                awful.layout.inc(-1)
                        end),

                        --- Scrolling
                        awful.button({}, 4, function()
                                awful.layout.inc(-1)
                        end),
                        awful.button({}, 5, function()
                                awful.layout.inc(1)
                        end)
                )

                s.mylayoutbox = awful.widget.layoutbox()
                s.mylayoutbox:buttons(layoutbox_buttons)

                local widget = wbutton.elevated.state({
                        child = s.mylayoutbox,
                        normal_bg = beautiful.wibar_bg,
                })

                return widget
        end

        --- Create the bottom_panel
        --- ~~~~~~~~~~~~~~~~~~~~~~~
        s.bottom_panel = awful.popup({
                screen = s,
                type = "dock",
                maximum_height = beautiful.wibar_height,
                minimum_width = s.geometry.width,
                maximum_width = s.geometry.width,
                placement = function(c)
                        awful.placement.bottom(c)
                end,
                bg = beautiful.transparent,
                widget = {
                        {
                                {
                                        layout = wibox.layout.align.horizontal,
                                        expand = "none",
                                        s.clock,
                                        tag_list(s),
                                        {
                                                system_tray(),
                                                kbdcfg.widget,
                                                s.battery,
                                                s.network,
                                                notif_panel(),
                                                layoutbox(),
                                                layout = wibox.layout.fixed.horizontal,
                                        },
                                },
                                left = dpi(10),
                                right = dpi(10),
                                widget = wibox.container.margin,
                        },
                        bg = beautiful.wibar_bg,
                        widget = wibox.container.background,
                },
        })

        s.bottom_panel:struts({
                bottom = s.bottom_panel.maximum_height,
        })

        --- Remove bottom_panel on full screen
        local function remove_bottom_panel(c)
                if c.fullscreen or c.maximized then
                        c.screen.bottom_panel.visible = false
                else
                        c.screen.bottom_panel.visible = true
                end
        end

        --- Remove bottom_panel on full screen
        local function add_bottom_panel(c)
                if c.fullscreen or c.maximized then
                        c.screen.bottom_panel.visible = true
                end
        end

        --- Hide bar when a splash widget is visible
        awesome.connect_signal("widgets::splash::visibility", function(vis)
                screen.primary.bottom_panel.visible = not vis
        end)

        client.connect_signal("property::fullscreen", remove_bottom_panel)
        client.connect_signal("request::unmanage", add_bottom_panel)
end

Thanks for the code. I used the country flags instead of text. It now looks awesome.