From 225eeafcea67d63a608f9c666faf2a2ef014be4a Mon Sep 17 00:00:00 2001 From: delta Date: Mon, 19 Jan 2026 06:30:33 +0100 Subject: sync: electric boogaloo --- .config/awesome/ui/fresnel/text_input.lua | 934 ++++++++++++++++++++++++++++++ 1 file changed, 934 insertions(+) create mode 100644 .config/awesome/ui/fresnel/text_input.lua (limited to '.config/awesome/ui/fresnel/text_input.lua') diff --git a/.config/awesome/ui/fresnel/text_input.lua b/.config/awesome/ui/fresnel/text_input.lua new file mode 100644 index 0000000..2dc7368 --- /dev/null +++ b/.config/awesome/ui/fresnel/text_input.lua @@ -0,0 +1,934 @@ +------------------------------------------- +-- @author https://github.com/Kasper24 +-- @copyright 2021-2025 Kasper24 +------------------------------------------- +local lgi = require('lgi') +local Gtk = lgi.require('Gtk', '3.0') +local Gdk = lgi.require('Gdk', '3.0') +local Pango = lgi.Pango +local awful = require("awful") +local gtable = require("gears.table") +local gtimer = require("gears.timer") +local gcolor = require("gears.color") +local wibox = require("wibox") +local qcolor = require "quarrel.color" +local abs = math.abs +local ipairs = ipairs +local string = string +local capi = { + awesome = awesome, + root = root, + tag = tag, + client = client, + mouse = mouse, + mousegrabber = mousegrabber +} + +local text_input = { + mt = {} +} + +local properties = { + "unfocus_keys", + "unfocus_on_root_clicked", "unfocus_on_client_clicked", "unfocus_on_client_focus", + "unfocus_on_mouse_leave", "unfocus_on_tag_change", + "focus_on_subject_mouse_enter", "unfocus_on_subject_mouse_leave", + "click_timeout", + "reset_on_unfocus", + "text_color", + "placeholder", "initial", + "pattern", "obscure", + "cursor_blink", "cursor_blink_rate","cursor_size", "cursor_bg", + "selection_bg" +} + +text_input.patterns = { + numbers = "[%d.]*", + numbers_one_decimal = "%d*%.?%d*", + round_numbers = "[0-9]*", + email = "%S+@%S+%.%S+", + time = "%d%d?:%d%d:%d%d?|%d%d?:%d%d", + date = "%d%d%d%d%-%d%d%-%d%d|%d%d?/%d%d?/%d%d%d%d|%d%d?%.%d%d?%.%d%d%d%d", + phone = "%+?%d[%d%-%s]+%d", + url = "https?://[%w-_%.]+%.[%w]+/?[%w-_%.?=%+]*", + email = "[%w._%-%+]+@[%w._%-]+%.%w+", + alphanumeric = "%w+", + letters = "[a-zA-Z]+" +} + +local function build_properties(prototype, prop_names) + for _, prop in ipairs(prop_names) do + if not prototype["set_" .. prop] then + prototype["set_" .. prop] = function(self, value) + if self._private[prop] ~= value then + self._private[prop] = value + self:emit_signal("widget::redraw_needed") + self:emit_signal("property::" .. prop, value) + end + return self + end + end + if not prototype["get_" .. prop] then + prototype["get_" .. prop] = function(self) + return self._private[prop] + end + end + end +end + +local function has_value(tab, val) + for _, value in ipairs(tab) do + if val:lower():find(value:lower(), 1, true) then + return true + end + end + return false +end + +local function is_word_char(c) + if string.find(c, "[{[(,.:;_-+=@/ ]") then + return false + else + return true + end +end + +local function cword_start(s, pos) + local i = pos + if i > 1 then + i = i - 1 + end + while i >= 1 and not is_word_char(s:sub(i, i)) do + i = i - 1 + end + while i >= 1 and is_word_char(s:sub(i, i)) do + i = i - 1 + end + if i <= #s then + i = i + 1 + end + return i +end + +local function cword_end(s, pos) + local i = pos + while i <= #s and not is_word_char(s:sub(i, i)) do + i = i + 1 + end + while i <= #s and is_word_char(s:sub(i, i)) do + i = i + 1 + end + return i +end + +local function set_mouse_cursor(cursor) + capi.root.cursor(cursor) + local wibox = capi.mouse.current_wibox + if wibox then + wibox.cursor = cursor + end +end + +local function single_double_triple_tap(self, args) + local wp = self._private + + if wp.click_timer == nil then + wp.click_timer = gtimer { + timeout = wp.click_timeout, + autostart = false, + call_now = false, + single_shot = true, + callback = function() + wp.click_count = 0 + end + } + end + + wp.click_timer:again() + wp.click_count = wp.click_count + 1 + if wp.click_count == 1 then + args.on_single_click() + elseif wp.click_count == 2 then + args.on_double_click() + elseif wp.click_count == 3 then + args.on_triple_click() + wp.click_count = 0 + end +end + +local function run_keygrabber(self) + local wp = self._private + wp.keygrabber = awful.keygrabber.run(function(modifiers, key, event) + if event ~= "press" then + self:emit_signal("key::release", modifiers, key, event) + return + end + self:emit_signal("key::press", modifiers, key, event) + + -- Convert index array to hash table + local mod = {} + for _, v in ipairs(modifiers) do + mod[v] = true + end + + if mod.Control then + if key == "a" then + self:select_all() + elseif key == "c" then + self:copy() + elseif key == "v" then + self:paste() + elseif key == "b" or key == "Left" then + self:set_cursor_index_to_word_start() + elseif key == "f" or key == "Right" then + self:set_cursor_index_to_word_end() + elseif key == "d" then + self:delete_next_word() + elseif key == "BackSpace" then + self:delete_previous_word() + end + elseif mod.Shift and key:wlen() ~= 1 then + if key =="Left" then + self:decremeant_selection_end_index() + elseif key == "Right" then + self:increamant_selection_end_index() + end + else + if has_value(wp.unfocus_keys, key) then + self:unfocus() + end + + if mod.Shift and key == "Insert" then + self:paste() + elseif key == "Home" then + self:set_cursor_index(0) + elseif key == "End" then + self:set_cursor_index_to_end() + elseif key == "BackSpace" then + self:delete_text() + elseif key == "Delete" then + self:delete_text_after_cursor() + elseif key == "Left" then + self:decremeant_cursor_index() + elseif key == "Right" then + self:increamant_cursor_index() + elseif not mod.Mod1 and not mod.Mod4 and key:wlen() == 1 then + self:update_text(key) + end + end + end) +end + +function text_input:set_widget_template(widget_template) + local wp = self._private + + wp.text_widget = widget_template:get_children_by_id("text_role")[1] + wp.text_widget.forced_width = math.huge + local text_draw = wp.text_widget.draw + if self:get_initial() then + self:replace_text(self:get_initial()) + end + + local placeholder_widget = widget_template:get_children_by_id("placeholder_role") + if placeholder_widget then + placeholder_widget = placeholder_widget[1] + end + + function wp.text_widget:draw(context, cr, width, height) + local _, logical_rect = self._private.layout:get_pixel_extents() + + -- Selection bg + cr:set_source(gcolor.change_opacity(wp.selection_bg, wp.selection_opacity)) + cr:rectangle( + wp.selection_start_x, + logical_rect.y - 3, + wp.selection_end_x - wp.selection_start_x, + logical_rect.y + logical_rect.height + 6 + ) + cr:fill() + + -- Cursor + cr:set_source(gcolor.change_opacity(wp.cursor_bg, wp.cursor_opacity)) + cr:set_line_width(wp.cursor_width) + cr:move_to(wp.cursor_x, logical_rect.y - 3) + cr:line_to(wp.cursor_x, logical_rect.y + logical_rect.height + 6) + cr:stroke() + + cr:set_source(gcolor(wp.text_color)) + text_draw(self, context, cr, width, height) + + if self:get_text() == "" and placeholder_widget then + placeholder_widget.visible = true + elseif placeholder_widget then + placeholder_widget.visible = false + end + end + + local function on_drag(_, lx, ly) + lx, ly = wp.hierarchy:get_matrix_from_device():transform_point(lx, ly) + if abs(lx - wp.press_pos.lx) > 2 or abs(ly - wp.press_pos.ly) > 2 then + if self:get_mode() ~= "overwrite" then + self:set_selection_start_index_from_x_y(wp.press_pos.lx, wp.press_pos.ly) + end + self:set_selection_end_index_from_x_y(lx, ly) + end + end + + wp.text_widget:connect_signal("button::press", function(_, lx, ly, button, mods, find_widgets_result) + if gtable.hasitem(mods, "Mod4") or button ~= 1 then + return + end + + single_double_triple_tap(self, { + on_single_click = function() + self:focus() + self:set_cursor_index_from_x_y(lx, ly) + end, + on_double_click = function() + self:set_selection_to_word() + end, + on_triple_click = function() + self:select_all() + end + }) + + wp.press_pos = { lx = lx, ly = ly } + wp.hierarchy = find_widgets_result.hierarchy + find_widgets_result.drawable:connect_signal("mouse::move", on_drag) + end) + + wp.text_widget:connect_signal("button::release", function(_, lx, ly, button, mods, find_widgets_result) + if button == 1 then + find_widgets_result.drawable:disconnect_signal("mouse::move", on_drag) + end + end) + + wp.text_widget:connect_signal("mouse::enter", function() + set_mouse_cursor("xterm") + end) + + wp.text_widget:connect_signal("mouse::leave", function(_, find_widgets_result) + if self:get_focused() == false then + set_mouse_cursor("left_ptr") + end + + find_widgets_result.drawable:disconnect_signal("mouse::move", on_drag) + if wp.unfocus_on_mouse_leave then + self:unfocus() + end + end) + + self:set_widget(widget_template) +end + +function text_input:get_mode() + return self._private.mode +end + +function text_input:set_focused(focused) + if focused == true then + self:focus() + else + self:unfocus() + end +end + +function text_input:set_pattern(pattern) + self._private.pattern = text_input.patterns[pattern] +end + +function text_input:set_obscure(obscure) + self._private.obscure = obscure + self:set_text(self:get_text()) +end + +function text_input:toggle_obscure() + self:set_obscure(not self._private.obscure) +end + +function text_input:set_initial(initial) + self._private.initial = initial + self:replace_text(initial) +end + +function text_input:update_text(text) + if self:get_mode() == "insert" then + self:insert_text(text) + else + self:overwrite_text(text) + end +end + +function text_input:set_text(text) + self._private.text_buffer = text + + if self:get_obscure() then + self:get_text_widget():set_text(string.rep("*", #text)) + else + self:get_text_widget():set_text(text) + end +end + +function text_input:replace_text(text) + self._private.text_buffer = text + + if self:get_obscure() then + self:set_text(string.rep("*", #text)) + else + self:set_text(text) + end + + self:set_cursor_index(#text) +end + +function text_input:insert_text(text) + local wp = self._private + + local old_text = self:get_text() + local cursor_index = self:get_cursor_index() + local left_text = old_text:sub(1, cursor_index) .. text + local right_text = old_text:sub(cursor_index + 1) + local new_text = left_text .. right_text + if wp.pattern then + new_text = new_text:match(wp.pattern) + if new_text then + self:set_text(new_text) + self:set_cursor_index(self:get_cursor_index() + #text) + self:emit_signal("property::text", self:get_text()) + end + else + self:set_text(new_text) + self:set_cursor_index(self:get_cursor_index() + #text) + self:emit_signal("property::text", self:get_text()) + end +end + +function text_input:overwrite_text(text) + local wp = self._private + + local start_pos = wp.selection_start + local end_pos = wp.selection_end + if start_pos > end_pos then + start_pos, end_pos = end_pos, start_pos + end + + local old_text = self:get_text() + local left_text = old_text:sub(1, start_pos) + local right_text = old_text:sub(end_pos + 1) + local new_text = left_text .. text .. right_text + + if wp.pattern then + new_text = new_text:match(wp.pattern) + if new_text then + self:set_text(new_text) + self:set_cursor_index(#left_text + 1) + self:emit_signal("property::text", self:get_text()) + end + else + self:set_text(new_text) + self:set_cursor_index(#left_text + 1) + self:emit_signal("property::text", self:get_text()) + end +end + +function text_input:copy() + local wp = self._private + if self:get_mode() == "overwrite" then + local text = self:get_text() + local start_pos = self._private.selection_start + local end_pos = self._private.selection_end + if start_pos > end_pos then + start_pos, end_pos = end_pos + 1, start_pos + end + text = text:sub(start_pos, end_pos) + wp.clipboard:set_text(text, -1) + end +end + +function text_input:paste() + local wp = self._private + + wp.clipboard:request_text(function(clipboard, text) + if text then + self:update_text(text) + end + end) +end + +function text_input:delete_next_word() + local old_text = self:get_text() + local cursor_index = self:get_cursor_index() + + local left_text = old_text:sub(1, cursor_index) + local right_text = old_text:sub(cword_end(old_text, cursor_index + 1)) + self:set_text(left_text .. right_text) + self:emit_signal("property::text", self:get_text()) +end + +function text_input:delete_previous_word() + local old_text = self:get_text() + local cursor_index = self:get_cursor_index() + local wstart = cword_start(old_text, cursor_index + 1) - 1 + local left_text = old_text:sub(1, wstart) + local right_text = old_text:sub(cursor_index + 1) + self:set_text(left_text .. right_text) + self:set_cursor_index(wstart) + self:emit_signal("property::text", self:get_text()) +end + +function text_input:delete_text() + if self:get_mode() == "insert" then + self:delete_text_before_cursor() + else + self:overwrite_text("") + end +end + +function text_input:delete_text_before_cursor() + local cursor_index = self:get_cursor_index() + if cursor_index > 0 then + local old_text = self:get_text() + local left_text = old_text:sub(1, cursor_index - 1) + local right_text = old_text:sub(cursor_index + 1) + self:set_text(left_text .. right_text) + self:set_cursor_index(cursor_index - 1) + self:emit_signal("property::text", self:get_text()) + end +end + +function text_input:delete_text_after_cursor() + local cursor_index = self:get_cursor_index() + if cursor_index < #self:get_text() then + local old_text = self:get_text() + local left_text = old_text:sub(1, cursor_index) + local right_text = old_text:sub(cursor_index + 2) + self:set_text(left_text .. right_text) + self:emit_signal("property::text", self:get_text()) + end +end + +function text_input:get_text() + return self._private.text_buffer or "" +end + +function text_input:get_text_widget() + return self._private.text_widget +end + +function text_input:show_selection() + self._private.selection_opacity = 1 + self:get_text_widget():emit_signal("widget::redraw_needed") +end + +function text_input:hide_selection() + self._private.selection_opacity = 0 + self:get_text_widget():emit_signal("widget::redraw_needed") +end + +function text_input:select_all() + if self:get_text() == "" then + return + end + + self:set_selection_start_index(0) + self:set_selection_end_index(#self:get_text()) +end + +function text_input:set_selection_to_word() + if self:get_text() == "" then + return + end + + local word_start_index = cword_start(self:get_text(), self:get_cursor_index() + 1) - 1 + local word_end_index = cword_end(self:get_text(), self:get_cursor_index() + 1) - 1 + + self:set_selection_start_index(word_start_index) + self:set_selection_end_index(word_end_index) +end + +function text_input:set_selection_start_index(index) + if #self:get_text() == 0 then + return + end + + index = math.max(math.min(index, #self:get_text()), 0) + + local layout = self:get_text_widget()._private.layout + local strong_pos, weak_pos = layout:get_caret_pos(index) + if strong_pos then + self._private.selection_start = index + self._private.selection_start_x = strong_pos.x / Pango.SCALE + self._private.selection_start_y = strong_pos.y / Pango.SCALE + self:get_text_widget():emit_signal("widget::redraw_needed") + end +end + +function text_input:set_selection_end_index(index) + if #self:get_text() == 0 then + return + end + + index = math.max(math.min(index, #self:get_text()), 0) + + local layout = self:get_text_widget()._private.layout + local strong_pos, weak_pos = layout:get_caret_pos(index) + if strong_pos then + if self:get_mode() ~= "overwrite" and index ~= self._private.selection_start then + self._private.mode = "overwrite" + self:show_selection() + self:hide_cursor() + end + + self._private.selection_end = index + self._private.selection_end_x = strong_pos.x / Pango.SCALE + self._private.selection_end_y = strong_pos.y / Pango.SCALE + self:get_text_widget():emit_signal("widget::redraw_needed") + end +end + +function text_input:increamant_selection_end_index() + if self:get_mode() == "insert" then + self:set_selection_start_index(self:get_cursor_index()) + self:set_selection_end_index(self:get_cursor_index() + 1) + else + self:set_selection_end_index(self._private.selection_end + 1) + end +end + +function text_input:decremeant_selection_end_index() + if self:get_mode() == "insert" then + self:set_selection_start_index(self:get_cursor_index()) + self:set_selection_end_index(self:get_cursor_index() - 1) + else + self:set_selection_end_index(self._private.selection_end - 1) + end +end + +function text_input:set_selection_start_index_from_x_y(x, y) + local layout = self:get_text_widget()._private.layout + local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE) + if index then + self:set_selection_start_index(index) + else + local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents() + if x < logical_rect.x + logical_rect.width then + self:set_selection_start_index(0) + else + self:set_selection_start_index(#self:get_text()) + end + end +end + +function text_input:set_selection_end_index_from_x_y(x, y) + local layout = self:get_text_widget()._private.layout + local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE) + if index then + self:set_selection_end_index(index + trailing) + else + local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents() + if x < logical_rect.x + logical_rect.width then + self:set_selection_end_index(0) + else + self:set_selection_end_index(#self:get_text()) + end + end +end + +function text_input:show_cursor() + self._private.cursor_opacity = 1 + self:get_text_widget():emit_signal("widget::redraw_needed") +end + +function text_input:hide_cursor() + self._private.cursor_opacity = 0 + self:get_text_widget():emit_signal("widget::redraw_needed") +end + +function text_input:set_cursor_index(index) + index = math.max(math.min(index, #self:get_text()), 0) + + local layout = self:get_text_widget()._private.layout + local strong_pos, weak_pos = layout:get_cursor_pos(index) + if strong_pos then + if strong_pos == self._private.cursor_index and self._private.mode == "insert" then + return + end + + if self:get_focused() and self:get_mode() ~= "insert" then + self:show_cursor() + end + + self._private.cursor_index = index + self._private.mode = "insert" + + self._private.cursor_x = strong_pos.x / Pango.SCALE + self._private.cursor_y = strong_pos.y / Pango.SCALE + + self:hide_selection() + + self:get_text_widget():emit_signal("widget::redraw_needed") + end +end + +function text_input:set_cursor_index_from_x_y(x, y) + local layout = self:get_text_widget()._private.layout + local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE) + + if index then + self:set_cursor_index(index) + else + local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents() + if x < logical_rect.x + logical_rect.width then + self:set_cursor_index(0) + else + self:set_cursor_index(#self:get_text()) + end + end +end + +function text_input:set_cursor_index_to_word_start() + self:set_cursor_index(cword_start(self:get_text(), self:get_cursor_index() + 1) - 1) +end + +function text_input:set_cursor_index_to_word_end() + self:set_cursor_index(cword_end(self:get_text(), self:get_cursor_index() + 1) - 1) +end + +function text_input:set_cursor_index_to_end() + self:set_cursor_index(#self:get_text()) +end + +function text_input:increamant_cursor_index() + if self:get_mode() == "insert" then + self:set_cursor_index(self:get_cursor_index() + 1) + else + local start_pos = self._private.selection_start + local end_pos = self._private.selection_end + if start_pos > end_pos then + start_pos, end_pos = end_pos, start_pos + end + self:set_cursor_index(end_pos) + end +end + +function text_input:decremeant_cursor_index() + if self:get_mode() == "insert" then + self:set_cursor_index(self:get_cursor_index() - 1) + else + local start_pos = self._private.selection_start + local end_pos = self._private.selection_end + if start_pos > end_pos then + start_pos, end_pos = end_pos, start_pos + end + self:set_cursor_index(start_pos) + end +end + +function text_input:get_cursor_index() + return self._private.cursor_index +end + +function text_input:set_focus_on_subject_mouse_enter(subject) + subject:connect_signal("mouse::enter", function() + self:focus() + end) +end + +function text_input:set_unfocus_on_subject_mouse_leave(subject) + subject:connect_signal("mouse::leave", function() + self:unfocus() + end) +end + +function text_input:get_focused() + return self._private.focused +end + +function text_input:focus() + local wp = self._private + + if self:get_focused() == true then + return + end + + -- Do it first, so the cursor won't change back when unfocus was called on the focused text input + capi.awesome.emit_signal("text_input::focus", self) + + set_mouse_cursor("xterm") + + if self:get_mode() == "insert" then + self:show_cursor() + end + + run_keygrabber(self) + + if wp.cursor_blink then + if wp.cursor_blink_timer == nil then + wp.cursor_blink_timer = gtimer { + timeout = wp.cursor_blink_rate, + autostart = false, + call_now = false, + single_shot = false, + callback = function() + if self._private.cursor_opacity == 1 then + self:hide_cursor() + elseif self:get_mode() == "insert" then + self:show_cursor() + end + end + } + end + wp.cursor_blink_timer:start() + end + + + wp.focused = true + self:emit_signal("focus") +end + +function text_input:unfocus(context) + local wp = self._private + if self:get_focused() == false then + return + end + + set_mouse_cursor("left_ptr") + self:hide_cursor() + wp.cursor_blink_timer:stop() + self:hide_selection() + if self.reset_on_unfocus == true then + self:replace_text("") + end + + awful.keygrabber.stop(wp.keygrabber) + wp.focused = false + self:emit_signal("unfocus", context or "normal", self:get_text()) +end + +function text_input:toggle() + local wp = self._private + + if self:get_focused() == false then + self:focus() + else + self:unfocus() + end +end + +local function new() + local widget = wibox.container.background() + gtable.crush(widget, text_input, true) + + local wp = widget._private + + wp.focused = false + wp.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) + wp.cursor_index = 0 + wp.mode = "insert" + wp.click_count = 0 + + wp.cursor_x = 0 + wp.cursor_y = 0 + wp.cursor_opacity = 0 + wp.selection_start_x = 0 + wp.selection_end_x = 0 + wp.selection_start_y = 0 + wp.selection_end_y = 0 + wp.selection_opacity = 0 + + wp.click_timeout = 0.2 + + wp.unfocus_keys = { "Escape", "Return" } + wp.unfocus_on_root_clicked = true + wp.unfocus_on_client_clicked = true + wp.unfocus_on_mouse_leave = false + wp.unfocus_on_tag_change = true + wp.unfocus_on_other_text_input_focus = true + wp.unfocus_on_client_focus = true + + wp.focus_on_subject_mouse_enter = nil + wp.unfocus_on_subject_mouse_leave = nil + + wp.reset_on_unfocus = false + + wp.pattern = nil + wp.obscure = false + + wp.placeholder = "" + wp.text_color = qcolor.palette.fg() + wp.text = "" + + wp.cursor_width = 2 + wp.cursor_bg = qcolor.palette.fg() + wp.cursor_blink = true + wp.cursor_blink_rate = 0.6 + + wp.selection_bg = qcolor.palette.bg.high + + widget:set_widget_template(wibox.widget { + layout = wibox.layout.stack, + { + widget = wibox.widget.textbox, + id = "placeholder_role", + text = wp.placeholder + }, + { + widget = wibox.widget.textbox, + id = "text_role", + text = wp.text + } + }) + + capi.tag.connect_signal("property::selected", function() + if wp.unfocus_on_tag_change then + widget:unfocus() + end + end) + + capi.awesome.connect_signal("text_input::focus", function(text_input) + if wp.unfocus_on_other_text_input_focus and text_input ~= widget then + widget:unfocus() + end + end) + + capi.client.connect_signal("focus", function() + if wp.unfocus_on_client_focus then + widget:unfocus() + end + end) + + awful.mouse.append_global_mousebindings({ + awful.button({"Any"}, 1, function() + if wp.unfocus_on_root_clicked then + widget:unfocus() + end + end), + awful.button({"Any"}, 3, function() + if wp.unfocus_on_root_clicked then + widget:unfocus() + end + end) + }) + + capi.client.connect_signal("button::press", function() + if wp.unfocus_on_client_clicked then + widget:unfocus() + end + end) + + capi.awesome.connect_signal("colorscheme::changed", function(old_colorscheme_to_new_map) + wp.text_color = old_colorscheme_to_new_map[wp.text_color] + wp.cursor_bg = old_colorscheme_to_new_map[wp.cursor_bg] + wp.selection_bg = old_colorscheme_to_new_map[wp.selection_bg] + end) + + return widget +end + +function text_input.mt:__call(...) + return new() +end + +build_properties(text_input, properties) + +return setmetatable(text_input, text_input.mt) -- cgit v1.2.3