From c6341f84e74359286250e8226136aa5fc8ef1464 Mon Sep 17 00:00:00 2001 From: Rene Kievits Date: Tue, 22 Nov 2022 16:59:55 +0100 Subject: [PATCH] desktop, calendar, various other modules --- awesome/awful/widget/inputbox.lua | 522 +++++++++++++ awesome/rc.lua | 8 +- awesome/src/assets/icons/bluetooth/power.svg | 1 + .../src/assets/icons/bluetooth/refresh.svg | 1 + awesome/src/assets/icons/calendar/alarm.svg | 1 + .../src/assets/icons/calendar/location.svg | 1 + .../src/assets/icons/desktop/application.svg | 1 + awesome/src/assets/icons/desktop/copy.svg | 1 + awesome/src/assets/icons/desktop/cut.svg | 1 + awesome/src/assets/icons/desktop/delete.svg | 1 + .../assets/icons/desktop/dots-vertical.svg | 1 + awesome/src/assets/icons/desktop/edit.svg | 1 + .../assets/icons/desktop/energy_settings.svg | 1 + awesome/src/assets/icons/desktop/file.svg | 1 + awesome/src/assets/icons/desktop/file_add.svg | 1 + .../src/assets/icons/desktop/file_manager.svg | 1 + awesome/src/assets/icons/desktop/folder.svg | 1 + .../src/assets/icons/desktop/gtk_settings.svg | 1 + awesome/src/assets/icons/desktop/launch.svg | 1 + .../src/assets/icons/desktop/music_player.svg | 3 + awesome/src/assets/icons/desktop/power.svg | 1 + awesome/src/assets/icons/desktop/quit.svg | 1 + awesome/src/assets/icons/desktop/refresh.svg | 1 + .../assets/icons/desktop/screen_settings.svg | 1 + awesome/src/assets/icons/desktop/search.svg | 1 + awesome/src/assets/icons/desktop/terminal.svg | 1 + .../src/assets/icons/desktop/text_editor.svg | 1 + .../src/assets/icons/desktop/web_browser.svg | 1 + .../src/assets/icons/network/airplane-off.svg | 1 + .../src/assets/icons/network/airplane-on.svg | 1 + awesome/src/assets/icons/network/link.svg | 1 + .../src/assets/icons/network/menu-down.svg | 1 + awesome/src/assets/icons/network/menu-up.svg | 1 + .../assets/icons/network/wifi-strength-5.svg | 1 + awesome/src/core/notifications.lua | 4 - awesome/src/core/signals.lua | 7 + awesome/src/modules/__test.lua | 60 ++ .../application_launcher/application.lua | 596 ++++++++------- .../src/modules/application_launcher/init.lua | 152 +++- .../src/modules/audio/volume_controller.lua | 553 ++++++++++++++ awesome/src/modules/audio/volume_osd.lua | 153 ++++ awesome/src/modules/bluetooth/device.lua | 2 +- awesome/src/modules/bluetooth/init.lua | 115 ++- .../src/modules/brightness/brightness_osd.lua | 133 ++++ awesome/src/modules/calendar/init.lua | 590 +++++++-------- awesome/src/modules/calendar/task_info.lua | 73 +- awesome/src/modules/context_menu/init.lua | 214 ++++++ awesome/src/modules/crylia_bar/center_bar.lua | 99 +-- awesome/src/modules/crylia_bar/dock.lua | 49 +- awesome/src/modules/crylia_bar/init.lua | 6 +- awesome/src/modules/crylia_bar/left_bar.lua | 41 +- awesome/src/modules/crylia_bar/right_bar.lua | 37 +- awesome/src/modules/crylia_wibox/init.lua | 129 ++++ awesome/src/modules/desktop/context_menu.lua | 54 ++ awesome/src/modules/desktop/desktop.lua | 605 +++++++++++++++ awesome/src/modules/desktop/element.lua | 119 +++ awesome/src/modules/init.lua | 18 +- .../network_controller/access_point.lua | 168 +++++ .../modules/network_controller/ap_form.lua | 262 +++++++ .../src/modules/network_controller/init.lua | 703 ++++++++++++++++-- .../notification-center/notification_list.lua | 2 +- awesome/src/modules/powermenu/powermenu.lua | 249 +++++++ awesome/src/modules/titlebar/titlebar.lua | 447 +++++++++++ awesome/src/theme/theme_config.lua | 167 +++-- awesome/src/theme/user_config.lua | 36 +- awesome/src/tools/dbus/bluetooth_dbus.lua | 7 + awesome/src/tools/helpers/audio.lua | 25 +- awesome/src/tools/helpers/gpu_temp.lua | 1 + awesome/src/tools/helpers/gpu_usage.lua | 1 + awesome/src/tools/ical_parser.lua | 75 +- awesome/src/widgets/date.lua | 21 +- awesome/src/widgets/gpu_info.lua | 1 + awesome/src/widgets/network.lua | 24 +- awesome/src/widgets/taglist.lua | 10 - 74 files changed, 5587 insertions(+), 985 deletions(-) create mode 100644 awesome/awful/widget/inputbox.lua create mode 100644 awesome/src/assets/icons/bluetooth/power.svg create mode 100644 awesome/src/assets/icons/bluetooth/refresh.svg create mode 100644 awesome/src/assets/icons/calendar/alarm.svg create mode 100644 awesome/src/assets/icons/calendar/location.svg create mode 100644 awesome/src/assets/icons/desktop/application.svg create mode 100644 awesome/src/assets/icons/desktop/copy.svg create mode 100644 awesome/src/assets/icons/desktop/cut.svg create mode 100644 awesome/src/assets/icons/desktop/delete.svg create mode 100644 awesome/src/assets/icons/desktop/dots-vertical.svg create mode 100644 awesome/src/assets/icons/desktop/edit.svg create mode 100644 awesome/src/assets/icons/desktop/energy_settings.svg create mode 100644 awesome/src/assets/icons/desktop/file.svg create mode 100644 awesome/src/assets/icons/desktop/file_add.svg create mode 100644 awesome/src/assets/icons/desktop/file_manager.svg create mode 100644 awesome/src/assets/icons/desktop/folder.svg create mode 100644 awesome/src/assets/icons/desktop/gtk_settings.svg create mode 100644 awesome/src/assets/icons/desktop/launch.svg create mode 100644 awesome/src/assets/icons/desktop/music_player.svg create mode 100644 awesome/src/assets/icons/desktop/power.svg create mode 100644 awesome/src/assets/icons/desktop/quit.svg create mode 100644 awesome/src/assets/icons/desktop/refresh.svg create mode 100644 awesome/src/assets/icons/desktop/screen_settings.svg create mode 100644 awesome/src/assets/icons/desktop/search.svg create mode 100644 awesome/src/assets/icons/desktop/terminal.svg create mode 100644 awesome/src/assets/icons/desktop/text_editor.svg create mode 100644 awesome/src/assets/icons/desktop/web_browser.svg create mode 100644 awesome/src/assets/icons/network/airplane-off.svg create mode 100644 awesome/src/assets/icons/network/airplane-on.svg create mode 100644 awesome/src/assets/icons/network/link.svg create mode 100644 awesome/src/assets/icons/network/menu-down.svg create mode 100644 awesome/src/assets/icons/network/menu-up.svg create mode 100644 awesome/src/assets/icons/network/wifi-strength-5.svg create mode 100644 awesome/src/modules/__test.lua create mode 100644 awesome/src/modules/audio/volume_controller.lua create mode 100644 awesome/src/modules/audio/volume_osd.lua create mode 100644 awesome/src/modules/brightness/brightness_osd.lua create mode 100644 awesome/src/modules/context_menu/init.lua create mode 100644 awesome/src/modules/crylia_wibox/init.lua create mode 100644 awesome/src/modules/desktop/context_menu.lua create mode 100644 awesome/src/modules/desktop/desktop.lua create mode 100644 awesome/src/modules/desktop/element.lua create mode 100644 awesome/src/modules/network_controller/access_point.lua create mode 100644 awesome/src/modules/network_controller/ap_form.lua create mode 100644 awesome/src/modules/powermenu/powermenu.lua create mode 100644 awesome/src/modules/titlebar/titlebar.lua diff --git a/awesome/awful/widget/inputbox.lua b/awesome/awful/widget/inputbox.lua new file mode 100644 index 0000000..ba59ce3 --- /dev/null +++ b/awesome/awful/widget/inputbox.lua @@ -0,0 +1,522 @@ +--------------------------------------------------------------------------- +-- This widget can be used to type text and get the text from it. +--@DOC_wibox_widget_defaults_inputbox_EXAMPLE@ +-- +-- @author Rene Kievits +-- @copyright 2022, Rene Kievits +-- @module awful.widget.inputbox +--------------------------------------------------------------------------- + +local setmetatable = setmetatable +local abutton = require("awful.button") +local beautiful = require("beautiful") +local gtable = require("gears.table") +local base = require("wibox.widget.base") +local gstring = require("gears.string") +local keygrabber = require("awful.keygrabber") +local wtemplate = require("wibox.template") + +local capi = +{ + selection = selection, + mousegrabber = mousegrabber, + mouse = mouse, +} + +local inputbox = { mt = {} } + +--- Formats the text with a cursor and highlights if set. +local function text_with_cursor(text, cursor_pos, self) + local char, spacer, text_start, text_end + + local cursor_fg = beautiful.inputbox_cursor_fg or "#313131" + local cursor_bg = beautiful.inputbox_cursor_bg or "#0dccfc" + local text_color = beautiful.inputbox_fg or "#ffffff" + local placeholder_text = beautiful.inputbox_placeholder_text or "Type here..." + local placeholder_fg = beautiful.inputbox_placeholder_fg or "#777777" + local highlight_bg = beautiful.inputbox_highlight_bg or "#35ffe4" + local highlight_fg = beautiful.inputbox_highlight_fg or "#000000" + + if text == "" then + return "" .. placeholder_text .. "" + end + + if #text < cursor_pos then + char = " " + spacer = "" + text_start = gstring.xml_escape(text) + text_end = "" + else + local offset = 0 + if #text:sub(cursor_pos, cursor_pos) == -1 then + offset = 1 + end + char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset)) + spacer = " " + text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1)) + text_end = gstring.xml_escape(text:sub(cursor_pos + offset + 1)) + end + + if self._private.highlight and self._private.highlight.cur_pos_start and self._private.highlight.cur_pos_end then + -- split the text into 3 parts based on the highlight and cursor position + local text_start_highlight = gstring.xml_escape(text:sub(1, self._private.highlight.cur_pos_start - 1)) + local text_highlighted = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_start, + self._private.highlight.cur_pos_end)) + local text_end_highlight = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_end + 1)) + + return "" .. text_start_highlight .. "" .. + "" .. + text_highlighted .. + "" .. "" .. text_end_highlight .. "" + else + return "" .. text_start .. "" .. + "" .. + char .. "" .. "" .. text_end .. spacer .. "" + end +end + +function inputbox:layout(_, width, height) + if self._private.widget then + return { base.place_widget_at(self._private.widget, 0, 0, width, height) } + end +end + +function inputbox:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +inputbox.set_widget = base.set_widget_common + +function inputbox:set_widget_template(widget_template) + self._private.widget_template = widget_template + self:set_widget(widget_template) +end + +function inputbox:get_widget() + return self._private.widget +end + +function inputbox:get_children() + return { self._private.widget } +end + +function inputbox:set_children(children) + self:set_widget(children[1]) +end + +function inputbox:reset() + self._private.widget_template = nil + self:set_widget(nil) +end + +--- The inputbox border color +-- +-- @DOC_awful_widget_inputbox_border_color_EXAMPLE@ +-- +-- @property border_color +-- @tparam[opt=gears.color] string border_color +-- @see gears.color +-- @propemits true false +-- @propbeautiful +function inputbox:set_border_color(v) + self._private.border_color = v + self:emit_signal("property::border_color", v) +end + +--- The inputbox border width +-- +-- @DOC_awful_widget_inputbox_border_width_EXAMPLE@ +-- +-- @property border_width +-- @tparam[opt=0] number|nil border_width +-- @negativeallowed false +-- @propertyunit pixel +-- @propemits true false +-- @propbeautiful +function inputbox:set_border_width(v) + self._private.border_width = v + self:emit_signal("property::border_width", v) +end + +--- The inputbox background color +-- +-- @DOC_awful_widget_inputbox_bg_EXAMPLE@ +-- +-- @property bg +-- @tparam[opt=gears.color] string foreground +-- @see gears.color +-- @propemits true false +-- @propbeautiful +function inputbox:set_bg(v) + self._private.bg = v + self:emit_signal("property::bg", v) +end + +--- The text foreground color +-- +-- @DOC_awful_widget_inputbox_fg_EXAMPLE@ +-- +-- @property string +-- @tparam[opt=gears.color] string foreground +-- @see gears.color +-- @propemits true false +-- @propbeautiful +function inputbox:set_fg(v) + self._private.fg = v + self:emit_signal("property::fg", v) +end + +--- The shape of the inputbox +-- +-- @DOC_awful_widget_inputbox_shape_EXAMPLE@ +-- +-- @property shape +-- @tparam[opt=gears.shape.rectangle] shape|nil shape +-- @see gears.shape +-- @propemits true false +-- @propbeautiful +function inputbox:set_shape(v) + self._private.shape = v + self:emit_signal("property::shape", v) +end + +--- Clears the current text +function inputbox:clear() + self:set_text("") +end + +function inputbox:get_text() + return self._private.text or "" +end + +function inputbox:set_text(text) + self._private.text = text + self:emit_signal("property::text", text) +end + +--- Stop the keygrabber and mousegrabber +function inputbox:stop() + self:emit_signal("stopped") + keygrabber.stop() + capi.mousegrabber.stop() +end + +function inputbox:focus() + keygrabber.stop() + if not keygrabber.is_running then + self:run() + end + + -- Stops the mousegrabber when not clicked on the widget + --[[ capi.mousegrabber.run( + function(m) + if m.buttons[1] then + if capi.mouse.current_wibox ~= self:get_widget().widget then + self:emit_signal("keygrabber::stop", "") + return false + end + end + return true + end, "left_ptr" + ) ]] + + self:connect_signal("button::press", function() + if capi.mouse.current_widget ~= self then + self:emit_signal("keygrabber::stop", "") + end + end) +end + +--[[ local function widget_update(text, cursor_pos, widget) + text = text or "" + cursor_pos = cursor_pos or 1 + widget:set_text(text) + widget:emit_signal("property::markup", text) +end ]] + +--- Init the inputbox and start the keygrabber +function inputbox:run() + + if not self._private.text then self._private.text = "" end + + -- Init the cursor position, but causes on refocus the cursor to move to the left + local cursor_pos = #self:get_text() + 1 + + self:emit_signal("started") + + -- Init and reset(when refocused) the highlight + self._private.highlight = {} + + -- Emitted when the keygrabber is stopped + self:connect_signal("cancel", function() + self:stop() + self:emit_signal("stopped") + end) + + -- Emitted when the keygrabber should submit the text + self:connect_signal("submit", function(text) + self:stop() + self:emit_signal("stopped", text) + end) + + self:emit_signal("key_pressed", "B", "A") + + + keygrabber.run(function(mod, key, event) + local mod_keys = {} + for _, v in ipairs(mod) do + mod_keys[v] = true + end + + if not (event == "press") then return end + --Escape cases + -- Just quit and leave the text as is + if (not mod_keys.Control) and (key == "Escape") then + self:emit_signal("cancel") + elseif (not mod_keys.Control and key == "KP_Enter") or (not mod_keys.Control and key == "Return") then + self:emit_signal("submit", self:get_text()) + self:set_text("") + end + + -- All shift, control or key cases + if mod_keys.Shift then + if key == "Left" then + if cursor_pos > 1 then + if not self._private.highlight.cur_pos_start then + self._private.highlight.cur_pos_start = cursor_pos - 1 + end + if not self._private.highlight.cur_pos_end then + self._private.highlight.cur_pos_end = cursor_pos + end + + if self._private.highlight.cur_pos_start < cursor_pos then + self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end - 1 + else + self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start - 1 + end + + cursor_pos = cursor_pos - 1 + end + elseif key == "Right" then + if #self._private.text >= cursor_pos then + if not self._private.highlight.cur_pos_end then + self._private.highlight.cur_pos_end = cursor_pos - 1 + end + if not self._private.highlight.cur_pos_start then + self._private.highlight.cur_pos_start = cursor_pos + end + + if self._private.highlight.cur_pos_end <= cursor_pos then + self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end + 1 + else + self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start + 1 + end + cursor_pos = cursor_pos + 1 + if cursor_pos > #self._private.text + 1 then + self._private.highlight = {} + end + end + else + if key:wlen() == 1 then + self:set_text(self._private.text:sub(1, cursor_pos - 1) .. + string.upper(key) .. self._private.text:sub(cursor_pos)) + cursor_pos = cursor_pos + 1 + end + end + elseif mod_keys.Control then + if key == "a" then + -- Mark the entire text + self._private.highlight = { + cur_pos_start = 1, + cur_pos_end = #self._private.text + } + elseif key == "c" then + -- TODO: Copy the highlighted text when the selection setter gets implemented + elseif key == "v" then + local sel = capi.selection() + if sel then + sel = sel:gsub("\n", "") + if self._private.highlight and self._private.highlight.cur_pos_start and + self._private.highlight.cur_pos_end then + -- insert the text into the selected part + local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1) + local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1) + self:set_text(text_start .. sel .. text_end) + self._private.highlight = {} + cursor_pos = #text_start + #sel + 1 + else + self:set_text(self._private.text:sub(1, cursor_pos - 1) .. + sel .. self._private.text:sub(cursor_pos)) + cursor_pos = cursor_pos + #sel + end + end + elseif key == "x" then + --TODO: "cut". Copy selected then clear text, this requires to add the c function first. + self._private.highlight = {} + elseif key == "Left" then + -- Find all spaces + local spaces = {} + local t, i = self._private.text, 0 + + while t:find("%s") do + i = t:find("%s") + table.insert(spaces, i) + t = t:sub(1, i - 1) .. "-" .. t:sub(i + 1) + end + + local cp = 1 + for _, v in ipairs(spaces) do + if (v < cursor_pos) then + cp = v + end + end + cursor_pos = cp + elseif key == "Right" then + local next_space = self._private.text:sub(cursor_pos):find("%s") + if next_space then + cursor_pos = cursor_pos + next_space + else + cursor_pos = #self._private.text + 1 + end + end + else + if key == "BackSpace" then + -- If text is highlighted delete that, else just delete the character to the left + if self._private.highlight and self._private.highlight.cur_pos_start and + self._private.highlight.cur_pos_end then + local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1) + local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1) + self:set_text(text_start .. text_end) + self._private.highlight = {} + cursor_pos = #text_start + 1 + else + if cursor_pos > 1 then + self:set_text(self._private.text:sub(1, cursor_pos - 2) .. + self._private.text:sub(cursor_pos)) + cursor_pos = cursor_pos - 1 + end + end + elseif key == "Delete" then + -- If text is highlighted delete that, else just delete the character to the right + if self._private.highlight and self._private.highlight.cur_pos_start and + self._private.highlight.cur_pos_end then + local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1) + local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1) + self:set_text(text_start .. text_end) + self._private.highlight = {} + cursor_pos = #text_start + 1 + else + if cursor_pos <= #self._private.text then + self:set_text(self._private.text:sub(1, cursor_pos - 1) .. + self._private.text:sub(cursor_pos + 1)) + end + end + elseif key == "Left" then + -- Move cursor ro the left + if cursor_pos > 1 then + cursor_pos = cursor_pos - 1 + end + self._private.highlight = {} + elseif key == "Right" then + -- Move cursor to the right + if cursor_pos <= #self._private.text then + cursor_pos = cursor_pos + 1 + end + self._private.highlight = {} + else + -- Print every alphanumeric key + -- It seems like gears.xmlescape doesn't support non alphanumeric characters + if key:wlen() == 1 then + self:set_text(self._private.text:sub(1, cursor_pos - 1) .. + key .. self._private.text:sub(cursor_pos)) + cursor_pos = cursor_pos + 1 + end + end + + -- Make sure the cursor cannot go out of bounds + if cursor_pos < 1 then + cursor_pos = 1 + elseif cursor_pos > #self._private.text + 1 then + cursor_pos = #self._private.text + 1 + end + end + -- Update cycle + self:get_widget():update { + text = text_with_cursor(self:get_text(), cursor_pos, self) + } + -- using self:emit_signal... results in nil tables beeing send + awesome.emit_signal("inputbox::key_pressed", mod_keys, key) + end) +end + +--- Creates a new inputbox widget +-- @tparam table args Arguments for the inputbox widget +-- @tparam string args.text The text to display in the inputbox +-- @tparam[opt=beautiful.fg_normal] string args.fg Text foreground color +-- @tparam[opt=beautiful.border_focus] string args.border_focus_color Border color when focused +-- @tparam[opt=""] string args.placeholder_text placeholder text to be shown when not focused and +-- @tparam[opt=beautiful.inputbox_placeholder_fg] string args.placeholder_fg placeholder text foreground color +-- @tparam[opt=beautiful.inputbox_cursor_bg] string args.cursor_bg Cursor background color +-- @tparam[opt=beautiful.inputbox_cursor_fg] string args.cursor_fg Cursor foreground color +-- @tparam[opt=beautiful.inputbox_highlight_bg] string args.highlight_bg Highlight background color +-- @tparam[opt=beautiful.inputbox_highlight_fg] string args.highlight_fg Highlight foreground color +-- @treturn awful.widget.inputbox The inputbox widget. +-- @constructorfct awful.widget.inputbox +function inputbox.new(args) + + local w = base.make_widget(nil, nil, { enable_properties = true }) + + gtable.crush(w, inputbox, true) + + w:set_widget(wtemplate.make_from_value(args.widget_template)) + + w:buttons( + gtable.join { + abutton({}, 1, function() + w:focus() + end), + abutton({}, 3, function() + -- TODO: Figure out how to paste with highlighted support + -- Maybe with a signal? + end) + } + ) + + -- Change the cursor to "xterm" on hover over + local old_cursor, old_wibox + w:connect_signal( + "mouse::enter", + function() + local wid = capi.mouse.current_wibox + if wid then + old_cursor, old_wibox = wid.cursor, wid + wid.cursor = "xterm" + end + end + ) + + -- Change the cursor back once leaving the widget + w:connect_signal( + "mouse::leave", + function() + old_wibox.cursor = old_cursor + old_wibox = nil + end + ) + + -- Initialize the text and placeholder with a first update + w:get_widget():update { + text = text_with_cursor("", 1, w) + } + return w +end + +function inputbox.mt:__call(...) + return inputbox.new(...) +end + +return setmetatable(inputbox, inputbox.mt) diff --git a/awesome/rc.lua b/awesome/rc.lua index bbc303e..bcb5c0c 100644 --- a/awesome/rc.lua +++ b/awesome/rc.lua @@ -14,8 +14,12 @@ mouse = mouse mousegrabber = mousegrabber root = root screen = screen +selection = selection tag = tag +-- Do not touch as this is used to share some variables between files +Global_config = {} + require("src.theme.user_config") require("src.theme.theme_config") @@ -30,5 +34,5 @@ require("src.bindings.global_buttons") require("src.bindings.bind_to_tags") require("src.modules.init") require("src.tools.helpers.init") -require("src.tools.auto_starter")(User_config.autostart) -require("src.tools.dbus.bluetooth_dbus")() +--require("src.tools.auto_starter")(User_config.autostart) +--require("src.tools.dbus.bluetooth_dbus")() diff --git a/awesome/src/assets/icons/bluetooth/power.svg b/awesome/src/assets/icons/bluetooth/power.svg new file mode 100644 index 0000000..343d1ba --- /dev/null +++ b/awesome/src/assets/icons/bluetooth/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/bluetooth/refresh.svg b/awesome/src/assets/icons/bluetooth/refresh.svg new file mode 100644 index 0000000..04b9c88 --- /dev/null +++ b/awesome/src/assets/icons/bluetooth/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/calendar/alarm.svg b/awesome/src/assets/icons/calendar/alarm.svg new file mode 100644 index 0000000..a215e33 --- /dev/null +++ b/awesome/src/assets/icons/calendar/alarm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/calendar/location.svg b/awesome/src/assets/icons/calendar/location.svg new file mode 100644 index 0000000..efbc9ef --- /dev/null +++ b/awesome/src/assets/icons/calendar/location.svg @@ -0,0 +1 @@ + diff --git a/awesome/src/assets/icons/desktop/application.svg b/awesome/src/assets/icons/desktop/application.svg new file mode 100644 index 0000000..9478edb --- /dev/null +++ b/awesome/src/assets/icons/desktop/application.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/copy.svg b/awesome/src/assets/icons/desktop/copy.svg new file mode 100644 index 0000000..cedde8d --- /dev/null +++ b/awesome/src/assets/icons/desktop/copy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/cut.svg b/awesome/src/assets/icons/desktop/cut.svg new file mode 100644 index 0000000..73f4554 --- /dev/null +++ b/awesome/src/assets/icons/desktop/cut.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/delete.svg b/awesome/src/assets/icons/desktop/delete.svg new file mode 100644 index 0000000..0f0c936 --- /dev/null +++ b/awesome/src/assets/icons/desktop/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/dots-vertical.svg b/awesome/src/assets/icons/desktop/dots-vertical.svg new file mode 100644 index 0000000..0a1ae0e --- /dev/null +++ b/awesome/src/assets/icons/desktop/dots-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/edit.svg b/awesome/src/assets/icons/desktop/edit.svg new file mode 100644 index 0000000..2e90a4f --- /dev/null +++ b/awesome/src/assets/icons/desktop/edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/energy_settings.svg b/awesome/src/assets/icons/desktop/energy_settings.svg new file mode 100644 index 0000000..61443d1 --- /dev/null +++ b/awesome/src/assets/icons/desktop/energy_settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/file.svg b/awesome/src/assets/icons/desktop/file.svg new file mode 100644 index 0000000..a978967 --- /dev/null +++ b/awesome/src/assets/icons/desktop/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/file_add.svg b/awesome/src/assets/icons/desktop/file_add.svg new file mode 100644 index 0000000..e4dc811 --- /dev/null +++ b/awesome/src/assets/icons/desktop/file_add.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/file_manager.svg b/awesome/src/assets/icons/desktop/file_manager.svg new file mode 100644 index 0000000..d647d05 --- /dev/null +++ b/awesome/src/assets/icons/desktop/file_manager.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/folder.svg b/awesome/src/assets/icons/desktop/folder.svg new file mode 100644 index 0000000..d647d05 --- /dev/null +++ b/awesome/src/assets/icons/desktop/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/gtk_settings.svg b/awesome/src/assets/icons/desktop/gtk_settings.svg new file mode 100644 index 0000000..da0ebdc --- /dev/null +++ b/awesome/src/assets/icons/desktop/gtk_settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/launch.svg b/awesome/src/assets/icons/desktop/launch.svg new file mode 100644 index 0000000..0435cea --- /dev/null +++ b/awesome/src/assets/icons/desktop/launch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/music_player.svg b/awesome/src/assets/icons/desktop/music_player.svg new file mode 100644 index 0000000..45620c1 --- /dev/null +++ b/awesome/src/assets/icons/desktop/music_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/awesome/src/assets/icons/desktop/power.svg b/awesome/src/assets/icons/desktop/power.svg new file mode 100644 index 0000000..343d1ba --- /dev/null +++ b/awesome/src/assets/icons/desktop/power.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/quit.svg b/awesome/src/assets/icons/desktop/quit.svg new file mode 100644 index 0000000..343d1ba --- /dev/null +++ b/awesome/src/assets/icons/desktop/quit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/refresh.svg b/awesome/src/assets/icons/desktop/refresh.svg new file mode 100644 index 0000000..04b9c88 --- /dev/null +++ b/awesome/src/assets/icons/desktop/refresh.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/screen_settings.svg b/awesome/src/assets/icons/desktop/screen_settings.svg new file mode 100644 index 0000000..9dc942a --- /dev/null +++ b/awesome/src/assets/icons/desktop/screen_settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/search.svg b/awesome/src/assets/icons/desktop/search.svg new file mode 100644 index 0000000..fa4b7e7 --- /dev/null +++ b/awesome/src/assets/icons/desktop/search.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/terminal.svg b/awesome/src/assets/icons/desktop/terminal.svg new file mode 100644 index 0000000..2768962 --- /dev/null +++ b/awesome/src/assets/icons/desktop/terminal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/text_editor.svg b/awesome/src/assets/icons/desktop/text_editor.svg new file mode 100644 index 0000000..0ba9680 --- /dev/null +++ b/awesome/src/assets/icons/desktop/text_editor.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/desktop/web_browser.svg b/awesome/src/assets/icons/desktop/web_browser.svg new file mode 100644 index 0000000..7984bd2 --- /dev/null +++ b/awesome/src/assets/icons/desktop/web_browser.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/airplane-off.svg b/awesome/src/assets/icons/network/airplane-off.svg new file mode 100644 index 0000000..179ebb3 --- /dev/null +++ b/awesome/src/assets/icons/network/airplane-off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/airplane-on.svg b/awesome/src/assets/icons/network/airplane-on.svg new file mode 100644 index 0000000..88b0d1d --- /dev/null +++ b/awesome/src/assets/icons/network/airplane-on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/link.svg b/awesome/src/assets/icons/network/link.svg new file mode 100644 index 0000000..6f4c3b6 --- /dev/null +++ b/awesome/src/assets/icons/network/link.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/menu-down.svg b/awesome/src/assets/icons/network/menu-down.svg new file mode 100644 index 0000000..50b8625 --- /dev/null +++ b/awesome/src/assets/icons/network/menu-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/menu-up.svg b/awesome/src/assets/icons/network/menu-up.svg new file mode 100644 index 0000000..5fb8642 --- /dev/null +++ b/awesome/src/assets/icons/network/menu-up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/assets/icons/network/wifi-strength-5.svg b/awesome/src/assets/icons/network/wifi-strength-5.svg new file mode 100644 index 0000000..3974275 --- /dev/null +++ b/awesome/src/assets/icons/network/wifi-strength-5.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/src/core/notifications.lua b/awesome/src/core/notifications.lua index c6f9835..12d54a6 100644 --- a/awesome/src/core/notifications.lua +++ b/awesome/src/core/notifications.lua @@ -418,10 +418,6 @@ naughty.connect_signal( widget_template = w_template } - awful.spawn.easy_async_with_shell( - "paplay /usr/share/sounds/freedesktop/stereo/message.oga" - ) - box.buttons = {} n.buttons = {} end diff --git a/awesome/src/core/signals.lua b/awesome/src/core/signals.lua index 55d8a8f..b1bc8d1 100644 --- a/awesome/src/core/signals.lua +++ b/awesome/src/core/signals.lua @@ -47,6 +47,13 @@ capi.client.connect_signal( if c.transient_for then c.floating = true end + if c.fullscreen then + gears.timer.delayed_call(function() + if c.valid then + c:geometry(c.screen.geometry) + end + end) + end end ) diff --git a/awesome/src/modules/__test.lua b/awesome/src/modules/__test.lua new file mode 100644 index 0000000..e60ff2c --- /dev/null +++ b/awesome/src/modules/__test.lua @@ -0,0 +1,60 @@ +local setmetatable = setmetatable +local base = require("wibox.widget.base") +local gtable = require("gears.table") +local wibox = require("wibox") + +local module = { mt = {} } + +function module:layout(_, width, height) + if self._private.widget then + return { base.place_widget_at(self._private.widget, 0, 0, width, height) } + end +end + +function module:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +module.set_widget = base.set_widget_common + +function module:set_widget_template(widget_template) + self._private.widget_template = widget_template + self:set_widget(widget_template) +end + +function module:get_widget() + return self._private.widget +end + +function module:get_children() + return { self._private.widget } +end + +function module:set_children(children) + self:set_widget(children[1]) +end + +function module:reset() + self._private.widget_template = nil + self:set_widget(nil) +end + +local function new(args) + local self = base.make_widget(nil, nil, { enable_properties = true }) + + gtable.crush(self, module, true) + + self:set_widget(wibox.widget.textbox("Hello World!")) + + return self +end + +function module.mt:__call(...) + return new(...) +end + +return setmetatable(module, module.mt) diff --git a/awesome/src/modules/application_launcher/application.lua b/awesome/src/modules/application_launcher/application.lua index eefaf02..c490155 100644 --- a/awesome/src/modules/application_launcher/application.lua +++ b/awesome/src/modules/application_launcher/application.lua @@ -9,21 +9,242 @@ local gfilesystem = require("gears").filesystem local dpi = require("beautiful").xresources.apply_dpi local gears = require("gears") local wibox = require("wibox") +local base = require("wibox.widget.base") +local gtable = require("gears.table") + +local json = require("src.lib.json-lua.json-lua") +local cm = require("src.modules.context_menu.init") local capi = { awesome = awesome, mouse = mouse, } -local json = require("src.lib.json-lua.json-lua") - -local cm = require("src.modules.context_menu") - local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/context_menu/" -return function(s) +local application_grid = { mt = {} } - local application_grid = wibox.widget { +function application_grid:layout(_, width, height) + if self._private.widget then + return { base.place_widget_at(self._private.widget, 0, 0, width, height) } + end +end + +function application_grid:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +application_grid.set_widget = base.set_widget_common + +function application_grid:get_widget() + return self._private.widget +end + +function application_grid:get_applications_from_file() + local list = {} + local app_info = Gio.AppInfo + local apps = app_info.get_all() + for _, app in ipairs(apps) do + if app.should_show(app) then -- check no display + local desktop_app_info = Gio.DesktopAppInfo.new(app_info.get_id(app)) + local app_widget = wibox.widget { + { + { + { + { + { -- Icon + valign = "center", + halign = "center", + image = Get_gicon_path(app_info.get_icon(app)), + resize = true, + widget = wibox.widget.imagebox + }, + height = dpi(64), + width = dpi(64), + strategy = "exact", + widget = wibox.container.constraint + }, + { + { -- Name + text = app_info.get_name(app), + align = "center", + valign = "center", + widget = wibox.widget.textbox + }, + strategy = "exact", + width = dpi(170), + -- Prevents widget from overflowing + height = dpi(40), + widget = wibox.container.constraint + }, + layout = wibox.layout.fixed.vertical + }, + halign = "center", + valign = "center", + widget = wibox.container.place + }, + margins = dpi(10), + widget = wibox.container.margin + }, + name = app_info.get_name(app), + comment = Gio.DesktopAppInfo.get_string(desktop_app_info, "Comment") or "", + exec = Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"), + keywords = Gio.DesktopAppInfo.get_string(desktop_app_info, "Keywords") or "", + categories = Gio.DesktopAppInfo.get_categories(desktop_app_info) or "", + terminal = Gio.DesktopAppInfo.get_string(desktop_app_info, "Terminal") == "true", + actions = Gio.DesktopAppInfo.list_actions(desktop_app_info), + border_color = Theme_config.application_launcher.application.border_color, + border_width = Theme_config.application_launcher.application.border_width, + bg = Theme_config.application_launcher.application.bg, + fg = Theme_config.application_launcher.application.fg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(8)) + end, + widget = wibox.container.background + } + + local context_menu = cm { + widget_template = wibox.widget { + { + { + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "icon_role", + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + { + widget = wibox.widget.textbox, + valign = "center", + halign = "left", + id = "text_role" + }, + layout = wibox.layout.fixed.horizontal + }, + widget = wibox.container.margin + }, + widget = wibox.container.background, + }, + spacing = dpi(10), + entries = { + { + name = "Execute as sudo", + icon = gears.color.recolor_image(icondir .. "launch.svg", + Theme_config.application_launcher.application.cm_icon_color), + callback = function() + capi.awesome.emit_signal("application_launcher::show") + awful.spawn("/home/crylia/.config/awesome/src/scripts/start_as_admin.sh " .. app_widget.exec) + end + }, + { + name = "Pin to dock", + icon = gears.color.recolor_image(icondir .. "pin.svg", + Theme_config.application_launcher.application.cm_icon_color), + callback = function() + local dir = gears.filesystem.get_configuration_dir() .. "src/config" + gfilesystem.make_directories(dir) + if not gfilesystem.file_readable(dir) then + os.execute("touch " .. dir .. "/dock.json") + end + local handler = io.open(dir .. "/dock.json", "r") + if not handler then + return + end + local dock_table = json:decode(handler:read("a")) or {} + handler:close() + + ---@diagnostic disable-next-line: param-type-mismatch + table.insert(dock_table, { + name = app_widget.name or "", + icon = Get_gicon_path(app_info.get_icon(app)) or "", + comment = app_widget.comment or "", + exec = app_widget.exec or "", + keywords = app_widget.keywords or "", + categories = app_widget.categories or "", + terminal = app_widget.terminal or "", + actions = app_widget.actions or "", + desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or "" + }) + local dock_encoded = json:encode(dock_table) + handler = io.open("/home/crylia/.config/awesome/src/config/dock.json", "w") + if not handler then + return + end + handler:write(dock_encoded) + handler:close() + capi.awesome.emit_signal("dock::changed") + end + }, + { + name = "Add to desktop", + icon = gears.color.recolor_image(icondir .. "desktop.svg", + Theme_config.application_launcher.application.cm_icon_color), + callback = function() + capi.awesome.emit_signal("application_launcher::show") + capi.awesome.emit_signal("desktop::add_to_desktop", { + label = app_info.get_name(app), + icon = Get_gicon_path(app_info.get_icon(app)) or "", + exec = Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"), + desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or "" + }) + end + } + } + } + + context_menu:connect_signal("mouse::leave", function() + context_menu.visible = false + end) + + -- Execute command on left click and hide launcher + app_widget:buttons( + gears.table.join( + awful.button({ + modifiers = {}, + button = 1, + on_release = function() + Gio.AppInfo.launch_uris_async(app) + --!Change! + capi.awesome.emit_signal("application_launcher::show") + end + }), + awful.button({ + modifiers = {}, + button = 3, + on_release = function() + context_menu:toggle() + end + }) + ) + ) + Hover_signal(app_widget) + table.insert(list, app_widget) + end + end + self.app_list = list +end + +function application_grid:set_applications(search_filter) + local filter = search_filter or self.filter or "" + -- Reset to first position + self._private.curser = { + x = 1, + y = 1 + } + + local grid = wibox.widget { homogenous = true, expand = false, spacing = dpi(10), @@ -34,279 +255,104 @@ return function(s) orientation = "vertical", layout = wibox.layout.grid } - -- Selected application position, default is first at 1,1 - -- The typo *might* be intentional - local curser = { + + for _, application in ipairs(self.app_list) do + -- Match the filter + if string.match(string.lower(application.name or ""), string.lower(filter)) or + string.match(string.lower(application.categories or ""), string.lower(filter)) or + string.match(string.lower(application.keywords or ""), string.lower(filter)) then + grid:add(application) + + -- Get the current position in the grid of the application as a table + local pos = grid:get_widget_position(application) + + -- Check if the curser is currently at the same position as the application + capi.awesome.connect_signal( + "update::selected", + function() + if self._private.curser.y == pos.row and self._private.curser.x == pos.col then + application.border_color = Theme_config.application_launcher.application.border_color_active + else + application.border_color = Theme_config.application_launcher.application.border_color + end + end + ) + end + end + capi.awesome.emit_signal("update::selected") + self:set_widget(grid) +end + +function application_grid:move_up() + self._private.curser.y = self._private.curser.y - 1 + if self._private.curser.y < 1 then + self._private.curser.y = 1 + end + capi.awesome.emit_signal("update::selected") +end + +function application_grid:move_down() + print(self._private.curser.y) + self._private.curser.y = self._private.curser.y + 1 + local grid_rows, _ = self:get_widget():get_dimension() + if self._private.curser.y > grid_rows then + self._private.curser.y = grid_rows + end + capi.awesome.emit_signal("update::selected") +end + +function application_grid:move_left() + self._private.curser.x = self._private.curser.x - 1 + if self._private.curser.x < 1 then + self._private.curser.x = 1 + end + capi.awesome.emit_signal("update::selected") +end + +function application_grid:move_right() + self._private.curser.x = self._private.curser.x + 1 + local _, grid_cols = self:get_widget():get_dimension() + if self._private.curser.x > grid_cols then + self._private.curser.x = grid_cols + end + capi.awesome.emit_signal("update::selected") +end + +function application_grid:execute() + local selected_widget = self:get_widget():get_widgets_at(self._private.curser.y, + self._private.curser.x)[1] + Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0)) +end + +function application_grid:reset() + self._private.curser = { + x = 1, + y = 1 + } + capi.awesome.emit_signal("update::selected") +end + +function application_grid.new(args) + args = args or {} + + local w = base.make_widget(nil, nil, { enable_properties = true }) + + gtable.crush(w, application_grid, true) + + w._private.curser = { x = 1, y = 1 } - local filter = "" + w:get_applications_from_file() - ---Executes only once to create a widget from each desktop file - ---@return table widgets Unsorted widget table - local function get_applications_from_file() - local list = {} - local app_info = Gio.AppInfo - local apps = app_info.get_all() - for _, app in ipairs(apps) do - if app.should_show(app) then -- check no display - local desktop_app_info = Gio.DesktopAppInfo.new(app_info.get_id(app)) - local app_widget = wibox.widget { - { - { - { - { - { -- Icon - valign = "center", - halign = "center", - image = Get_gicon_path(app_info.get_icon(app)), - resize = true, - widget = wibox.widget.imagebox - }, - height = dpi(64), - width = dpi(64), - strategy = "exact", - widget = wibox.container.constraint - }, - { - { -- Name - text = app_info.get_name(app), - align = "center", - valign = "center", - widget = wibox.widget.textbox - }, - strategy = "exact", - width = dpi(170), - -- Prevents widget from overflowing - height = dpi(40), - widget = wibox.container.constraint - }, - layout = wibox.layout.fixed.vertical - }, - halign = "center", - valign = "center", - widget = wibox.container.place - }, - margins = dpi(10), - widget = wibox.container.margin - }, - name = app_info.get_name(app), - comment = Gio.DesktopAppInfo.get_string(desktop_app_info, "Comment") or "", - exec = Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"), - keywords = Gio.DesktopAppInfo.get_string(desktop_app_info, "Keywords") or "", - categories = Gio.DesktopAppInfo.get_categories(desktop_app_info) or "", - terminal = Gio.DesktopAppInfo.get_string(desktop_app_info, "Terminal") == "true", - actions = Gio.DesktopAppInfo.list_actions(desktop_app_info), - border_color = Theme_config.application_launcher.application.border_color, - border_width = Theme_config.application_launcher.application.border_width, - bg = Theme_config.application_launcher.application.bg, - fg = Theme_config.application_launcher.application.fg, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(8)) - end, - widget = wibox.container.background - } + w:set_applications() - local context_menu = cm({ - entries = { - { - name = "Execute as sudo", - icon = gears.color.recolor_image(icondir .. "launch.svg", Theme_config.context_menu.icon_color), - callback = function() - capi.awesome.emit_signal("application_launcher::show") - awful.spawn("/home/crylia/.config/awesome/src/scripts/start_as_admin.sh " .. app_widget.exec) - end - }, - { - name = "Pin to dock", - icon = gears.color.recolor_image(icondir .. "pin.svg", Theme_config.context_menu.icon_color), - callback = function() - local dir = gears.filesystem.get_configuration_dir() .. "src/config" - gfilesystem.make_directories(dir) - if not gfilesystem.file_readable(dir) then - os.execute("touch " .. dir .. "/dock.json") - end - local handler = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r") - if not handler then - return - end - local dock_table = json:decode(handler:read("a")) or {} - handler:close() - - ---@diagnostic disable-next-line: param-type-mismatch - table.insert(dock_table, { - name = app_widget.name or "", - icon = Get_gicon_path(app_info.get_icon(app)) or "", - comment = app_widget.comment or "", - exec = app_widget.exec or "", - keywords = app_widget.keywords or "", - categories = app_widget.categories or "", - terminal = app_widget.terminal or "", - actions = app_widget.actions or "", - desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or "" - }) - local dock_encoded = json:encode(dock_table) - handler = io.open("/home/crylia/.config/awesome/src/config/dock.json", "w") - if not handler then - return - end - handler:write(dock_encoded) - handler:close() - capi.awesome.emit_signal("dock::changed") - end - }, - { - name = "Add to desktop", - icon = gears.color.recolor_image(icondir .. "desktop.svg", Theme_config.context_menu.icon_color), - callback = function() - capi.awesome.emit_signal("application_launcher::show") - --!TODO: Add to desktop - end - } - } - }) - - -- Execute command on left click and hide launcher - app_widget:buttons( - gears.table.join( - awful.button({ - modifiers = {}, - button = 1, - on_release = function() - Gio.AppInfo.launch_uris_async(app) - capi.awesome.emit_signal("application_launcher::show") - end - }), - awful.button({ - modifiers = {}, - button = 3, - on_release = function() - if not context_menu then - return - end - -- add offset so mouse is above widget, this is so the mouse::leave event triggers always - context_menu.x = capi.mouse.coords().x - 10 - context_menu.y = capi.mouse.coords().y - 10 - context_menu.visible = not context_menu.visible - end - }) - ) - ) - Hover_signal(app_widget) - table.insert(list, app_widget) - end - end - return list - end - - -- Table to hold all application widgets unsorted - local application_list = get_applications_from_file() - - ---Function to filter the applications and sort them into a widget grid - ---@param search_filter string Filter string from the searchbar - ---@return wibox.layout.grid wibox.layout.grid Sorted grid with all applications matching the filter - local function get_applications(search_filter) - filter = search_filter or filter - --Clear grid from previous widgets - application_grid:reset() - -- Reset to first position - curser = { - x = 1, - y = 1 - } - for _, application in ipairs(application_list) do - -- Match the filter - if string.match(string.lower(application.name), string.lower(filter)) or - string.match(string.lower(application.categories), string.lower(filter)) or - string.match(string.lower(application.keywords), string.lower(filter)) then - application_grid:add(application) - - -- Get the current position in the grid of the application as a table - local pos = application_grid:get_widget_position(application) - - -- Check if the curser is currently at the same position as the application - capi.awesome.connect_signal( - "update::selected", - function() - if curser.y == pos.row and curser.x == pos.col then - application.border_color = Theme_config.application_launcher.application.border_color_active - else - application.border_color = Theme_config.application_launcher.application.border_color - end - end - ) - capi.awesome.emit_signal("update::selected") - end - end - - return application_grid - end - - application_grid = get_applications(filter) - - capi.awesome.connect_signal( - "application::left", - function() - curser.x = curser.x - 1 - if curser.x < 1 then - curser.x = 1 - end - capi.awesome.emit_signal("update::selected") - end - ) - - capi.awesome.connect_signal( - "application::right", - function() - curser.x = curser.x + 1 - local _, grid_cols = application_grid:get_dimension() - if curser.x > grid_cols then - curser.x = grid_cols - end - capi.awesome.emit_signal("update::selected") - end - ) - - capi.awesome.connect_signal( - "application::up", - function() - curser.y = curser.y - 1 - if curser.y < 1 then - curser.y = 1 - end - capi.awesome.emit_signal("update::selected") - end - ) - - capi.awesome.connect_signal( - "application::down", - function() - curser.y = curser.y + 1 - local grid_rows, _ = application_grid:get_dimension() - if curser.y > grid_rows then - curser.y = grid_rows - end - capi.awesome.emit_signal("update::selected") - end - ) - - capi.awesome.connect_signal( - "update::application_list", - function(f) - application_grid = get_applications(f) - end - ) - - capi.awesome.connect_signal( - "application_launcher::execute", - function() - capi.awesome.emit_signal("searchbar::stop") - - local selected_widget = application_grid:get_widgets_at(curser.y, curser.x)[1] - Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0)) - end - ) - - return application_grid + return w end + +function application_grid.mt:__call(...) + return application_grid.new(...) +end + +return setmetatable(application_grid, application_grid.mt) diff --git a/awesome/src/modules/application_launcher/init.lua b/awesome/src/modules/application_launcher/init.lua index d63ea44..ef7c988 100644 --- a/awesome/src/modules/application_launcher/init.lua +++ b/awesome/src/modules/application_launcher/init.lua @@ -7,23 +7,67 @@ local awful = require("awful") local dpi = require("beautiful").xresources.apply_dpi local gears = require("gears") local wibox = require("wibox") +local gshape = require("gears.shape") +local gtable = require("gears.table") +local gobject = require("gears.object") local capi = { awesome = awesome, mouse = mouse, } -local application_grid = require("src.modules.application_launcher.application")() -local searchbar = require("src.modules.application_launcher.searchbar")() +local application_launcher = { mt = {} } -return function(s) +application_launcher.searchbar = awful.widget.inputbox { + widget_template = wibox.template { + widget = wibox.widget { + { + { + { + widget = wibox.widget.textbox, + halign = "left", + valign = "center", + id = "text_role", + }, + widget = wibox.container.margin, + margins = 5, + id = "marg" + }, + widget = wibox.container.constraint, + strategy = "exact", + width = 400, + height = 50, + id = "const" + }, + widget = wibox.container.background, + bg = "#212121", + fg = "#F0F0F0", + border_color = "#414141", + border_width = 2, + shape = gshape.rounded_rect, + }, + update_callback = function(template_widget, args) + template_widget.widget.const.marg.text_role.markup = args.text + end + } +} + +application_launcher.application_grid = require("src.modules.application_launcher.application") {} + + +function application_launcher.new(args) + args = args or {} + + local ret = gobject { enable_properties = true } + + gtable.crush(ret, application_launcher, true) local applicaton_launcher = wibox.widget { { { - searchbar, + ret.searchbar, { - application_grid, + ret.application_grid, spacing = dpi(10), layout = require("src.lib.overflow_widget.overflow").vertical, scrollbar_width = 0, @@ -36,18 +80,18 @@ return function(s) margins = dpi(20), widget = wibox.container.margin }, - height = s.geometry.height / 100 * 60, + height = args.screen.geometry.height / 100 * 60, --width = s.geometry.width / 100 * 60, strategy = "exact", widget = wibox.container.constraint } - local application_container = awful.popup { - widget = wibox.container.background, + ret.application_container = awful.popup { + widget = applicaton_launcher, ontop = true, visible = false, stretch = false, - screen = s, + screen = args.screen, shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(12)) end, @@ -57,24 +101,90 @@ return function(s) border_width = Theme_config.application_launcher.border_width } - application_container:setup { - applicaton_launcher, - layout = wibox.layout.fixed.vertical - } - capi.awesome.connect_signal( "application_launcher::show", function() - if capi.mouse.screen == s then - application_container.visible = not application_container.visible - if application_container.visible == false then - capi.awesome.emit_signal("searchbar::stop") - end + if capi.mouse.screen == args.screen then + ret.application_container.visible = not ret.application_container.visible end - if application_container.visible then - capi.awesome.emit_signal("searchbar::start") + if ret.application_container.visible then + ret.searchbar:focus() + else + awful.keygrabber.stop() end end ) + ret.searchbar:connect_signal( + "submit", + function(text) + ret.application_grid:execute() + capi.awesome.emit_signal("application_launcher::show") + end + ) + + ret.searchbar:connect_signal( + "stopped", + function() + ret.searchbar:get_widget().widget.border_color = Theme_config.application_launcher.searchbar.border_color + end + ) + + ret.searchbar:connect_signal( + "started", + function() + ret.searchbar:get_widget().widget.border_color = Theme_config.application_launcher.searchbar.border_active + end + ) + + awesome.connect_signal( + "inputbox::key_pressed", + function(modkey, key) + if key == "Escape" then + ret.searchbar:stop() + capi.awesome.emit_signal("application_launcher::show") + ret.application_grid:reset() + ret.searchbar:set_text("") + elseif key == "Down" or key == "Right" then + ret.searchbar:stop() + awful.keygrabber.run(function(mod, key2, event) + if event == "press" then + if key2 == "Down" then + ret.application_grid:move_down() + elseif key2 == "Up" then + local old_y = ret.application_grid._private.curser.y + ret.application_grid:move_up() + if old_y - ret.application_grid._private.curser.y == 0 then + ret.searchbar:focus() + end + elseif key2 == "Left" then + ret.application_grid:move_left() + elseif key2 == "Right" then + ret.application_grid:move_right() + elseif key2 == "Return" then + awful.keygrabber.stop() + ret.application_grid:execute() + capi.awesome.emit_signal("application_launcher::show") + ret.application_grid:reset() + ret.searchbar:set_text("") + elseif key2 == "Escape" then + capi.awesome.emit_signal("application_launcher::show") + ret.application_grid:reset() + ret.searchbar:set_text("") + awful.keygrabber.stop() + end + end + end) + end + ret.application_grid:set_applications(ret.searchbar:get_text()) + end + ) + + return ret end + +function application_launcher.mt:__call(...) + return application_launcher.new(...) +end + +return setmetatable(application_launcher, application_launcher.mt) diff --git a/awesome/src/modules/audio/volume_controller.lua b/awesome/src/modules/audio/volume_controller.lua new file mode 100644 index 0000000..47445b0 --- /dev/null +++ b/awesome/src/modules/audio/volume_controller.lua @@ -0,0 +1,553 @@ +----------------------------------- +-- This is the volume controller -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +local gobject = require("gears.object") + +local capi = { + awesome = awesome, + mousegrabber = mousegrabber, +} + +local rubato = require("src.lib.rubato") + +-- Icon directory path +local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/" + +local volume_controler = { mt = {} } + +function volume_controler.get_device_widget() + local device = wibox.widget { + { + { + { + id = "icon", + resize = false, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox + }, + spacing = dpi(10), + { + text = name, + id = "node", + widget = wibox.widget.textbox + }, + id = "device_layout", + layout = wibox.layout.fixed.horizontal + }, + id = "device_margin", + margins = dpi(9), + widget = wibox.container.margin + }, + id = "background", + bg = Theme_config.volume_controller.device_bg, + border_color = Theme_config.volume_controller.device_border_color, + border_width = Theme_config.volume_controller.device_border_width, + shape = Theme_config.volume_controller.device_shape, + widget = wibox.container.background + } + if true then + device:connect_signal( + "button::press", + function(_, _, _, key) + if key == 1 then + if node then + --awful.spawn("./.config/awesome/src/scripts/vol.sh set_sink " .. node) + --capi.awesome.emit_signal("update::bg_sink", node) + end + end + end + ) + --[[ capi.awesome.connect_signal( + "update::bg_sink", + function(new_node) + if node == new_node then + device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg", + Theme_config.volume_controller.device_icon_color) + device.bg = Theme_config.volume_controller.device_headphones_selected_bg + device.fg = Theme_config.volume_controller.device_headphones_selected_fg + Hover_signal(device) + else + device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg", + Theme_config.volume_controller.device_headphones_selected_icon_color) + device.bg = Theme_config.volume_controller.device_bg + device.fg = Theme_config.volume_controller.device_headphones_fg + Hover_signal(device) + end + end + ) ]] + else + device:connect_signal( + "button::press", + function(_, _, _, key) + if key == 1 then + if node then + --awful.spawn("./.config/awesome/src/scripts/mic.sh set_source " .. node) + --capi.awesome.emit_signal("update::bg_source", node) + end + end + end + ) + --[[ capi.awesome.connect_signal( + "update::bg_source", + function(new_node) + if node == new_node then + device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg", + Theme_config.volume_controller.device_icon_color) + device.bg = Theme_config.volume_controller.device_microphone_selected_bg + device.fg = Theme_config.volume_controller.device_microphone_selected_fg + Hover_signal(device) + else + device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg", + Theme_config.volume_controller.device_microphone_selected_icon_color) + device.bg = Theme_config.volume_controller.device_bg + device.fg = Theme_config.volume_controller.device_microphone_fg + Hover_signal(device) + end + end + ) ]] + end + return device +end + +-- Get all source devices +function volume_controler:get_source_devices() + +end + +-- Get all input devices +function volume_controler:get_input_devices() + +end + +function volume_controler:toggle() + volume_controler.popup.visible = not volume_controler.popup.visible +end + +function volume_controler.run(args) + + args = args or {} + + local ret = gobject {} + + local w = wibox.widget { + { + { + -- Audio Device selector + { + { + { + { + { + resize = false, + image = gears.color.recolor_image(icondir .. "menu-down.svg", + Theme_config.volume_controller.device_headphones_selected_icon_color), + widget = wibox.widget.imagebox, + valign = "center", + halign = "center", + id = "icon" + }, + id = "center", + halign = "center", + valign = "center", + widget = wibox.container.place, + }, + { + { + text = "Output Device", + widget = wibox.widget.textbox, + id = "device_name" + }, + margins = dpi(5), + widget = wibox.container.margin + }, + id = "audio_volume", + layout = wibox.layout.fixed.horizontal + }, + id = "audio_bg", + bg = Theme_config.volume_controller.list_bg, + fg = Theme_config.volume_controller.list_headphones_fg, + shape = Theme_config.volume_controller.list_shape, + widget = wibox.container.background + }, + id = "audio_selector_margin", + left = dpi(10), + right = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + { + id = "volume_list", + widget = { + { + { + { + { + spacing = dpi(10), + layout = require("src.lib.overflow_widget.overflow").vertical, + scrollbar_width = 0, + step = dpi(50), + id = "volume_device_list", + }, + id = "margin", + margins = dpi(10), + widget = wibox.container.margin + }, + id = "place", + height = dpi(200), + strategy = "max", + widget = wibox.container.constraint + }, + border_color = Theme_config.volume_controller.list_border_color, + border_width = Theme_config.volume_controller.list_border_width, + id = "volume_device_background", + shape = Theme_config.volume_controller.list_shape, + widget = wibox.container.background + }, + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + }, + forced_height = 0 + }, + -- Microphone selector + { + { + { + { + { + resize = false, + image = gears.color.recolor_image(icondir .. "menu-down.svg", + Theme_config.volume_controller.device_microphone_selected_icon_color), + widget = wibox.widget.imagebox, + valign = "center", + halign = "center", + id = "icon", + }, + id = "center", + halign = "center", + valign = "center", + widget = wibox.container.place, + }, + { + { + text = "Input Device", + widget = wibox.widget.textbox, + id = "device_name" + }, + margins = dpi(5), + widget = wibox.container.margin + }, + id = "mic_volume", + layout = wibox.layout.fixed.horizontal + }, + id = "mic_bg", + bg = Theme_config.volume_controller.list_bg, + fg = Theme_config.volume_controller.list_microphone_fg, + shape = Theme_config.volume_controller.selector_shape, + widget = wibox.container.background + }, + id = "mic_selector_margin", + left = dpi(10), + right = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + { + id = "mic_list", + widget = { + { + { + { + { + spacing = dpi(10), + layout = require("src.lib.overflow_widget.overflow").vertical, + id = "volume_device_list", + scrollbar_width = 0, + step = dpi(50), + }, + id = "margin", + margins = dpi(10), + widget = wibox.container.margin + }, + id = "place", + height = dpi(200), + strategy = "max", + widget = wibox.container.constraint + }, + id = "volume_device_background", + border_color = Theme_config.volume_controller.list_border_color, + border_width = Theme_config.volume_controller.list_border_width, + shape = Theme_config.volume_controller.list_shape, + widget = wibox.container.background + }, + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + }, + forced_height = 0 + }, + -- Audio volume slider + { + { + { + resize = false, + widget = wibox.widget.imagebox, + valign = "center", + halign = "center", + image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_controller.volume_fg), + id = "icon", + }, + { + { + bar_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(5)) + end, + bar_height = dpi(5), + bar_color = Theme_config.volume_controller.border_color, + bar_active_color = Theme_config.volume_controller.volume_fg, + handle_color = Theme_config.volume_controller.volume_fg, + handle_shape = gears.shape.circle, + handle_border_color = Theme_config.volume_controller.volume_fg, + handle_width = dpi(12), + maximum = 100, + forced_height = dpi(26), + widget = wibox.widget.slider, + id = "slider" + }, + left = dpi(5), + id = "slider_margin", + widget = wibox.container.margin + }, + id = "audio_volume", + layout = wibox.layout.align.horizontal + }, + id = "audio_volume_margin", + top = dpi(10), + left = dpi(10), + right = dpi(10), + widget = wibox.container.margin + }, + -- Microphone volume slider + { + { + { + resize = false, + widget = wibox.widget.imagebox, + valign = "center", + halign = "center", + image = gears.color.recolor_image(icondir .. "microphone.svg", Theme_config.volume_controller.microphone_fg), + id = "icon" + }, + { + { + bar_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(5)) + end, + bar_height = dpi(5), + bar_color = Theme_config.volume_controller.device_border_color, + bar_active_color = Theme_config.volume_controller.microphone_fg, + handle_color = Theme_config.volume_controller.microphone_fg, + handle_shape = gears.shape.circle, + handle_border_color = Theme_config.volume_controller.microphone_fg, + handle_width = dpi(12), + maximum = 100, + forced_height = dpi(26), + widget = wibox.widget.slider, + id = "slider" + }, + left = dpi(5), + id = "slider_margin", + widget = wibox.container.margin + }, + id = "mic_volume", + layout = wibox.layout.align.horizontal + }, + id = "mic_volume_margin", + left = dpi(10), + right = dpi(10), + top = dpi(10), + widget = wibox.container.margin + }, + id = "controller_layout", + layout = wibox.layout.fixed.vertical + }, + id = "controller_margin", + margins = dpi(10), + widget = wibox.container.margin + }, + bg = Theme_config.volume_controller.bg, + border_color = Theme_config.volume_controller.border_color, + border_width = Theme_config.volume_controller.border_width, + shape = Theme_config.volume_controller.shape, + forced_width = dpi(400), + widget = wibox.container.background + } + + ret.widget = w + ret.audio_dropdown = w:get_children_by_id("audio_list")[1] + ret.mic_dropdown = w:get_children_by_id("mic_list")[1] + ret.audio_slider = w:get_children_by_id("slider")[1] + ret.mic_slider = w:get_children_by_id("slider")[1] + + -- Main container + ret.popup = awful.popup { + widget = w, + ontop = true, + bg = Theme_config.volume_controller.bg, + stretch = false, + visible = false, + screen = args.screen, + --! Calculate the popup position instead of hardcoding it + placement = function(c) awful.placement.align(c, + { position = "top_right", margins = { right = dpi(305), top = dpi(60) } }) + end, + shape = Theme_config.volume_controller.shape, + } + + -- Set the volume and icon + capi.awesome.connect_signal( + "audio::get", + function(muted, volume) + if muted then + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color + .recolor_image(icondir .. "volume-mute.svg", Theme_config.volume_controller.volume_fg)) + else + volume = tonumber(volume) + if not volume then + return + end + local icon = icondir .. "volume" + if volume < 1 then + icon = icon .. "-mute" + elseif volume >= 1 and volume < 34 then + icon = icon .. "-low" + elseif volume >= 34 and volume < 67 then + icon = icon .. "-medium" + elseif volume >= 67 then + icon = icon .. "-high" + end + + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.slider_margin.slider: + set_value(volume) + volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color + .recolor_image(icon + .. ".svg", Theme_config.volume_controller.volume_fg)) + end + end + ) + + -- Get microphone volume + capi.awesome.connect_signal( + "microphone::get", + function(muted, volume) + if muted then + --volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(0)) + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir + .. "microphone-off.svg", Theme_config.volume_controller.microphone_fg)) + else + volume = tonumber(volume) + if not volume then + return + end + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(volume)) + if volume > 0 then + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir + .. "microphone.svg", Theme_config.volume_controller.microphone_fg)) + else + volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir + .. "microphone-off.svg", Theme_config.volume_controller.microphone_fg)) + end + end + end + ) + + -- Microphone slider change event + ret.widget:connect_signal( + "property::value", + function() + end + ) + + -- Slide animation + ret.audio_dropdown:connect_signal( + "button::press", + function(_, _, _, key) + if key == 1 then + local rubato_timer = rubato.timed { + duration = 0.4, + intro = 0.1, + outro = 0.1, + pos = mic_list.forced_height, + easing = rubato.linear, + subscribed = function(v) + mic_list.forced_height = v + end + } + if mic_list.forced_height == 0 then + rubato_timer.target = dpi(200) + mic_selector_margin.mic_bg.shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4)) + end + mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg", + Theme_config.volume_controller.device_microphone_selected_icon_color)) + else + rubato_timer.target = 0 + mic_bg.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(4)) + end + mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg", + Theme_config.volume_controller.device_microphone_selected_icon_color)) + end + end + end + ) + + -- Slide animation + ret.mic_dropdown:connect_signal( + "button::press", + function(_, _, _, key) + if key == 1 then + local rubato_timer = rubato.timed { + duration = 0.4, + intro = 0.1, + outro = 0.1, + pos = volume_list.forced_height, + easing = rubato.linear, + subscribed = function(v) + volume_list.forced_height = v + end + } + if volume_list.forced_height == 0 then + rubato_timer.target = dpi(200) + audio_bg.shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4)) + end + audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg", + Theme_config.volume_controller.device_headphones_selected_icon_color)) + else + rubato_timer.target = 0 + audio_bg.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(4)) + end + audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg", + Theme_config.volume_controller.device_headphones_selected_icon_color)) + end + end + end + ) + + return ret +end + +function volume_controler.mt:__call(...) + return volume_controler.run(...) +end + +return setmetatable(volume_controler, volume_controler.mt) diff --git a/awesome/src/modules/audio/volume_osd.lua b/awesome/src/modules/audio/volume_osd.lua new file mode 100644 index 0000000..d53a145 --- /dev/null +++ b/awesome/src/modules/audio/volume_osd.lua @@ -0,0 +1,153 @@ +----------------------------------- +-- This is the volume_old module -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") +local gobject = require("gears.object") + +local capi = { + awesome = awesome, + mouse = mouse, +} + +-- Icon directory path +local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/" + +local osd = { mt = {} } + +function osd.new(args) + args = args or {} + args.screen = args.screen or 1 + + local ret = gobject {} + + ret.w = wibox.widget { + { + { + { -- Volume Icon + image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_osd.icon_color), + valign = "center", + halign = "center", + resize = false, + id = "icon", + widget = wibox.widget.imagebox + }, + { -- Volume Bar + { + { + id = "progressbar1", + color = Theme_config.volume_osd.bar_bg_active, + background_color = Theme_config.volume_osd.bar_bg, + max_value = 100, + value = 50, + forced_height = dpi(6), + shape = function(cr, width, heigth) + gears.shape.rounded_bar(cr, width, heigth, dpi(6)) + end, + widget = wibox.widget.progressbar + }, + id = "progressbar_container2", + halign = "center", + valign = "center", + widget = wibox.container.place + }, + id = "progressbar_container", + width = dpi(240), + heigth = dpi(20), + stragety = "max", + widget = wibox.container.constraint + }, + id = "layout1", + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + id = "margin", + margins = dpi(10), + widget = wibox.container.margin + }, + forced_width = dpi(300), + forced_height = dpi(80), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(12)) + end, + border_color = Theme_config.volume_osd.border_color, + border_width = Theme_config.volume_osd.border_width, + fg = Theme_config.volume_osd.fg, + bg = Theme_config.volume_osd.bg, + widget = wibox.container.background + } + + local volume_container = awful.popup { + widget = ret.w, + ontop = true, + stretch = false, + visible = false, + screen = args.screen, + placement = function(c) awful.placement.bottom_left(c, { margins = dpi(20) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(14)) + end + } + + local hide_volume_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + volume_container.visible = false + end + } + + capi.awesome.connect_signal( + "audio::get", + function(muted, volume) + if muted then + ret.w:get_children_by_id("icon")[1] + :set_image(gears.color.recolor_image( + icondir .. "volume-mute" .. ".svg", Theme_config.volume_osd.icon_color)) + ret.w:get_children_by_id("progressbar1")[1].value = tonumber(0) + else + volume = tonumber(volume) + if not volume then + return + end + ret.w:get_children_by_id("progressbar1")[1].value = tonumber(volume) + local icon = icondir .. "volume" + if volume < 1 then + icon = icon .. "-mute" + elseif volume >= 1 and volume < 34 then + icon = icon .. "-low" + elseif volume >= 34 and volume < 67 then + icon = icon .. "-medium" + elseif volume >= 67 then + icon = icon .. "-high" + end + ret.w:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg", + Theme_config.volume_osd.icon_color)) + end + end + ) + + capi.awesome.connect_signal( + "widget::volume_osd:rerun", + function() + if capi.mouse.screen == args.screen then + volume_container.visible = true + if hide_volume_osd.started then + hide_volume_osd:again() + else + hide_volume_osd:start() + end + end + end + ) +end + +function osd.mt:__call(...) + return osd.new(...) +end + +return setmetatable(osd, osd.mt) diff --git a/awesome/src/modules/bluetooth/device.lua b/awesome/src/modules/bluetooth/device.lua index d3d7ad0..25db7d8 100644 --- a/awesome/src/modules/bluetooth/device.lua +++ b/awesome/src/modules/bluetooth/device.lua @@ -181,7 +181,7 @@ function device.new(args) return ret end -function device.mt.__call(...) +function device.mt:__call(...) return device.new(...) end diff --git a/awesome/src/modules/bluetooth/init.lua b/awesome/src/modules/bluetooth/init.lua index d36ad26..a5376b8 100644 --- a/awesome/src/modules/bluetooth/init.lua +++ b/awesome/src/modules/bluetooth/init.lua @@ -51,8 +51,12 @@ local function add_device(self, device, battery) end end -function bluetooth.remove_device(self, device) - +local function remove_device(self, device) + for i, dev in pairs(self.devices) do + if dev.Address == device.Address then + table.remove(self.devices, i) + end + end end function bluetooth.new(args) @@ -110,21 +114,15 @@ function bluetooth.new(args) id = "connected_list", { { - { - step = dpi(50), - spacing = dpi(10), - layout = require("src.lib.overflow_widget.overflow").vertical, - scrollbar_width = 0, - id = "connected_device_list" - }, - id = "margin", - margins = dpi(10), - widget = wibox.container.margin + step = dpi(50), + spacing = dpi(10), + layout = require("src.lib.overflow_widget.overflow").vertical, + scrollbar_width = 0, + id = "connected_device_list" }, - id = "place", - height = dpi(200), - strategy = "max", - widget = wibox.container.constraint + id = "margin", + margins = dpi(10), + widget = wibox.container.margin }, border_color = Theme_config.bluetooth_controller.con_device_border_color, border_width = Theme_config.bluetooth_controller.con_device_border_width, @@ -180,21 +178,15 @@ function bluetooth.new(args) id = "discovered_list", { { - { - id = "discovered_device_list", - spacing = dpi(10), - step = dpi(50), - layout = require("src.lib.overflow_widget.overflow").vertical, - scrollbar_width = 0, - }, - id = "margin", - margins = dpi(10), - widget = wibox.container.margin + id = "discovered_device_list", + spacing = dpi(10), + step = dpi(50), + layout = require("src.lib.overflow_widget.overflow").vertical, + scrollbar_width = 0, }, - id = "place", - height = dpi(200), - strategy = "max", - widget = wibox.container.constraint + id = "margin", + margins = dpi(10), + widget = wibox.container.margin }, border_color = Theme_config.bluetooth_controller.con_device_border_color, border_width = Theme_config.bluetooth_controller.con_device_border_width, @@ -204,6 +196,59 @@ function bluetooth.new(args) widget = wibox.container.background, forced_height = 0 }, + { + { -- action buttons + { -- turn off + { + { + image = gcolor.recolor_image(icondir .. "power.svg", + Theme_config.bluetooth_controller.power_icon_color), + resize = false, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox, + id = "icon" + }, + widget = wibox.container.margin, + margins = dpi(5), + id = "center" + }, + border_width = dpi(2), + border_color = Theme_config.bluetooth_controller.border_color, + shape = function(cr, width, height) + gshape.rounded_rect(cr, width, height, dpi(4)) + end, + bg = Theme_config.bluetooth_controller.power_bg, + widget = wibox.container.background, + id = "power", + }, + nil, + { -- refresh + { + { + image = gcolor.recolor_image(icondir .. "refresh.svg", + Theme_config.bluetooth_controller.refresh_icon_color), + resize = false, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox, + }, + widget = wibox.container.margin, + margins = dpi(5), + }, + border_width = dpi(2), + border_color = Theme_config.bluetooth_controller.border_color, + shape = function(cr, width, height) + gshape.rounded_rect(cr, width, height, dpi(4)) + end, + bg = Theme_config.bluetooth_controller.refresh_bg, + widget = wibox.container.background + }, + layout = wibox.layout.align.horizontal + }, + widget = wibox.container.margin, + top = dpi(10), + }, id = "layout1", layout = wibox.layout.fixed.vertical }, @@ -229,15 +274,14 @@ function bluetooth.new(args) "bluetooth::device_changed", function(device, battery) add_device(ret, device, battery) + remove_device(ret, device) bluetooth_container:get_children_by_id("connected_device_list")[1].children = ret:get_devices().paired bluetooth_container:get_children_by_id("discovered_device_list")[1].children = ret:get_devices().discovered end ) - local connected_margin = bluetooth_container:get_children_by_id("connected_margin")[1] local connected_list = bluetooth_container:get_children_by_id("connected_list")[1] - local connected_bg = bluetooth_container:get_children_by_id("connected_bg")[1] local connected = bluetooth_container:get_children_by_id("connected")[1].center connected_margin:connect_signal( @@ -264,7 +308,7 @@ function bluetooth.new(args) Theme_config.bluetooth_controller.connected_icon_color)) else rubato_timer.target = 0 - connected_bg.shape = function(cr, width, height) + connected_margin.connected_bg.shape = function(cr, width, height) gshape.rounded_rect(cr, width, height, 4) end connected.icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg", @@ -294,9 +338,10 @@ function bluetooth.new(args) if discovered_list.forced_height == 0 then local size = (#ret:get_devices().discovered * 60) + 1 - if size < 210 then - rubato_timer.target = dpi(size) + if size > 210 then + size = 210 end + rubato_timer.target = dpi(size) discovered_margin.discovered_bg.shape = function(cr, width, height) gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4)) end diff --git a/awesome/src/modules/brightness/brightness_osd.lua b/awesome/src/modules/brightness/brightness_osd.lua new file mode 100644 index 0000000..35d821b --- /dev/null +++ b/awesome/src/modules/brightness/brightness_osd.lua @@ -0,0 +1,133 @@ +--------------------------------------- +-- This is the brightness_osd module -- +--------------------------------------- + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +local capi = { + awesome = awesome, + mouse = mouse, +} + +-- Icon directory path +local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/brightness/" + +return function(s) + + local brightness_osd_widget = wibox.widget { + { + { + { -- Brightness Icon + image = gears.color.recolor_image(icondir .. "brightness-high.svg", Theme_config.brightness_osd.icon_color), + valign = "center", + halign = "center", + resize = false, + id = "icon", + widget = wibox.widget.imagebox + }, + { -- Brightness Bar + { + { + id = "progressbar1", + color = Theme_config.brightness_osd.bar_bg_active, + background_color = Theme_config.brightness_osd.bar_bg, + max_value = 100, + value = 0, + forced_height = dpi(6), + shape = function(cr, width, height) + gears.shape.rounded_bar(cr, width, height, dpi(6)) + end, + widget = wibox.widget.progressbar + }, + id = "progressbar_container2", + halign = "center", + valign = "center", + widget = wibox.container.place + }, + id = "progressbar_container", + width = dpi(240), + heigth = dpi(20), + stragety = "max", + widget = wibox.container.constraint + }, + id = "layout1", + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + id = "margin", + margins = dpi(10), + widget = wibox.container.margin + }, + forced_width = dpi(300), + forced_height = dpi(80), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(12)) + end, + border_color = Theme_config.brightness_osd.border_color, + border_width = Theme_config.brightness_osd.border_width, + fg = Theme_config.brightness_osd.fg, + bg = Theme_config.brightness_osd.bg, + widget = wibox.container.background + } + + capi.awesome.connect_signal( + "brightness::get", + function(brightness) + brightness_osd_widget:get_children_by_id("progressbar1")[1].value = brightness + + local icon = icondir .. "brightness" + if brightness >= 0 and brightness < 34 then + icon = icon .. "-low" + elseif brightness >= 34 and brightness < 67 then + icon = icon .. "-medium" + elseif brightness >= 67 then + icon = icon .. "-high" + end + brightness_osd_widget:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg", + Theme_config.brightness_osd.icon_color)) + end + ) + + local brightness_container = awful.popup { + widget = {}, + ontop = true, + stretch = false, + visible = false, + screen = s, + placement = function(c) awful.placement.bottom_left(c, { margins = dpi(20) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(14)) + end + } + + local hide_brightness_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + brightness_container.visible = false + end + } + + brightness_container:setup { + brightness_osd_widget, + layout = wibox.layout.fixed.horizontal + } + + capi.awesome.connect_signal( + "brightness::rerun", + function() + if capi.mouse.screen == s then + brightness_container.visible = true + if hide_brightness_osd.started then + hide_brightness_osd:again() + else + hide_brightness_osd:start() + end + end + end + ) +end diff --git a/awesome/src/modules/calendar/init.lua b/awesome/src/modules/calendar/init.lua index 2ee9f24..8c7a5c3 100644 --- a/awesome/src/modules/calendar/init.lua +++ b/awesome/src/modules/calendar/init.lua @@ -7,6 +7,7 @@ local gshape = require("gears.shape") local gcolor = require("gears.color") local gfilesystem = require("gears").filesystem local wibox = require("wibox") +local base = require("wibox.widget.base") local capi = { awesome = awesome, @@ -14,12 +15,13 @@ local capi = { } local ical_parser = require("src.tools.ical_parser")() ---local task_info = require("src.modules.calendar.task_info") +local task_info = require("src.modules.calendar.task_info") local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/calendar/" local calendar = { mt = {} } calendar.tasks = {} +calendar.calendars = {} calendar._private = {} @@ -57,6 +59,29 @@ calendar.date = { year = tonumber(os.date("%Y")) or 1970 } +--#region base widget functions +function calendar:layout(_, width, height) + if self._private.widget then + return { base.place_widget_at(self._private.widget, 0, 0, width, height) } + end +end + +function calendar:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +calendar.set_widget = base.set_widget_common + +function calendar:get_widget() + return self._private.widget +end + +--#endregion + ---Checks how many days a month has and returns the ammount. Also takes leap years into account. ---@param month number|nil ---@param year number|nil @@ -147,6 +172,33 @@ end function calendar:get_tasks() if not ical_parser or not ical_parser.VCALENDAR then return end local tasks = {} + + local function task_factory(start_date, end_date, sum, loc, des, uid, freq) + table.insert(tasks, { + date_start = { + year = start_date.y, + month = start_date.m, + day = start_date.d, + hour = start_date.hour or 0, + min = start_date.min or 0, + sec = start_date.sec or 0 + }, + date_end = { + year = end_date.y, + month = end_date.m, + day = end_date.d, + hour = end_date.hour or 0, + min = end_date.min or 0, + sec = end_date.sec or 0 + }, + summary = sum, + location = loc, + description = des, + uid = uid, + freq = freq, + }) + end + for _, cal in ipairs(ical_parser.VCALENDAR) do for _, event in ipairs(cal.VEVENT) do if not self:check_event_uid(event.UID) then @@ -158,44 +210,60 @@ function calendar:get_tasks() if event.DTEND then end_time = event.DTEND.DTEND end + + -- If there is no end time then we just set it to the start time + if not event.DTEND.DTEND then + end_time = { + year = start_time.year + 1000, + month = start_time.month, + day = start_time.day, + hour = start_time.hour, + min = start_time.min, + sec = start_time.sec + } + end -- Get repeat cases if event.RRULE then if event.RRULE.FREQ == "DAILY" then + local year_counter, month_counter, day_counter = start_time.year, start_time.month, + start_time.day + while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or + (day_counter <= event.RRULE.UNTIL.day) do + task_factory({ + y = year_counter, + m = month_counter, + d = day_counter, + hour = start_time.hour, + min = start_time.min, + sec = start_time.sec + }, { + y = year_counter, + m = month_counter, + d = day_counter, + hour = end_time.hour, + min = end_time.min, + sec = end_time.sec + }, event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ) + + day_counter = day_counter + 1 + if day_counter > calendar:get_last_day_in_month(month_counter, year_counter) then + day_counter = 1 + month_counter = month_counter + 1 + if month_counter > 12 then + month_counter = 1 + year_counter = year_counter + 1 + end + end + end elseif event.RRULE.FREQ == "WEEKLY" then local year_counter, month_counter, day_counter = start_time.year, start_time.month, start_time.day - end_time = event.RRULE.UNTIL - if not event.RRULE.UNTIL then - end_time = { - year = start_time.year + 1000, - month = start_time.month, - day = start_time.day - } - end - - while (year_counter < end_time.year) or (month_counter < end_time.month) or (day_counter <= end_time.day) do - table.insert(tasks, { - date_start = { - year = year_counter, - month = month_counter, - day = day_counter, - hour = start_time.hour or 0, - minute = start_time.min or 0, - second = start_time.sec or 0 - }, - date_end = { - year = year_counter, - month = month_counter, - day = day_counter, - hour = end_time.hour or 0, - minute = end_time.min or 0, - second = end_time.sec or 0 - }, - summary = event.SUMMARY, - location = event.LOCATION, - description = event.DESCRIPTION, - uid = event.UID - }) + while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or + (day_counter <= event.RRULE.UNTIL.day) do + task_factory({ y = year_counter, m = month_counter, d = day_counter, hour = start_time.hour, + min = start_time.min, sec = start_time.sec }, { y = year_counter, m = month_counter, + d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec }, + event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ) day_counter = day_counter + 7 local month_length = calendar:get_last_day_in_month(month_counter, year_counter) if day_counter > month_length then @@ -208,6 +276,20 @@ function calendar:get_tasks() end end elseif event.RRULE.FREQ == "MONTHLY" then + local year_counter, month_counter, day_counter = start_time.year, start_time.month, + start_time.day + while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or + (day_counter <= event.RRULE.UNTIL.day) do + task_factory({ y = year_counter, m = month_counter, d = day_counter, hour = start_time.hour, + min = start_time.min, sec = start_time.sec }, { y = year_counter, m = month_counter, + d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec }, + event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ) + month_counter = month_counter + 1 + if month_counter > 12 then + month_counter = 1 + year_counter = year_counter + 1 + end + end elseif event.RRULE.FREQ == "YEARLY" then end_time = event.RRULE.UNTIL if not event.RRULE.UNTIL then @@ -218,65 +300,32 @@ function calendar:get_tasks() } end for i = start_time.year, end_time.year, 1 do - table.insert(tasks, { - date_start = { - year = i, - month = start_time.month, - day = start_time.day, - hour = start_time.hour or 0, - minute = start_time.min or 0, - second = start_time.sec or 0 - }, - date_end = { - year = i, - month = end_time.month, - day = end_time.day, - hour = end_time.hour or 0, - minute = end_time.min or 0, - second = end_time.sec or 0 - }, - summary = event.SUMMARY, - location = event.LOCATION, - description = event.DESCRIPTION, - url = event.URL.URL, - uid = event.UID - }) + task_factory({ y = i, m = start_time.month, d = start_time.day, hour = start_time.hour, + min = start_time.min, sec = start_time.sec }, { y = i, m = end_time.month, d = end_time.day, + hour = end_time.hour, min = end_time.min, sec = end_time.sec }, event.SUMMARY, + event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ) end end -- If RRULE is empty we just add a single day event else - table.insert(tasks, { - date_start = { - year = start_time.year, - month = start_time.month, - day = start_time.day, - hour = start_time.hour or 0, - minute = start_time.min or 0, - second = start_time.sec or 0 - }, - date_end = { - year = start_time.year, - month = start_time.month, - day = start_time.day, - hour = start_time.hour or 0, - minute = start_time.min or 0, - second = start_time.sec or 0 - }, - summary = event.SUMMARY, - description = event.DESCRIPTION, - location = event.LOCATION, - url = event.URL, - uid = event.UID, - }) + task_factory({ y = start_time.year, m = start_time.month, d = start_time.day, hour = start_time.hour, + min = start_time.min, sec = start_time.sec }, { y = end_time.year, m = end_time.month, + d = end_time.day, hour = end_time.hour, min = end_time.min, sec = end_time.sec }, + event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ) end if event.VALARM then - -- send a notification 15 minutes before an event starts + -- send a notification X minutes before an event starts end end end + --table.insert(calendars, tasks) + table.insert(self.tasks, tasks) + table.insert(self.calendars, { + tasks = self.tasks, + color = cal.color + }) end - table.insert(self.tasks, tasks) end ---!Fix later, I have no idea how to calculate it and the internet has no clue either @@ -360,149 +409,91 @@ function calendar:create_calendar_widget() step = dpi(50), spacing = dpi(2) } - for _, cal in ipairs(self.tasks) do - for _, task in ipairs(cal) do - if (task.date_start.year == year) and (task.date_start.month == month) and (task.date_start.day == day) then - local tw = wibox.widget { - { - { - text = task.summary, - align = "left", - halign = "center", - font = "JetBrainsMono Nerd Font, bold 10", - widget = wibox.widget.textbox - }, - margins = dpi(2), - widget = wibox.container.margin - }, - fg = Theme_config.calendar.task.fg, - bg = Theme_config.calendar.task.bg, - shape = Theme_config.calendar.task.shape, - forced_height = dpi(20), - widget = wibox.container.background - } - --[[ local ti = task_info { - summary = task.summary, - description = task.description, - location = task.location, - url = task.url, - uid = task.uid, - date_start = task.date_start, - date_end = task.date_end, - } ]] + local function task_factory(task, bg) + return wibox.widget { + { + { + text = task.summary, + align = "left", + halign = "center", + font = "JetBrainsMono Nerd Font, bold 10", + widget = wibox.widget.textbox + }, + margins = dpi(2), + widget = wibox.container.margin + }, + fg = Theme_config.calendar.task.fg, + bg = bg, + shape = Theme_config.calendar.task.shape, + forced_height = dpi(20), + widget = wibox.container.background + } + end - local task_info_widget = wibox.widget { - { - { -- Task detail - { -- Calendar color - widget = wibox.container.background, - shape = function(cr, _, height) - gshape.rounded_rect(cr, dpi(10), height, dpi(8)) - end, - }, - { - { -- Summary - widget = wibox.widget.textbox, - text = task.summary, - valign = "center", - align = "left", - id = "summary", - }, - { -- Date long - widget = wibox.widget.textbox, - text = task.date_long, - valign = "center", - align = "right", - id = "date_long", - }, - { -- From - To - widget = wibox.widget.textbox, - text = task.from_to, - valign = "center", - align = "left", - id = "from_to", - }, - { -- Repeat information - widget = wibox.widget.textbox, - text = task.repeat_info, - valign = "center", - align = "right", - id = "repeat_info", - }, - layout = wibox.layout.fixed.vertical, - }, - layout = wibox.layout.fixed.horizontal - }, - { -- Location - { - widget = wibox.widget.imagebox, - image = gcolor.recolor_image(icondir .. "location.svg", - Theme_config.calendar.border_color), - resize = false, - valign = "center", - halign = "center", - }, - { - widget = wibox.widget.textbox, - text = task.location, - valign = "center", - align = "left", - id = "location", - }, - id = "location_container", - layout = wibox.layout.fixed.horizontal - }, - { -- Alarm - { - widget = wibox.widget.imagebox, - image = gcolor.recolor_image(icondir .. "alarm.svg", Theme_config.calendar.fg), - resize = false, - valign = "center", - halign = "center", - }, - { - widget = wibox.widget.textbox, - text = task.alarm, - valign = "center", - align = "left", - id = "alarm", - }, - id = "alarm_container", - layout = wibox.layout.fixed.horizontal - }, - id = "task_detail", - layout = wibox.layout.fixed.vertical - }, - bg = Theme_config.calendar.bg, - fg = Theme_config.calendar.fg, - shape = function(cr, _, height) - gshape.rounded_rect(cr, height, height, dpi(8)) - end, - widget = wibox.container.background, - } + for _, cal in ipairs(self.calendars) do + for _, tasks in ipairs(cal.tasks) do + for _, task in ipairs(tasks) do + if (task.date_start.year == year) and (task.date_start.month == month) and (task.date_start.day == day) then + -- Check if task if before the current date + local tw + if task.date_start.year < self.date.year or + (task.date_start.year == self.date.year and task.date_start.month < self.date.month) or + ( + task.date_start.year == self.date.year and task.date_start.month == self.date.month and + task.date_start.day < self.date.day) then + tw = task_factory(task, cal.color .. "55") + else + tw = task_factory(task, cal.color) + end - local task_popup = awful.popup { - widget = task_info_widget, - ontop = true, - visible = true, - bg = "#00000000", - x = capi.mouse.coords().x, - y = capi.mouse.coords().y, - screen = self.screen - } + local ti = task_info { + summary = task.summary, + description = task.description, + location = task.location, + url = task.url, + uid = task.uid, + date_start = task.date_start, + start_time = task.start_time, + date_end = task.date_end, + end_time = task.end_time, + freq = task.freq, + task = task, + color = cal.color, + } - tw:connect_signal("button::down", function() - --ti:toggle() - task_popup.visible = not task_popup.visible - end) + local task_popup = awful.popup { + widget = ti, + ontop = true, + visible = false, + bg = "#00000000", + x = capi.mouse.coords().x, + y = capi.mouse.coords().y, + screen = self.screen + } - Hover_signal(tw) + tw:buttons( + gtable.join( + awful.button({}, 1, function() + task_popup.x = capi.mouse.coords().x + task_popup.y = capi.mouse.coords().y + task_popup.visible = not task_popup.visible + end) + ) + ) - table.insert(tasks_layout, tw) + tw:connect_signal("mouse::leave", function() + task_popup.visible = false + end) + + Hover_signal(tw) + + table.insert(tasks_layout, tw) + end end end end + return tasks_layout end @@ -749,10 +740,11 @@ end function calendar.new(args) args = args or {} - local ret = gobject { enable_properties = true, enable_auto_signals = true } + + local ret = base.make_widget(nil, nil, { enable_properties = true }) gtable.crush(ret, calendar, true) - local calendar_widget = wibox.widget { + ret:set_widget(wibox.widget { { { { @@ -892,7 +884,7 @@ function calendar.new(args) border_strategy = "inner", fg = Theme_config.calendar.fg, shape = Theme_config.calendar.shape, - } + }) ret:get_tasks() @@ -901,109 +893,81 @@ function calendar.new(args) ret:create_weekdays_widget() ret:create_calendar_weeks_widget() - ret.widget = awful.popup { - widget = calendar_widget, - screen = args.screen, - ontop = true, - bg = "#00000000", - visible = false, - placement = function(c) awful.placement.align(c, - { position = "top_right", margins = { right = dpi(10), top = dpi(65) } }) - end - - } - - calendar_widget:get_children_by_id("add_ical")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - awful.spawn.easy_async_with_shell( - "zenity --file-selection --title='Select an ICalendar file' --file-filter='iCalendar File | *.ics'", - function(path_to_file) - path_to_file = string.gsub(path_to_file, "\n", "") - if not path_to_file then return end - ical_parser:add_calendar(path_to_file) - ret:get_tasks() - ret:create_calendar_widget() - end - ) - end) - ) - ) - - calendar_widget:get_children_by_id("add_task")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - awful.spawn.easy_async_with_shell( - "zenity --info --text='Soon TM'", - function() - - end - ) - end) - ) - ) - - calendar_widget:get_children_by_id("prev_month")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - ret.date.month = ret.date.month - 1 - if ret.date.month == 0 then - ret.date.month = 12 - ret.date.year = ret.date.year - 1 + ret:get_widget():get_children_by_id("add_ical")[1]:buttons(gtable.join( + awful.button({}, 1, function() + awful.spawn.easy_async_with_shell( + "zenity --file-selection --title='Select an ICalendar file' --file-filter='iCalendar File | *.ics'", + function(path_to_file) + path_to_file = string.gsub(path_to_file, "\n", "") + if (not path_to_file) or (path_to_file == "") then return end + ical_parser:add_calendar(path_to_file) + ret:get_tasks() + ret:create_calendar_widget() end - calendar_widget:get_children_by_id("month")[1].text = ret._private.months[ret.date.month] - calendar_widget:get_children_by_id("year")[1].text = ret.date.year - ret:create_calendar_weeks_widget() - ret:create_calendar_widget() - end) - ) - ) + ) + end) + )) + + ret:get_widget():get_children_by_id("add_task")[1]:buttons(gtable.join( + awful.button({}, 1, function() + awful.spawn.easy_async_with_shell( + "zenity --info --text='Soon TM'", + function() - calendar_widget:get_children_by_id("next_month")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - ret.date.month = ret.date.month + 1 - if ret.date.month == 13 then - ret.date.month = 1 - ret.date.year = ret.date.year + 1 end - calendar_widget:get_children_by_id("month")[1].text = ret._private.months[ret.date.month] - calendar_widget:get_children_by_id("year")[1].text = ret.date.year - ret:create_calendar_weeks_widget() - ret:create_calendar_widget() - end) - ) - ) + ) + end) + )) + + ret:get_widget():get_children_by_id("prev_month")[1]:buttons(gtable.join( + awful.button({}, 1, function() + ret.date.month = ret.date.month - 1 + if ret.date.month == 0 then + ret.date.month = 12 + ret.date.year = ret.date.year - 1 + end + ret:get_widget():get_children_by_id("month")[1].text = ret._private.months[ret.date.month] + ret:get_widget():get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + )) + + ret:get_widget():get_children_by_id("next_month")[1]:buttons(gtable.join( + awful.button({}, 1, function() + ret.date.month = ret.date.month + 1 + if ret.date.month == 13 then + ret.date.month = 1 + ret.date.year = ret.date.year + 1 + end + ret:get_widget():get_children_by_id("month")[1].text = ret._private.months[ret.date.month] + ret:get_widget():get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + )) --- Calendar switch year back - calendar_widget:get_children_by_id("prev_year")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - ret.date.year = ret.date.year - 1 - calendar_widget:get_children_by_id("year")[1].text = ret.date.year - ret:create_calendar_weeks_widget() - ret:create_calendar_widget() - end) - ) - ) + ret:get_widget():get_children_by_id("prev_year")[1]:buttons(gtable.join( + awful.button({}, 1, function() + ret.date.year = ret.date.year - 1 + ret:get_widget():get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + )) --- Calendar switch year forward - calendar_widget:get_children_by_id("next_year")[1]:buttons( - gtable.join( - awful.button({}, 1, function() - ret.date.year = ret.date.year + 1 - calendar_widget:get_children_by_id("year")[1].text = ret.date.year - ret:create_calendar_weeks_widget() - ret:create_calendar_widget() - end) - ) - ) + ret:get_widget():get_children_by_id("next_year")[1]:buttons(gtable.join( + awful.button({}, 1, function() + ret.date.year = ret.date.year + 1 + ret:get_widget():get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + )) - capi.awesome.connect_signal("calendar::toggle", function() - if capi.mouse.screen == args.screen then - ret.widget.visible = not ret.widget.visible - end - end) + return ret end function calendar.mt:__call(...) diff --git a/awesome/src/modules/calendar/task_info.lua b/awesome/src/modules/calendar/task_info.lua index 0f263fc..8144d50 100644 --- a/awesome/src/modules/calendar/task_info.lua +++ b/awesome/src/modules/calendar/task_info.lua @@ -20,15 +20,24 @@ task_info._private = {} function task_info.new(args) args = args or {} if not args.task then return end - args.screen = args.screen or awful.screen.focused() local ret = gobject {} gtable.crush(ret, task_info, true) + args.color = args.color or "#ffffff" + + local date_long_written = os.date("%A, %d. %B %Y", os.time(args.date_start)) + + local from_to = os.date("%H:%M", os.time(args.date_start)) .. " - " .. os.date("%H:%M", os.time(args.date_end)) + local task_info_widget = wibox.widget { { + { + { { -- Task detail { -- Calendar color widget = wibox.container.background, + bg = args.color, + forced_width = dpi(10), shape = function(cr, _, height) gshape.rounded_rect(cr, dpi(10), height, dpi(8)) end, @@ -36,95 +45,109 @@ function task_info.new(args) { { -- Summary widget = wibox.widget.textbox, - text = ret.summary, + text = args.summary:sub(1, -2) or "NO SUMMARY", valign = "center", - align = "left", + halign = "left", id = "summary", }, { -- Date long widget = wibox.widget.textbox, - text = ret.date_long, + text = date_long_written or "01.12.1970", valign = "center", - align = "right", + halign = "right", id = "date_long", }, { -- From - To widget = wibox.widget.textbox, - text = ret.from_to, + text = from_to or "", valign = "center", - align = "left", + halign = "left", id = "from_to", }, { -- Repeat information widget = wibox.widget.textbox, - text = ret.repeat_info, + text = args.freq or "0", valign = "center", - align = "right", + halign = "left", id = "repeat_info", + }, -- Year + { + widget = wibox.widget.textbox, + text = args.date_start.year or "1970", + valign = "center", + halign = "left", + id = "year", }, + spacing = dpi(10), layout = wibox.layout.fixed.vertical, }, + spacing = dpi(20), layout = wibox.layout.fixed.horizontal }, + widget = wibox.container.margin, + left = dpi(9) + }, { -- Location { widget = wibox.widget.imagebox, - image = gcolor.recolor_image(icondir .. "location.svg", Theme_config.calendar.task_info.location_icon_color), + image = gcolor.recolor_image(icondir .. "location.svg", args.color), resize = false, valign = "center", halign = "center", }, { widget = wibox.widget.textbox, - text = ret.location, + text = args.location:sub(1, -2) or "F303", valign = "center", - align = "left", + halign = "left", id = "location", }, + spacing = dpi(10), id = "location_container", layout = wibox.layout.fixed.horizontal }, { -- Alarm { widget = wibox.widget.imagebox, - image = gcolor.recolor_image(icondir .. "alarm.svg", Theme_config.calendar.task_info.alarm_icon_color), + image = gcolor.recolor_image(icondir .. "alarm.svg", args.color), resize = false, valign = "center", halign = "center", }, { widget = wibox.widget.textbox, - text = ret.alarm, + text = args.alarm or "NO ALARM", valign = "center", - align = "left", + halign = "left", id = "alarm", }, + spacing = dpi(10), id = "alarm_container", layout = wibox.layout.fixed.horizontal }, id = "task_detail", + spacing = dpi(15), layout = wibox.layout.fixed.vertical }, + widget = wibox.container.margin, + left = dpi(6), + right = dpi(15), + top = dpi(15), + bottom = dpi(15), + }, bg = Theme_config.calendar.task_info.bg, fg = Theme_config.calendar.task_info.fg, shape = Theme_config.calendar.task_info.shape, widget = wibox.container.background, } - ret.widget = awful.popup { - widget = task_info_widget, - ontop = true, - visible = true, - bg = "#00000000", - x = capi.mouse.coords().x, - y = capi.mouse.coords().y, - screen = args.screen - } + ret.widget = task_info_widget + return ret.widget end function task_info.mt:__call(...) - task_info.new(...) + return task_info.new(...) end return setmetatable(task_info, task_info.mt) diff --git a/awesome/src/modules/context_menu/init.lua b/awesome/src/modules/context_menu/init.lua new file mode 100644 index 0000000..6beec02 --- /dev/null +++ b/awesome/src/modules/context_menu/init.lua @@ -0,0 +1,214 @@ +--------------------------------------- +-- This is the brightness_osd module -- +--------------------------------------- +-- Awesome Libs +local awful = require("awful") +local abutton = awful.button +local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears.table") +local base = require("wibox.widget.base") +local wibox = require("wibox") +local gfilesystem = require("gears.filesystem") +local gobject = require("gears.object") +local gcolor = require("gears.color") +local gtimer = require("gears.timer") + +local capi = { + awesome = awesome, + mouse = mouse +} + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/context_menu/" + +local context_menu = { + mt = {} +} + +function context_menu:layout(_, width, height) + if self._private.widget then + return { + base.place_widget_at(self._private.widget, 0, 0, width, height) + } + end +end + +function context_menu:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +context_menu.set_widget = base.set_widget_common + +function context_menu:make_entries(wtemplate, entries, spacing) + local menu_entries = { + layout = wibox.layout.fixed.vertical, + spacing = spacing + } + + if not wtemplate then + return + end + + for _, entry in ipairs(entries) do + -- TODO: Figure out how to make a new widget from etemplate + local menu_entry = wibox.widget { + { + { + { + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "icon_role" + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + { + widget = wibox.widget.textbox, + valign = "center", + halign = "left", + id = "text_role" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + nil, + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "arrow_role" + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + layout = wibox.layout.align.horizontal + }, + margins = dpi(5), + widget = wibox.container.margin + }, + bg = Theme_config.desktop.context_menu.entry_bg, + fg = Theme_config.desktop.context_menu.entry_fg, + widget = wibox.container.background + } + + Hover_signal(menu_entry) + + menu_entry:get_children_by_id("icon_role")[1].image = entry.icon + menu_entry:get_children_by_id("text_role")[1].text = entry.name + if entry.submenu then + menu_entry:get_children_by_id("arrow_role")[1].image = + gcolor.recolor_image(icondir .. "entry.svg", Theme_config.desktop.context_menu.entry_fg) + end + gtable.crush(menu_entry, entry, true) + + menu_entry:buttons(gtable.join { + abutton({ + modifiers = {}, + button = 1, + on_release = function() + if not entry.submenu then + entry.callback() + end + self.visible = false + end + }) + }) + + if entry.submenu then + menu_entry.popup = awful.popup { + widget = self:make_entries(wtemplate, entry.submenu, spacing), + bg = Theme_config.desktop.context_menu.bg, + ontop = true, + fg = Theme_config.desktop.context_menu.fg, + border_width = Theme_config.desktop.context_menu.border_width, + border_color = Theme_config.desktop.context_menu.border_color, + shape = Theme_config.desktop.context_menu.shape, + visible = false + } + + local hide_timer = gtimer { + timeout = 0.1, + autostart = false, + single_shot = true, + callback = function() + menu_entry.popup.visible = false + end + } + + menu_entry:connect_signal("mouse::enter", function() + -- place widget right of parent + menu_entry.popup:move_next_to(capi.mouse.current_widget_geometry) + hide_timer:stop() + menu_entry.popup.visible = true + end) + menu_entry.popup:connect_signal("mouse::leave", function() + hide_timer:again() + end) + menu_entry.popup:connect_signal("mouse::enter", function() + hide_timer:stop() + end) + menu_entry:connect_signal("mouse::leave", function() + hide_timer:again() + end) + capi.awesome.connect_signal("submenu::close", function() + menu_entry.popup.visible = false + end) + end + + table.insert(menu_entries, menu_entry) + end + + return menu_entries +end + +function context_menu:toggle() + self.x = capi.mouse.coords().x + self.y = capi.mouse.coords().y + self.visible = not self.visible +end + +function context_menu.new(args) + args = args or {} + + local ret = {} + + gtable.crush(ret, context_menu, true) + + ret = awful.popup { + widget = ret:make_entries(args.widget_template, args.entries, args.spacing), + bg = Theme_config.desktop.context_menu.bg, + fg = Theme_config.desktop.context_menu.fg, + ontop = true, + border_width = Theme_config.desktop.context_menu.border_width, + border_color = Theme_config.desktop.context_menu.border_color, + shape = Theme_config.desktop.context_menu.shape, + visible = false, + x = capi.mouse.coords().x + 10, + y = capi.mouse.coords().y - 10 + } + + gtable.crush(ret, context_menu, true) + + return ret +end + +function context_menu.mt:__call(...) + return context_menu.new(...) +end + +return setmetatable(context_menu, context_menu.mt) diff --git a/awesome/src/modules/crylia_bar/center_bar.lua b/awesome/src/modules/crylia_bar/center_bar.lua index 767a7d6..e6a54fc 100644 --- a/awesome/src/modules/crylia_bar/center_bar.lua +++ b/awesome/src/modules/crylia_bar/center_bar.lua @@ -14,23 +14,6 @@ local capi = { return function(s, widgets) - local top_center = awful.popup { - screen = s, - widget = wibox.container.background, - ontop = false, - bg = Theme_config.center_bar.bg, - visible = true, - maximum_width = dpi(500), - placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(6)) - end - } - - top_center:struts { - top = dpi(55) - } - local function prepare_widgets(w) local layout = { forced_height = dpi(50), @@ -72,55 +55,53 @@ return function(s, widgets) return layout end - top_center:setup { - nil, - prepare_widgets(widgets), - nil, - layout = wibox.layout.fixed.horizontal + local top_center = awful.popup { + screen = s, + widget = prepare_widgets(widgets), + ontop = false, + bg = Theme_config.center_bar.bg, + visible = true, + maximum_width = dpi(500), + placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end } - capi.client.connect_signal( - "manage", - function(c) - if #s.selected_tag:clients() < 1 then - top_center.visible = false - else - top_center.visible = true - end - end - ) + top_center:struts { + top = dpi(55) + } - capi.client.connect_signal( - "unmanage", - function(c) - if #s.selected_tag:clients() < 1 then - top_center.visible = false - else - top_center.visible = true - end + capi.client.connect_signal("manage", function(c) + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true end - ) + end) - capi.client.connect_signal( - "property::selected", - function(c) - if #s.selected_tag:clients() < 1 then - top_center.visible = false - else - top_center.visible = true - end + capi.client.connect_signal("unmanage", function(c) + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true end - ) + end) - capi.awesome.connect_signal( - "refresh", - function(c) - if #s.selected_tag:clients() < 1 then - top_center.visible = false - else - top_center.visible = true - end + capi.client.connect_signal("property::selected", function(c) + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true end - ) + end) + + capi.awesome.connect_signal("refresh", function(c) + if #s.selected_tag:clients() < 1 then + top_center.visible = false + else + top_center.visible = true + end + end) end diff --git a/awesome/src/modules/crylia_bar/dock.lua b/awesome/src/modules/crylia_bar/dock.lua index 4b136cf..bc2f1ae 100644 --- a/awesome/src/modules/crylia_bar/dock.lua +++ b/awesome/src/modules/crylia_bar/dock.lua @@ -18,7 +18,7 @@ local json = require("src.lib.json-lua.json-lua") local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/context_menu/" -local cm = require("src.modules.context_menu") +local cm = require("src.modules.context_menu.init") return function(screen) @@ -76,7 +76,7 @@ return function(screen) for _, action in ipairs(program.actions) do table.insert(action_entries, { name = Gio.DesktopAppInfo.get_action_name(DAI, action) or "", - icon = action.icon or icondir .. "entry.svg", + icon = gears.color.recolor_image(action.icon or icondir .. "entry.svg", Theme_config.dock.cm_icon), callback = function() Gio.DesktopAppInfo.launch_action(DAI, action) end @@ -85,7 +85,7 @@ return function(screen) table.insert(action_entries, { name = "Remove from Dock", - icon = icondir .. "entry.svg", + icon = gears.color.recolor_image(icondir .. "entry.svg", Theme_config.dock.cm_icon), callback = function() local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r") if not data then @@ -111,9 +111,41 @@ return function(screen) end }) - local context_menu = cm({ - entries = action_entries - }) + local context_menu = cm { + widget_template = wibox.widget { + { + { + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "icon_role", + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + { + widget = wibox.widget.textbox, + valign = "center", + halign = "left", + id = "text_role" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + margins = dpi(5), + widget = wibox.container.margin + }, + widget = wibox.container.background, + }, + entries = action_entries, + spacing = dpi(10), + } dock_element:buttons(gears.table.join( awful.button({ @@ -131,10 +163,7 @@ return function(screen) return end -- add offset so mouse is above widget, this is so the mouse::leave event triggers always - context_menu.x = capi.mouse.coords().x - 10 - context_menu.y = capi.mouse.coords().y + 10 - context_menu.height - context_menu.visible = not context_menu.visible - cm_open = context_menu.visible + context_menu:toggle() end }) )) diff --git a/awesome/src/modules/crylia_bar/init.lua b/awesome/src/modules/crylia_bar/init.lua index 73d2c92..2066cb2 100644 --- a/awesome/src/modules/crylia_bar/init.lua +++ b/awesome/src/modules/crylia_bar/init.lua @@ -25,7 +25,7 @@ return function(s) elseif widget == "Cpu Usage" then table.insert(widget_table, require("src.widgets.cpu_info")("usage")) elseif widget == "Date" then - table.insert(widget_table, require("src.widgets.date")()) + table.insert(widget_table, require("src.widgets.date")(s)) elseif widget == "Gpu Temperature" then table.insert(widget_table, require("src.widgets.gpu_info")("temp")) elseif widget == "Gpu Usage" then @@ -52,8 +52,8 @@ return function(s) return widget_table end - if User_config.widgets then - for index, screen in ipairs(User_config.widgets) do + if User_config.crylia_bar then + for index, screen in ipairs(User_config.crylia_bar) do if index == s.index then if screen.left_bar then require("src.modules.crylia_bar.left_bar")(s, get_widgets(screen.left_bar)) diff --git a/awesome/src/modules/crylia_bar/left_bar.lua b/awesome/src/modules/crylia_bar/left_bar.lua index 4f956b4..fdad12f 100644 --- a/awesome/src/modules/crylia_bar/left_bar.lua +++ b/awesome/src/modules/crylia_bar/left_bar.lua @@ -9,25 +9,6 @@ local wibox = require("wibox") return function(s, w) - local top_left = awful.popup { - screen = s, - widget = { - - }, - ontop = false, - bg = Theme_config.left_bar.bg, - visible = true, - maximum_width = dpi(650), - placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(6)) - end - } - - top_left:struts { - top = dpi(55) - } - local function prepare_widgets(widgets) local layout = { forced_height = dpi(50), @@ -69,10 +50,22 @@ return function(s, w) return layout end - top_left:setup { - prepare_widgets(w), - nil, - nil, - layout = wibox.layout.fixed.horizontal + local top_left = awful.popup { + screen = s, + widget = prepare_widgets(w), + ontop = false, + bg = Theme_config.left_bar.bg, + visible = true, + maximum_width = dpi(650), + placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end } + + top_left:struts { + top = dpi(55) + } + + Global_config.top_struts = dpi(55) end diff --git a/awesome/src/modules/crylia_bar/right_bar.lua b/awesome/src/modules/crylia_bar/right_bar.lua index b9b959c..a4a03ad 100644 --- a/awesome/src/modules/crylia_bar/right_bar.lua +++ b/awesome/src/modules/crylia_bar/right_bar.lua @@ -9,22 +9,6 @@ local wibox = require("wibox") return function(s, w) - local top_right = awful.popup { - widget = wibox.container.background, - ontop = false, - bg = Theme_config.right_bar.bg, - visible = true, - screen = s, - placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(6)) - end - } - - top_right:struts { - top = dpi(55) - } - local function prepare_widgets(widgets) local layout = { forced_height = dpi(50), @@ -66,10 +50,21 @@ return function(s, w) return layout end - top_right:setup { - nil, - nil, - prepare_widgets(w), - layout = wibox.layout.align.horizontal + local top_right = awful.popup { + widget = prepare_widgets(w), + ontop = false, + bg = Theme_config.right_bar.bg, + visible = true, + screen = s, + placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end } + + top_right:struts { + top = dpi(55) + } + + Global_config.top_struts = top_right end diff --git a/awesome/src/modules/crylia_wibox/init.lua b/awesome/src/modules/crylia_wibox/init.lua new file mode 100644 index 0000000..a85e278 --- /dev/null +++ b/awesome/src/modules/crylia_wibox/init.lua @@ -0,0 +1,129 @@ +-------------------------------------------------------------------------------------------------------------- +-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen -- +-------------------------------------------------------------------------------------------------------------- +local wibox = require("wibox") +local dpi = require("beautiful").xresources.apply_dpi +local gshape = require("gears.shape") + +return function(s) + ---Lookup function to return the widget from its easy name string + ---@param widgets table + ---@return widget + local function get_widgets(widgets) + local widget_table = {} + if widgets then + for _, widget in ipairs(widgets) do + if widget == "Audio" then + table.insert(widget_table, require("src.widgets.audio")(s)) + elseif widget == "Battery" then + table.insert(widget_table, require("src.widgets.battery")(User_config.battery_kind)) + elseif widget == "Bluetooth" then + table.insert(widget_table, require("src.widgets.bluetooth")()) + elseif widget == "Clock" then + table.insert(widget_table, require("src.widgets.clock")()) + elseif widget == "Cpu Frequency" then + table.insert(widget_table, require("src.widgets.cpu_info")("freq", User_config.cpu_frequency)) + elseif widget == "Cpu Temperature" then + table.insert(widget_table, require("src.widgets.cpu_info")("temp")) + elseif widget == "Cpu Usage" then + table.insert(widget_table, require("src.widgets.cpu_info")("usage")) + elseif widget == "Date" then + table.insert(widget_table, require("src.widgets.date")()) + elseif widget == "Gpu Temperature" then + table.insert(widget_table, require("src.widgets.gpu_info")("temp")) + elseif widget == "Gpu Usage" then + table.insert(widget_table, require("src.widgets.gpu_info")("usage")) + elseif widget == "Keyboard Layout" then + table.insert(widget_table, require("src.widgets.kblayout")(s)) + elseif widget == "Tiling Layout" then + table.insert(widget_table, require("src.widgets.layout_list")()) + elseif widget == "Network" then + table.insert(widget_table, require("src.widgets.network")()) + elseif widget == "Power Button" then + table.insert(widget_table, require("src.widgets.power")()) + elseif widget == "Ram Usage" then + table.insert(widget_table, require("src.widgets.ram_info")()) + elseif widget == "Systray" then + table.insert(widget_table, require("src.widgets.systray")(s)) + elseif widget == "Taglist" then + table.insert(widget_table, require("src.widgets.taglist")(s)) + elseif widget == "Tasklist" then + table.insert(widget_table, require("src.widgets.tasklist")(s)) + end + end + end + return widget_table + end + + if User_config.crylia_wibox then + for index, screen in ipairs(User_config.crylia_wibox) do + if index == s.index then + local function prepare_widgets(widgets) + local layout = { + forced_height = dpi(50), + layout = wibox.layout.fixed.horizontal + } + for i, widget in pairs(widgets) do + if i == 1 then + table.insert(layout, + { + widget, + left = dpi(6), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + elseif i == #widgets then + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + else + table.insert(layout, + { + widget, + left = dpi(3), + right = dpi(3), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + }) + end + end + return layout + end + + local w = wibox { + widget = { + prepare_widgets(get_widgets(screen.left_bar)), + prepare_widgets(get_widgets(screen.center_bar)), + prepare_widgets(get_widgets(screen.right_bar)), + layout = wibox.layout.align.horizontal, + }, + visible = true, + x = 0, + y = 1035, + type = "desktop", + height = dpi(55), + width = 1920, + bg = "#212121", + shape = function(cr, width, height) + gshape.partially_rounded_rect(cr, width, height, true, true, false, false, 8) + end, + } + + w:struts { + bottom = dpi(55) + } + + Global_config.bottom_struts = dpi(55) + end + end + end +end diff --git a/awesome/src/modules/desktop/context_menu.lua b/awesome/src/modules/desktop/context_menu.lua new file mode 100644 index 0000000..f276b02 --- /dev/null +++ b/awesome/src/modules/desktop/context_menu.lua @@ -0,0 +1,54 @@ +local base = require("wibox.widget.base") +local awful = require("awful") +local gtable = require("gears.table") +local gfilesystem = require("gears.filesystem") +local gcolor = require("gears.color") +local wibox = require("wibox") +local dpi = require("beautiful").xresources.apply_dpi +local gobject = require("gears.object") + + +local cm = require("src.modules.context_menu.init") + +local capi = { + awesome = awesome +} + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/" + +local context_menu = { mt = {} } +context_menu._private = {} + +function context_menu:toggle() + self._private.popup.x = mouse.coords().x - 10 + self._private.popup.y = mouse.coords().y - 10 + self._private.popup.visible = not self._private.popup.visible +end + +function context_menu.new(args) + args = args or {} + + local ret = gobject {} + gtable.crush(ret, context_menu, true) + + + + capi.awesome.connect_signal("context_menu:show", function() + ret:toggle() + mousegrabber.run(function() + if mouse.current_wibox ~= ret._private.popup then + ret:toggle() + return false + end + return true + end, nil) + end) + + return w +end + +function context_menu.mt:__call(...) + return context_menu.new(...) +end + +return setmetatable(context_menu, context_menu.mt) diff --git a/awesome/src/modules/desktop/desktop.lua b/awesome/src/modules/desktop/desktop.lua new file mode 100644 index 0000000..658c8c0 --- /dev/null +++ b/awesome/src/modules/desktop/desktop.lua @@ -0,0 +1,605 @@ +local base = require("wibox.widget.base") +local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears.table") +local gshape = require("gears.shape") +local grid = require("wibox.layout.grid") +local wibox = require("wibox") +local abutton = require("awful.button") +local awful = require("awful") +local gcolor = require("gears.color") +local json = require("src.lib.json-lua.json-lua") +local gfilesystem = require("gears.filesystem") +local Gio = require("lgi").Gio + +local element = require("src.modules.desktop.element") +local cm = require("src.modules.context_menu.init") + +local capi = { + mouse = mouse, + awesome = awesome +} + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/" + +local desktop = { mt = {} } + +function desktop:save_layout() + local layout = {} + + local dir = gfilesystem.get_configuration_dir() .. "src/config/files/desktop/icons/" + if not gfilesystem.dir_readable(dir) then + gfilesystem.make_directories(dir) + end + + for i, widget in ipairs(self.widget.mrgn.grid.children) do + local pos = self.widget.mrgn.grid:get_widget_position(widget) + + layout[i] = { + row = pos.row, + col = pos.col, + widget = { + icon = widget.icon, + label = widget:get_children_by_id("text_role")[1].text, + exec = widget.exec, + icon_size = widget.icon_size + } + } + end + + local dir = gfilesystem.get_configuration_dir() .. "src/config" + gfilesystem.make_directories(dir) + if not gfilesystem.file_readable(dir .. "/desktop.json") then + os.execute("touch " .. dir .. "/desktop.json") + end + local handler = io.open(dir .. "/desktop.json", "w") + if not handler then return end + + handler:write(json:encode(layout)) + handler:close() +end + +function desktop:load_layout() + local dir = gfilesystem.get_configuration_dir() .. "src/config" + if not gfilesystem.file_readable(dir .. "/desktop.json") then + return + end + local handler = io.open(dir .. "/desktop.json", "r") + if not handler then return end + + local layout = json:decode(handler:read("*all")) + handler:close() + if not layout then return end + for i, value in pairs(layout) do + self:add_element(value.widget, { x = value.row, y = value.col }) + end +end + +function desktop:get_element_at(x, y) + return self.widget.mrgn.grid:get_widgets_at(x, y)[1] +end + +function desktop:add_desktop_file(app_info) + self:add_element({ + icon = app_info.icon, + label = app_info.label, + exec = app_info.exec, + icon_size = dpi(96), + desktop_file = app_info.desktop_file, + parent = self.widget.mrgn.grid, + }) +end + +--[[ + Removes a given widget and returns it +]] +function desktop:remove_element(e) + return (self.widget.mrgn.grid:remove(e) and e) or nil +end + +function desktop:get_grid_index_at(y, x) + local col, row = 1, 1 + + local width = dpi(96) * 1.75 * (4 / 3) + local height = dpi(96) * 1.75 + local spacing = dpi(10) + + while width * col + spacing * (col - 1) < x do + col = col + 1 + end + while height * row + spacing * (row - 1) < y do + row = row + 1 + end + + return col, row +end + +---Main function to add an element to the desktop +---it will automatically place it on an empty spot and save it +---@param args table widget arguments +---@param pos table|nil {x = , y = } +function desktop:add_element(args, pos) + -- add into next available position + local x, y = self.widget.mrgn.grid:get_next_empty() + + if pos then + x = pos.x + y = pos.y + end + + local e = element { + icon = args.icon, + label = args.label, + exec = args.exec, + icon_size = args.icon_size, + desktop_file = args.desktop_file, + parent = args.parent + } + + local cm_popup = cm { + widget_template = wibox.widget { + { + { + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "icon_role", + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + { + widget = wibox.widget.textbox, + valign = "center", + halign = "left", + id = "text_role" + }, + layout = wibox.layout.fixed.horizontal + }, + widget = wibox.container.margin + }, + widget = wibox.container.background, + }, + spacing = dpi(10), + entries = { + { + name = "Open with", + icon = gcolor.recolor_image(icondir .. "launch.svg", Theme_config.desktop.context_menu.icon_color), + submenu = { + --!TODO: Fetch programs and add them as entries + } + }, + { + name = "Copy", + icon = gcolor.recolor_image(icondir .. "copy.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + end + }, + { + name = "Cut", + icon = gcolor.recolor_image(icondir .. "cut.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + end + }, + { + name = "Rename", + icon = gcolor.recolor_image(icondir .. "edit.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + end + }, + { + name = "Remove", + icon = gcolor.recolor_image(icondir .. "delete.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + self:remove_element(e) + self:save_layout() + end + }, + { + name = "Actions", + icon = gcolor.recolor_image(icondir .. "dots-vertical.svg", Theme_config.desktop.context_menu.icon_color), + submenu = { + -- TODO: fetch actions from desktop file + } + }, + } + } + + cm_popup:connect_signal("mouse::leave", function() + cm_popup.visible = false + end) + + -- While the mouse is down, remove the element from the grid and add it to manual then move it + -- until the mouse is released and then add it back to the grid. + e:connect_signal("button::press", function(_, _, _, b) + local start_pos = mouse.coords() + + if not mousegrabber.isrunning() then + + local width = args.icon_size * 1.75 * (4 / 3) + local height = args.icon_size * 1.75 + + local dnd_widget = element { + icon = args.icon, + label = args.label, + on_click = args.on_click, + icon_size = args.icon_size, + parent = args.parent, + width = width, + height = height, + } + dnd_widget.visible = false + + dnd_widget:get_children_by_id("icon_role")[1].opacity = 0.6 + + local xp, yp = capi.mouse.coords() + dnd_widget.point = { x = xp, y = yp } + + local old_pos = self.widget.mrgn.grid:get_widget_position(e) + self.widget.manual:add(dnd_widget) + mousegrabber.run(function(m) + if (math.abs(m.x - start_pos.x) > 10 or + math.abs(m.x - start_pos.x) < -10 or + math.abs(m.y - start_pos.y) > 10 or + math.abs(m.y - start_pos.y) < -10) and + m.buttons[1] then + self:remove_element(e) + dnd_widget.visible = true + dnd_widget.bg = gcolor("#0ffff088") + dnd_widget.border_color = gcolor("#0ffff0") + self.widget.manual:move_widget(dnd_widget, { x = m.x - dnd_widget.width / 2, y = m.y - dnd_widget.height / 2 }) + end + + if not m.buttons[1] then + if b == 1 then + dnd_widget.bg = gcolor("#0ffff088") + dnd_widget.border_color = gcolor("#0ffff0") + + if dnd_widget.visible then + dnd_widget.visible = false + + local np_x, np_y = self:get_grid_index_at(m.y, m.x) + if not self.widget.mrgn.grid:get_widgets_at(np_y, np_x) then + self.widget.mrgn.grid:add_widget_at(e, np_y, np_x) + self:save_layout() + else + self.widget.mrgn.grid:add_widget_at(e, old_pos.row, old_pos.col) + end + else + Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(e.exec, nil, 0)) + self.widget.manual:reset() + end + mousegrabber.stop() + elseif b == 3 then + cm_popup:toggle() + mousegrabber.stop() + end + end + + return m.buttons[1] + end, "left_ptr") + end + end) + + self.widget.mrgn.grid:add_widget_at(e, x, y) + self:save_layout() +end + +function desktop:draw_selector() + local start_pos = mouse.coords() + if not mousegrabber.isrunning() then + local selector = wibox.widget { + widget = wibox.container.background, + bg = gcolor("#0ffff088"), + border_color = gcolor("#0ffff0"), + border_width = dpi(2), + width = 100, + height = 100, + visible = true, + shape = function(cr, w, h) + gshape.rounded_rect(cr, w, h, dpi(10)) + end + } + + local coords = capi.mouse.coords() + selector.point = { x = coords.x, y = coords.y } + self.widget.manual:add(selector) + mousegrabber.run(function(m) + if m.buttons[1] then + selector.visible = true + end + if not m.buttons[1] then + mousegrabber.stop() + selector.visible = false + self.widget.manual:reset() + end + end, "left_ptr") + end +end + +function desktop:add_xdg() + self:add_element({ + icon = "/usr/share/icons/Papirus-Dark/96x96/places/user-trash.svg", + label = "Papierkorb", + exec = "nautilus trash:/", + icon_size = 96, + }) + + self:add_element({ + icon = "/usr/share/icons/Papirus-Dark/96x96/places/user-home.svg", + label = "Persönlicher Ordner", + exec = "nautilus file:/home/crylia", + icon_size = 96, + }) +end + +function desktop.new(args) + args = args or {} + + args.screen = args.screen or awful.screen.focused() + + local icon_size = args.icon_size or dpi(96) + + -- calculate the row and column count based on the screen size and icon size and aspect ratio of 16:9 + local screen_width = awful.screen.focused().geometry.width + local screen_height = awful.screen.focused().geometry.height + local aspect_ratio = 4 / 3 + + local cols = math.floor(screen_width / (icon_size * 1.75 * aspect_ratio)) + local rows = math.floor((screen_height - (dpi(75 + 95))) / (icon_size * 1.75)) + + --[[ + The wibox has a stacked layout with a manual layout over a grid. + + stacked + manual + grid + + manual: For positioning the dragged element since this layout allows for arbitrary positioning. + grid: For positioning the elements in a grid. + ]] + local w = wibox { + ontop = false, + visible = true, + type = "desktop", + input_passthrough = false, + x = 0, + y = 0, + bg = gcolor.transparent, + width = 1920, + height = 1080, + screen = args.screen, + widget = wibox.widget { + { + { + layout = grid, + homogeneous = true, + spacing = dpi(10), + expand = true, + orientation = "horizontal", + forced_num_cols = cols, + forced_num_rows = rows, + id = "grid", + }, + widget = wibox.container.margin, + left = dpi(10), + right = dpi(10), + top = dpi(75), + bottom = dpi(95), + id = "mrgn" + }, + { + layout = wibox.layout.manual, + id = "manual", + }, + layout = wibox.layout.stack, + } + } + + local cm_popup = cm { + widget_template = wibox.widget { + { + { + { + { + widget = wibox.widget.imagebox, + resize = true, + valign = "center", + halign = "center", + id = "icon_role", + }, + widget = wibox.container.constraint, + stragety = "exact", + width = dpi(24), + height = dpi(24), + id = "const" + }, + { + widget = wibox.widget.textbox, + valign = "center", + halign = "left", + id = "text_role" + }, + layout = wibox.layout.fixed.horizontal + }, + widget = wibox.container.margin + }, + widget = wibox.container.background, + }, + spacing = dpi(10), + entries = { + { + name = "Create new", + icon = gcolor.recolor_image(icondir .. "file_add.svg", Theme_config.desktop.context_menu.icon_color), + submenu = { + { + name = "Folder", + icon = gcolor.recolor_image(icondir .. "folder.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + --create a new folder and if it exists add a number to the end + local folder_name = "New folder" + local folder_path = os.getenv("HOME") .. "/Desktop/" .. folder_name + local i = 1 + while gfilesystem.dir_readable(folder_path) do + folder_name = "New folder " .. "(" .. i .. ")" + folder_path = os.getenv("HOME") .. "/Desktop/" .. folder_name + i = i + 1 + end + gfilesystem.make_directories(folder_path) + w:add_element({ + icon = "/usr/share/icons/Papirus-Dark/24x24/places/folder.svg", + label = folder_name, + exec = "nautilus file:\"" .. folder_path .. "\"", + icon_size = icon_size, + }) + end + }, + { + name = "File", + icon = gcolor.recolor_image(icondir .. "file.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + --create new text file and if it exists add a number to the end + local file_name = "New file.txt" + local file_path = os.getenv("HOME") .. "/Desktop/" .. file_name + local i = 1 + while gfilesystem.file_readable(file_path) do + file_name = "New file " .. "(" .. i .. ")" + file_path = os.getenv("HOME") .. "/Desktop/" .. file_name + i = i + 1 + end + awful.spawn.with_shell("touch " .. file_path) + w:add_element({ + icon = "/usr/share/icons/Papirus-Dark/24x24/mimetypes/text-plain.svg", + label = file_name, + exec = "xdg-open " .. file_path, + icon_size = icon_size, + }) + end + } + } + }, + { + name = "Terminal", + icon = gcolor.recolor_image(icondir .. "terminal.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.terminal) + end + }, + { + name = "Web Browser", + icon = gcolor.recolor_image(icondir .. "web_browser.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.web_browser) + end + }, + { + name = "File Manager", + icon = gcolor.recolor_image(icondir .. "file_manager.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.file_manager) + end + }, + { + name = "Text Editor", + icon = gcolor.recolor_image(icondir .. "text_editor.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.text_editor) + end + }, + { + name = "Music Player", + icon = gcolor.recolor_image(icondir .. "music_player.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.music_player) + end + }, + { + name = "Applications", + icon = gcolor.recolor_image(icondir .. "application.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + end + }, + { + name = "GTK Settings", + icon = gcolor.recolor_image(icondir .. "gtk_settings.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.gtk_settings) + end + }, + { + name = "Energy Settings", + icon = gcolor.recolor_image(icondir .. "energy_settings.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.energy_manager) + end + }, + { + name = "Screen Settings", + icon = gcolor.recolor_image(icondir .. "screen_settings.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + awful.spawn(User_config.screen_settings) + end + }, + { + name = "Reload Awesome", + icon = gcolor.recolor_image(icondir .. "refresh.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + capi.awesome.restart() + end + }, + { + name = "Quit", + icon = gcolor.recolor_image(icondir .. "quit.svg", Theme_config.desktop.context_menu.icon_color), + callback = function() + capi.awesome.quit() + end + }, + --cm_awesome + } + } + + w.widget.manual:buttons( + gtable.join( + awful.button( + {}, + 1, + function() + cm_popup.visible = false + if capi.mouse.current_widgets[4] == w.widget.manual then + --w:draw_selector() + end + end + ), + awful.button( + {}, + 3, + function() + if capi.mouse.current_widgets[4] == w.widget.manual then + cm_popup:toggle() + end + end + ) + ) + ) + + gtable.crush(w, desktop, true) + + w:load_layout() + + capi.awesome.connect_signal("desktop::add_to_desktop", function(args2) + w:add_desktop_file(args2) + end) + + return w +end + +function desktop.mt:__call(...) + return desktop.new(...) +end + +return setmetatable(desktop, desktop.mt) diff --git a/awesome/src/modules/desktop/element.lua b/awesome/src/modules/desktop/element.lua new file mode 100644 index 0000000..569f320 --- /dev/null +++ b/awesome/src/modules/desktop/element.lua @@ -0,0 +1,119 @@ +local base = require("wibox.widget.base") +local wibox = require("wibox") +local gtable = require("gears.table") +local dpi = require("beautiful").xresources.apply_dpi +local gshape = require("gears.shape") +local gfilesystem = require("gears.filesystem") +local gcolor = require("gears.color") +local abutton = require("awful.button") + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/" + +local capi = { + mouse = mouse +} + +local element = { mt = {} } + +function element:layout(_, width, height) + if self._private.widget then + return { base.place_widget_at(self._private.widget, 0, 0, width, height) } + end +end + +function element:fit(context, width, height) + local w, h = 0, 0 + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width, height) + end + return w, h +end + +function element:get_widget() + return self._private.widget +end + +function element:on_hover() + self:connect_signal("mouse::enter", function() + self.bg = "#0ffff033" + self.border_color = "#0ffff099" + end) + + self:connect_signal("mouse::leave", function() + self.bg = gcolor.transparent + self.border_color = gcolor.transparent + end) + + self:connect_signal("button::press", function() + self.bg = "#0ffff088" + self.border_color = "#0ffff0dd" + end) + + self:connect_signal("button::release", function() + self.bg = "#0ffff033" + self.border_color = "#0ffff099" + end) +end + +function element.new(args) + args = args or {} + + local w = base.make_widget_from_value(wibox.widget { + { + { + { + { + image = args.icon, + resize = true, + clip_shape = gshape.rounded_rect, + valign = "center", + halign = "center", + id = "icon_role", + widget = wibox.widget.imagebox + }, + strategy = "exact", + height = args.icon_size, + width = args.icon_size, + widget = wibox.container.constraint + }, + { + text = args.label, + id = "text_role", + valign = "center", + halign = "center", + widget = wibox.widget.textbox + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical + }, + widget = wibox.container.place, + valign = "center", + halign = "center" + }, + fg = "#ffffff", + bg = gcolor.transparent, + border_color = gcolor.transparent, + border_width = dpi(2), + shape = gshape.rounded_rect, + forced_width = args.width, + forced_height = args.height, + width = args.width, + height = args.height, + exec = args.exec, + icon_size = args.icon_size, + icon = args.icon, + widget = wibox.container.background + }) + + gtable.crush(w, element, true) + + w:on_hover() + + return w +end + +function element.mt:__call(...) + return element.new(...) +end + +return setmetatable(element, element.mt) diff --git a/awesome/src/modules/init.lua b/awesome/src/modules/init.lua index 8b4d8f0..d2c01fa 100644 --- a/awesome/src/modules/init.lua +++ b/awesome/src/modules/init.lua @@ -17,16 +17,20 @@ awful.screen.connect_for_each_screen( User_config.layouts[1] ) - require("src.modules.powermenu")(s) - require("src.modules.volume_osd")(s) - require("src.modules.brightness_osd")(s) + require("src.modules.desktop.context_menu") { screen = s } + require("src.modules.desktop.desktop") { screen = s } + require("src.modules.powermenu.powermenu")(s) + require("src.modules.audio.volume_osd") { screen = s } + --require("src.modules.audio.volume_controller") { screen = s } + require("src.modules.brightness.brightness_osd")(s) require("src.modules.bluetooth.init") { screen = s } - require("src.modules.titlebar") - require("src.modules.volume_controller")(s) + require("src.modules.titlebar.titlebar") require("src.modules.crylia_bar.init")(s) + --require("src.modules.crylia_wibox.init")(s) require("src.modules.notification-center.init")(s) require("src.modules.window_switcher.init")(s) - require("src.modules.application_launcher.init")(s) - require("src.modules.calendar.init") { screen = s } + require("src.modules.application_launcher.init") { screen = s } + --require("src.modules.calendar.init") { screen = s } + require("src.modules.network_controller.init") { screen = s } end ) diff --git a/awesome/src/modules/network_controller/access_point.lua b/awesome/src/modules/network_controller/access_point.lua new file mode 100644 index 0000000..3f00e85 --- /dev/null +++ b/awesome/src/modules/network_controller/access_point.lua @@ -0,0 +1,168 @@ +------------------------------------ +-- This is the network controller -- +------------------------------------ + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears").table +local gfilesystem = require("gears").filesystem +local gobject = require("gears").object +local gcolor = require("gears").color +local wibox = require("wibox") + +local ap_form = require("src.modules.network_controller.ap_form") + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network/" + +local access_point = { mt = {} } + +access_point.connected = false + +function access_point.new(args) + args = args or {} + + if not args.access_point then return end + + local ret = gobject { enable_properties = true, enable_auto_signals = true } + gtable.crush(ret, access_point, true) + + local strength = args.access_point.strength or 0 + + --normalize strength between 1 and 4 + strength = math.floor(strength / 25) + 1 + + local icon = "wifi-strength-" .. strength .. ".svg" + + local bg, fg, icon_color = Theme_config.network_manager.access_point.bg, Theme_config.network_manager.access_point.fg, + Theme_config.network_manager.access_point.icon_color + + if args.active == args.access_point.access_point_path then + bg, fg, icon_color = Theme_config.network_manager.access_point.fg, Theme_config.network_manager.access_point.bg, + Theme_config.network_manager.access_point.icon_color2 + end + + local ap_widget = wibox.widget { + { + { + { + { + { + image = gcolor.recolor_image( + icondir .. icon, icon_color), + id = "icon", + resize = true, + valign = "center", + halign = "center", + forced_width = dpi(24), + forced_height = dpi(24), + widget = wibox.widget.imagebox + }, + id = "icon_container", + strategy = "max", + width = dpi(24), + height = dpi(24), + widget = wibox.container.constraint + }, + { + { + { + text = args.access_point.ssid or args.access_point.hw_address or "Unknown", + id = "alias", + widget = wibox.widget.textbox + }, + { + text = "Connecting...", + id = "connecting", + visible = false, + font = User_config.font.specify .. ", regular 10", + widget = wibox.widget.textbox + }, + id = "alias_container", + layout = wibox.layout.fixed.horizontal + }, + width = dpi(260), + height = dpi(40), + strategy = "max", + widget = wibox.container.constraint + }, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal + }, + { -- Spacing + forced_width = dpi(10), + widget = wibox.container.background + }, + { + { + { + { + id = "con", + resize = false, + valign = "center", + halign = "center", + forced_width = dpi(24), + forced_height = dpi(24), + widget = wibox.widget.imagebox + }, + id = "place", + strategy = "max", + width = dpi(24), + height = dpi(24), + widget = wibox.container.constraint + }, + id = "margin", + margins = dpi(2), + widget = wibox.container.margin + }, + id = "margin0", + margin = dpi(5), + widget = wibox.container.margin + }, + id = "device_layout", + layout = wibox.layout.align.horizontal + }, + id = "device_margin", + margins = dpi(5), + widget = wibox.container.margin + }, + bg = bg, + fg = fg, + border_color = Theme_config.network_manager.access_point.border_color, + border_width = Theme_config.network_manager.access_point.border_width, + id = "background", + shape = Theme_config.network_manager.access_point.device_shape, + device = ret.access_point, + widget = wibox.container.background + } + + ap_form { screen = args.screen, SSID = args.access_point.ssid } + + ap_widget:buttons( + gtable.join( + awful.button( + {}, + 1, + nil, + function() + ap_form:popup_toggle() + end + ) + ) + ) + + ap_widget:get_children_by_id("con")[1].image = gcolor.recolor_image( + icondir .. "link.svg", icon_color) + + Hover_signal(ap_widget) + + ret.widget = ap_widget + + return ret +end + +function access_point.mt:__call(...) + return access_point.new(...) +end + +return setmetatable(access_point, access_point.mt) diff --git a/awesome/src/modules/network_controller/ap_form.lua b/awesome/src/modules/network_controller/ap_form.lua new file mode 100644 index 0000000..db736dc --- /dev/null +++ b/awesome/src/modules/network_controller/ap_form.lua @@ -0,0 +1,262 @@ +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears.table") +local gobject = require("gears.object") +local gcolor = require("gears.color") +local gshape = require("gears.shape") +local gfilesystem = require("gears.filesystem") +local wibox = require("wibox") + +local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network/" + +local capi = { + awesome = awesome, + mousegrabber = mousegrabber +} + +local ap_form = { mt = {} } +ap_form._private = {} + +ap_form.settigns_form = { + ssid = awful.widget.inputbox { + widget_template = wibox.template { + widget = wibox.widget { + { + { + { + widget = wibox.widget.textbox, + halign = "left", + valign = "center", + id = "text_role", + }, + widget = wibox.container.margin, + margins = 5, + id = "marg" + }, + widget = wibox.container.constraint, + strategy = "exact", + width = 400, + height = 50, + id = "const" + }, + widget = wibox.container.background, + bg = "#212121", + fg = "#F0F0F0", + border_color = "#414141", + border_width = 2, + shape = gshape.rounded_rect, + forced_width = 300, + forced_height = 50, + }, + update_callback = function(template_widget, args) + template_widget.widget.const.marg.text_role.markup = args.text + end + } + }, + password = awful.widget.inputbox { + widget_template = wibox.template { + widget = wibox.widget { + { + { + { + widget = wibox.widget.textbox, + halign = "left", + valign = "center", + id = "text_role", + }, + widget = wibox.container.margin, + margins = 5, + id = "marg" + }, + widget = wibox.container.constraint, + strategy = "exact", + width = 400, + height = 50, + id = "const" + }, + widget = wibox.container.background, + bg = "#212121", + fg = "#F0F0F0", + border_color = "#414141", + border_width = 2, + shape = gshape.rounded_rect, + forced_width = 300, + forced_height = 50, + }, + update_callback = function(template_widget, args) + template_widget.widget.const.marg.text_role.markup = args.text + end + } + }, +} + +function ap_form:popup_toggle() + self._private.popup.visible = not self._private.popup.visible +end + +function ap_form.new(args) + args = args or {} + args.screen = args.screen or awful.screen.preferred() + local ret = gobject {} + ret._private = {} + gtable.crush(ret, ap_form, true) + + gtable.crush(ret, args) + + ret._private.popup = awful.popup { + widget = { + { -- Header + { + nil, + { + { + widget = wibox.widget.textbox, + text = args.SSID, + halign = "center", + valign = "center", + }, + widget = wibox.container.margin, + margins = dpi(5) + }, + { -- Close button + { + { + widget = wibox.widget.imagebox, + image = gcolor.recolor_image(icondir .. "close.svg", Theme_config.network_manager.form.icon_fg), + resize = false, + valign = "center", + halign = "center", + }, + widget = wibox.container.margin, + }, + widget = wibox.container.background, + id = "close_button", + bg = Theme_config.network_manager.form.close_bg + }, + layout = wibox.layout.align.horizontal + }, + widget = wibox.container.background, + bg = Theme_config.network_manager.form.header_bg, + fg = Theme_config.network_manager.form.header_fg, + }, + { -- Form + { -- SSID + { + widget = wibox.widget.textbox, + text = "SSID", + halign = "center", + valign = "center" + }, + nil, + -- Change to inputtextbox container + ret.settigns_form.ssid, + layout = wibox.layout.align.horizontal + }, + { -- Password + { + widget = wibox.widget.textbox, + text = "Password", + halign = "center", + valign = "center" + }, + nil, + -- Change to inputtextbox container + ret.settigns_form.password, + layout = wibox.layout.align.horizontal + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical + }, + { -- Actions + { -- Auto connect + { + { + checked = false, + shape = Theme_config.network_manager.form.checkbox_shape, + color = Theme_config.network_manager.form.checkbox_bg, + check_color = Theme_config.network_manager.form.checkbox_fg, + check_border_color = Theme_config.network_manager.form.check_border_color, + check_border_width = Theme_config.network_manager.form.check_border_width, + widget = wibox.widget.checkbox + }, + widget = wibox.container.constraint, + strategy = "exact", + width = dpi(30), + height = dpi(30) + }, + { + widget = wibox.widget.textbox, + text = "Auto connect", + halign = "center", + valign = "center" + }, + layout = wibox.layout.fixed.horizontal + }, + nil, + { -- Connect + { + { + widget = wibox.widget.textbox, + text = "Connect", + halign = "center", + valign = "center" + }, + widget = wibox.container.background, + bg = Theme_config.network_manager.form.button_bg, + fg = Theme_config.network_manager.form.button_fg, + }, + widget = wibox.container.margin, + margins = dpi(10), + }, + layout = wibox.layout.align.horizontal + }, + layout = wibox.layout.align.vertical + }, + placement = awful.placement.centered, + ontop = true, + visible = false, + width = dpi(600), + height = dpi(400), + bg = Theme_config.network_manager.form.bg, + fg = Theme_config.network_manager.form.fg, + shape = Theme_config.network_manager.form.shape, + type = "dialog", + screen = args.screen, + } + + ret._private.popup.widget:get_children_by_id("close_button")[1]:connect_signal("button::press", function() + ret:popup_toggle() + end) + + ret.settigns_form.ssid:connect_signal( + "submit", + function(text) + end + ) + + ret.settigns_form.ssid:connect_signal( + "stopped", + function() + end + ) + + ret.settigns_form.password:connect_signal( + "submit", + function(text) + end + ) + + ret.settigns_form.password:connect_signal( + "stopped", + function() + end + ) + + return ret +end + +function ap_form.mt:__call(...) + return ap_form.new(...) +end + +return setmetatable(ap_form, ap_form.mt) diff --git a/awesome/src/modules/network_controller/init.lua b/awesome/src/modules/network_controller/init.lua index d6af1ed..175806c 100644 --- a/awesome/src/modules/network_controller/init.lua +++ b/awesome/src/modules/network_controller/init.lua @@ -4,113 +4,657 @@ -- Awesome Libs local awful = require("awful") +local dbus_proxy = require("dbus_proxy") local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears").table +local gtimer = require("gears").timer +local gshape = require("gears").shape +local gobject = require("gears").object +local gcolor = require("gears").color local gears = require("gears") +local lgi = require("lgi") local wibox = require("wibox") +local NM = require("lgi").NM + local rubato = require("src.lib.rubato") +local access_point = require("src.modules.network_controller.access_point") + local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/network/" -return function(s) +local capi = { + awesome = awesome, +} - local function get_connected_network() +local network = { mt = {} } +network.access_points = { layout = wibox.layout.fixed.vertical } + +network.NMState = { + UNKNOWN = 0, + ASLEEP = 10, + DISCONNECTED = 20, + DISCONNECTING = 30, + CONNECTING = 40, + CONNECTED_LOCAL = 50, + CONNECTED_SITE = 60, + CONNECTED_GLOBAL = 70, +} + +network.DeviceType = { + ETHERNET = 1, + WIFI = 2 +} + +network.DeviceState = { + UNKNOWN = 0, + UNMANAGED = 10, + UNAVAILABLE = 20, + DISCONNECTED = 30, + PREPARE = 40, + CONFIG = 50, + NEED_AUTH = 60, + IP_CONFIG = 70, + IP_CHECK = 80, + SECONDARIES = 90, + ACTIVATED = 100, + DEACTIVATING = 110, + FAILED = 120 +} + +local function flags_to_security(flags, wpa_flags, rsn_flags) + local str = "" + if flags == 1 and wpa_flags == 0 and rsn_flags == 0 then + str = str .. " WEP" + end + if wpa_flags ~= 0 then + str = str .. " WPA1" + end + if not rsn_flags ~= 0 then + str = str .. " WPA2" + end + if wpa_flags == 512 or rsn_flags == 512 then + str = str .. " 802.1X" end - local network_controller = wibox.widget { + return (str:gsub("^%s", "")) +end + +local function get_wifi_proxy(self) + local devices = self._private.client_proxy:GetDevices() + for _, device in ipairs(devices) do + local device_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.Device", + path = device + } + + if device_proxy.DeviceType == network.DeviceType.WIFI then + self._private.device_proxy = device_proxy + self._private.wifi_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.Device.Wireless", + path = device + } + + self._private.device_proxy:connect_signal(function(proxy, new_state, old_state, reason) + local active_access_point_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.AccessPoint", + path = self._private.wifi_proxy.ActiveAccessPoint + } + + self:emit_signal(tostring(active_access_point_proxy.HwAddress) .. "::state", new_state, old_state) + if new_state == network.DeviceState.ACTIVATED then + local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid) + self:emit_signal("NM::AccessPointConnected", ssid, active_access_point_proxy.Strength) + end + end, "StateChanged") + end + end +end + +function network.device_state_to_string(state) + local device_state_to_string = + { + [0] = "Unknown", + [10] = "Unmanaged", + [20] = "Unavailable", + [30] = "Disconnected", + [40] = "Prepare", + [50] = "Config", + [60] = "Need Auth", + [70] = "IP Config", + [80] = "IP Check", + [90] = "Secondaries", + [100] = "Activated", + [110] = "Deactivated", + [120] = "Failed" + } + + return device_state_to_string[state] +end + +local function get_access_point_connections(self, ssid) + local connection_proxies = {} + + local connections = self._private.settings_proxy:ListConnections() + for _, connection_path in ipairs(connections) do + local connection_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.Settings.Connection", + path = connection_path + } + + if connection_proxy.Filename:find(ssid) then + table.insert(connection_proxies, connection_proxy) + end + end + + return connection_proxies +end + +local function generate_uuid() + local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx' + local uuid = string.gsub(template, '[xy]', function(c) + local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb) + return string.format('%x', v) + end) + return uuid +end + +local function create_profile(ap, password, auto_connect) + local s_con = + { + -- ["interface-name"] = lgi.GLib.Variant("s", ap.device_interface), + ["uuid"] = lgi.GLib.Variant("s", generate_uuid()), + ["id"] = lgi.GLib.Variant("s", ap.ssid), + ["type"] = lgi.GLib.Variant("s", "802-11-wireless"), + ["autoconnect"] = lgi.GLib.Variant("b", auto_connect), + } + + local s_ip4 = + { + ["method"] = lgi.GLib.Variant("s", "auto") + } + + local s_ip6 = + { + ["method"] = lgi.GLib.Variant("s", "auto"), + } + + local s_wifi = + { + ["mode"] = lgi.GLib.Variant("s", "infrastructure"), + } + + local s_wsec = {} + if ap.security ~= "" then + if ap.security:match("WPA") ~= nil then + s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "wpa-psk") + s_wsec["auth-alg"] = lgi.GLib.Variant("s", "open") + --s_wsec["psk"] = lgi.GLib.Variant("s", helpers.string.trim(password)) + else + s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "None") + s_wsec["wep-key-type"] = lgi.GLib.Variant("s", NM.WepKeyType.PASSPHRASE) + --s_wsec["wep-key0"] = lgi.GLib.Variant("s", helpers.string.trim(password)) + end + end + + return { + ["connection"] = s_con, + ["ipv4"] = s_ip4, + ["ipv6"] = s_ip6, + ["802-11-wireless"] = s_wifi, + ["802-11-wireless-security"] = s_wsec + } +end + +function network:scan_access_points() + self._private.access_points = {} + + self._private.wifi_proxy:RequestScanAsync(function(proxy, context, success, failure) + if failure ~= nil then + self.access_points = { layout = wibox.layout.fixed.vertical } + self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid) + self:emit_signal("NM::ScanFailed", tostring(failure)) + return + end + + local access_points = self._private.wifi_proxy:GetAllAccessPoints() + + self._private.access_points = {} + if (not access_point) or (#access_points == 0) then + self.access_points = { layout = wibox.layout.fixed.vertical } + self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid) + end + + for _, ap in ipairs(access_points) do + local access_point_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.AccessPoint", + path = ap + } + + if access_point_proxy.Ssid then + local appSsid = access_point_proxy.Ssid or "" + local ssid = NM.utils_ssid_to_utf8(appSsid) or "" + local security = flags_to_security(access_point_proxy.Flags, access_point_proxy.WpaFlags) + local password = "" + local connections = get_access_point_connections(self, ssid) + + for _, connection in ipairs(connections) do + if connection.Filename:find(ssid) then + local secrets = connection:GetSecrets("802-11-wireless-security") + if secrets then + password = secrets["802-11-wireless-security"].psk + end + end + end + + table.insert(self._private.access_points, { + ssid = ssid, + security = security, + password = password, + strength = access_point_proxy.Strength, + hw_address = access_point_proxy.HwAddress, + device_interface = self._private.device_proxy.Interface, + device_path = self._private.device_proxy.object_path, + access_point_path = ap + }) + end + end + + self.access_points = { layout = wibox.layout.fixed.vertical } + + local seen = {} + for _, ap2 in ipairs(self._private.access_points) do + if not seen[ap2.ssid] then + seen[ap2.ssid] = true + table.insert(self.access_points, + access_point.new { access_point = ap2, active = self._private.wifi_proxy.ActiveAccessPoint }.widget) + end + end + + table.sort(self._private.access_points, function(a, b) + return a.strength > b.strength + end) + + self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid) + end, { call_id = "my-id" }, {}) +end + +function network:toggle() + self.container.visible = not self.container.visible +end + +function network:is_ap_active(ap) + print(self._private.wifi_proxy.ActiveAccessPoint) + return ap.path == self._private.wifi_proxy.ActiveAccessPoint +end + +function network:disconnect_ap() + self._private.client_proxy:DeactivateConnection(self._private.device_proxy.ActiveConnection) +end + +function network:connect_ap(ap, pw, auto_connect) + local connections = get_access_point_connections(self, ap.ssid) + local profile = create_profile(ap, pw, auto_connect) + + if #connections == 0 then + self._private.client_proxy:AddAndActivateConnectionAsync(function(proxy, context, success, failure) + if failure then + self:emit_signal("NM::AccessPointFailed", tostring(failure)) + return + end + + self:emit_signal("NM::AccessPointConnected", ap.ssid) + end, { call_id = "my-id", profile, ap.device_proxy_path, ap.path }) + else + connections[1]:Update(profile) + self._private.client_proxy:ActivateConnectionAsync(function(proxy, context, success, failure) + if failure then + self:emit_signal("NM::AccessPointFailed", tostring(failure)) + return + end + + self:emit_signal("NM::AccessPointConnected", ap.ssid) + end, { call_id = "my-id", connections[1].object_path, ap.device_proxy_path, ap.path }) + end +end + +function network:toggle_access_point(ap, password, auto_connect) + if self:is_ap_active(ap) then + self:disconnect_ap() + else + self:connect_ap(ap, password, auto_connect) + end +end + +function network:toggle_wireless() + local enable = not self._private.client_proxy.WirelessEnabled + if enable then + self._private.client_proxy:Enable(true) + end + + self._private.client_proxy:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable)) + + return enable +end + +function network.new(args) + args = args or {} + + local ret = gobject {} + + gtable.crush(ret, network, true) + + ret._private = {} + + ret._private.client_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager", + path = "/org/freedesktop/NetworkManager", + } + + ret._private.settings_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.Settings", + path = "/org/freedesktop/NetworkManager/Settings", + } + + local property_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.DBus.Properties", + path = "/org/freedesktop/NetworkManager", + } + + -- dbus proxy signals are in reversed order (function, signal) + property_proxy:connect_signal(function(_, properties, data) + if data.WirelessEnables ~= nil and ret._private.WirelessEnabled ~= data.WirelessEnabled then + ret._private.WirelessEnabled = data.WirelessEnabled + ret:emit_signal("NM::WirelessStateChanged", ret._private.WirelessEnabled) + + if data.WirelessEnabled then + gtimer { + timeout = 5, + autostart = true, + call_now = false, + single_shot = true, + callback = function() + ret:get_access_points() + end + } + end + end + end, "PropertiesChanged") + + get_wifi_proxy(ret) + + ret:scan_access_points() + + gtimer.delayed_call(function() + ret:emit_signal("NM::WirelessStateChanged", ret._private.client_proxy.WirelessEnabled) + + local active_access_point = ret._private.wifi_proxy.ActiveAccessPoint + if ret._private.device_proxy.State == network.DeviceState.ACTIVATED and active_access_point ~= "/" then + local active_access_point_proxy = dbus_proxy.Proxy:new { + bus = dbus_proxy.Bus.SYSTEM, + name = "org.freedesktop.NetworkManager", + interface = "org.freedesktop.NetworkManager.AccessPoint", + path = active_access_point, + } + + local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid) + ret:emit_signal("NM:AccessPointConnected", ssid, active_access_point_proxy.Strength) + end + end) + + local network_widget = wibox.widget { { { - { -- Connected - { --Connected header - { - { - text = "Connected to", - widget = wibox.widget.textbox - }, - widget = wibox.container.background - }, - widget = wibox.container.margin - }, - { -- Connected network - { - get_connected_network(), - widget = wibox.container.background - }, - widget = wibox.container.margin - }, - layout = wibox.layout.fixed.vertical - }, - { -- Discovered networks - { --Discovered header - { - { - text = "Available networks", - widget = wibox.widget.textbox - }, - widget = wibox.container.background - }, - widget = wibox.container.margin - }, - { -- Discovered networks list - - }, - spacing = dpi(10), - layout = wibox.layout.fixed.vertical - }, - { -- Airplanemode/Refresh buttons - { -- Airplane mode toggle + { + { { { { - -- TODO: Replace with image - text = "Airplane mode", - widget = wibox.widgeet.textbox + { + resize = false, + image = gcolor.recolor_image(icondir .. "menu-down.svg", + Theme_config.network_manager.wifi_icon_color), + widget = wibox.widget.imagebox, + valign = "center", + halign = "center", + id = "icon" + }, + id = "center", + halign = "center", + valign = "center", + widget = wibox.container.place, }, - widget = wibox.container.margin + { + { + text = "Wifi Networks", + widget = wibox.widget.textbox, + id = "ap_name" + }, + margins = dpi(5), + widget = wibox.container.margin + }, + id = "wifi", + layout = wibox.layout.fixed.horizontal }, + id = "wifi_bg", + bg = Theme_config.network_manager.wifi_bg, + fg = Theme_config.network_manager.wifi_fg, shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(5)) + gshape.rounded_rect(cr, width, height, dpi(4)) end, widget = wibox.container.background }, + id = "wifi_margin", widget = wibox.container.margin }, - { -- Refresh button + { + id = "wifi_list", { { - { - -- TODO: Replace with image - text = "Refresh", - widget = wibox.widgeet.textbox - }, - widget = wibox.container.margin + step = dpi(50), + spacing = dpi(10), + layout = require("src.lib.overflow_widget.overflow").vertical, + scrollbar_width = 0, + id = "wifi_ap_list" }, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(5)) - end, - widget = wibox.container.background + id = "margin", + margins = dpi(10), + widget = wibox.container.margin }, - widget = wibox.container.margin + border_color = Theme_config.network_manager.ap_border_color, + border_width = Theme_config.network_manager.ap_border_width, + shape = function(cr, width, height) + gshape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4)) + end, + widget = wibox.container.background, + forced_height = 0 }, - layout = wibox.layout.align.horizontal + { + { -- action buttons + { -- refresh + { + { + image = gcolor.recolor_image(icondir .. "refresh.svg", + Theme_config.network_manager.refresh_icon_color), + resize = false, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox, + id = "icon" + }, + widget = wibox.container.margin, + margins = dpi(5), + id = "center", + }, + border_width = dpi(2), + border_color = Theme_config.network_manager.border_color, + shape = function(cr, width, height) + gshape.rounded_rect(cr, width, height, dpi(4)) + end, + bg = Theme_config.network_manager.refresh_bg, + widget = wibox.container.background, + id = "refresh" + }, + nil, + { -- airplane mode + { + { + image = gcolor.recolor_image(icondir .. "airplane-off.svg", + Theme_config.network_manager.airplane_icon_color), + resize = false, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox, + id = "icon" + }, + widget = wibox.container.margin, + margins = dpi(5), + id = "center", + }, + border_width = dpi(2), + border_color = Theme_config.network_manager.border_color, + shape = function(cr, width, height) + gshape.rounded_rect(cr, width, height, dpi(4)) + end, + bg = Theme_config.network_manager.refresh_bg, + widget = wibox.container.background, + id = "airplane" + }, + layout = wibox.layout.align.horizontal + }, + widget = wibox.container.margin, + top = dpi(10), + id = "action_buttons" + }, + id = "layout1", + layout = wibox.layout.fixed.vertical }, - layout = wibox.layout.fixed.vertical + id = "margin", + margins = dpi(15), + widget = wibox.container.margin }, - margins = dpi(10), - widget = wibox.container.margin + shape = function(cr, width, height) + gshape.rounded_rect(cr, width, height, dpi(8)) + end, + border_color = Theme_config.network_manager.border_color, + border_width = Theme_config.network_manager.border_width, + bg = Theme_config.network_manager.bg, + id = "background", + widget = wibox.container.background }, width = dpi(400), strategy = "exact", widget = wibox.container.constraint } - local network_controller_container = awful.popup { - widget = wibox.container.background, - bg = Theme_config.network_controller.bg, - border_color = Theme_config.network_controller.border_color, - border_width = Theme_config.network_controller.border_width, - screen = s, + local refresh_button = network_widget:get_children_by_id("refresh")[1] + + refresh_button:buttons( + gtable.join( + awful.button( + {}, + 1, + nil, + function() + ret:scan_access_points() + end + ) + ) + ) + + Hover_signal(refresh_button) + + local airplane_button = network_widget:get_children_by_id("airplane")[1] + + airplane_button:buttons( + gtable.join( + awful.button( + {}, + 1, + nil, + function() + if ret:toggle_wireless() then + airplane_button.center.icon.image = gcolor.recolor_image(icondir + .. "airplane-off.svg", + Theme_config.network_manager.airplane_icon_color) + else + airplane_button.center.icon.image = gcolor.recolor_image(icondir + .. "airplane-on.svg", + Theme_config.network_manager.airplane_icon_color) + end + ret:scan_access_points() + end + ) + ) + ) + + Hover_signal(airplane_button) + + local wifi_margin = network_widget:get_children_by_id("wifi_margin")[1] + local wifi_list = network_widget:get_children_by_id("wifi_list")[1] + local wifi = network_widget:get_children_by_id("wifi")[1].center + + local rubato_timer = rubato.timed { + duration = 0.2, + pos = wifi_list.forced_height, + easing = rubato.linear, + subscribed = function(v) + wifi_list.forced_height = v + end + } + + wifi_margin:buttons( + gtable.join( + awful.button( + {}, + 1, + nil, + function() + if wifi_list.forced_height == 0 then + local size = (#ret.access_points * 49) + 1 + + size = size > 210 and 210 or size + + rubato_timer.target = dpi(size) + wifi_margin.wifi_bg.shape = function(cr, width, height) + gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4)) + end + wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-up.svg", + Theme_config.network_manager.wifi_icon_color)) + else + rubato_timer.target = 0 + wifi_margin.wifi_bg.shape = function(cr, width, height) + gshape.partially_rounded_rect(cr, width, height, true, true, true, true, dpi(4)) + end + wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg", + Theme_config.network_manager.wifi_icon_color)) + end + end + ) + ) + ) + + ret.widget = awful.popup { + widget = network_widget, + bg = Theme_config.network_manager.bg, + screen = args.screen, stretch = false, visible = false, ontop = true, @@ -122,9 +666,22 @@ return function(s) end } - network_controller_container:setup { - network_controller, - layout = wibox.layout.fixed.vertical - } + capi.awesome.connect_signal("NM::toggle_container", function() + ret.widget.visible = not ret.widget.visible + ret:scan_access_points() + end) + capi.awesome.connect_signal("NM::toggle_wifi", function() + ret:toggle_wireless() + end) + + ret:connect_signal("NM::AccessPointsFound", function(tab) + network_widget:get_children_by_id("wifi_ap_list")[1].children = ret.access_points + end) end + +function network.mt:__call(...) + return network.new(...) +end + +return setmetatable(network, network.mt) diff --git a/awesome/src/modules/notification-center/notification_list.lua b/awesome/src/modules/notification-center/notification_list.lua index df806f3..b28e9c4 100644 --- a/awesome/src/modules/notification-center/notification_list.lua +++ b/awesome/src/modules/notification-center/notification_list.lua @@ -254,7 +254,7 @@ function nl.create_notification(n) end ) - table.insert(nl.notification_list, notification) + table.insert(nl.notification_list, 1, notification) end naughty.connect_signal( diff --git a/awesome/src/modules/powermenu/powermenu.lua b/awesome/src/modules/powermenu/powermenu.lua new file mode 100644 index 0000000..c39e862 --- /dev/null +++ b/awesome/src/modules/powermenu/powermenu.lua @@ -0,0 +1,249 @@ +-------------------------------- +-- This is the network widget -- +-------------------------------- + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +local capi = { + awesome = awesome, + mouse = mouse, +} + +-- Icon directory path +local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/powermenu/" + +return function(s) + + -- Profile picture imagebox + local profile_picture = wibox.widget { + image = icondir .. "defaultpfp.svg", + resize = true, + forced_height = dpi(200), + clip_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(30)) + end, + valign = "center", + halign = "center", + widget = wibox.widget.imagebox + } + + -- Username textbox + local profile_name = wibox.widget { + align = 'center', + valign = 'center', + text = " ", + font = "JetBrains Mono Bold 30", + widget = wibox.widget.textbox + } + + -- Get the profile script from /var/lib/AccountsService/icons/${USER} + -- and copy it to the assets folder + -- TODO: If the user doesnt have AccountsService look into $HOME/.faces + local update_profile_picture = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/pfp.sh 'userPfp'", + function(stdout) + if stdout then + profile_picture:set_image(stdout:gsub("\n", "")) + else + profile_picture:set_image(icondir .. "defaultpfp.svg") + end + end + ) + end + update_profile_picture() + + -- Get the full username(if set) and the username + hostname + local update_user_name = function() + awful.spawn.easy_async_with_shell( + "./.config/awesome/src/scripts/pfp.sh 'userName' '" .. User_config.namestyle .. "'", + function(stdout) + if stdout:gsub("\n", "") == "Rick Astley" then + profile_picture:set_image(gears.filesystem.get_configuration_dir() .. "src/assets/userpfp/" .. "rickastley.jpg") + end + profile_name:set_text(stdout) + end + ) + end + update_user_name() + + -- Universal Button widget + local button = function(name, icon, bg_color, callback) + local item = wibox.widget { + { + { + { + { + -- TODO: using gears.color to recolor a SVG will make it look super low res + -- currently I recolor it in the .svg file directly, but later implement + -- a better way to recolor a SVG + image = icon, + resize = true, + forced_height = dpi(30), + valign = "center", + halign = "center", + widget = wibox.widget.imagebox + }, + { + text = name, + font = "JetBrains Mono Bold 30", + widget = wibox.widget.textbox + }, + widget = wibox.layout.fixed.horizontal + }, + margins = dpi(10), + widget = wibox.container.margin + }, + fg = Theme_config.powermenu.button_fg, + bg = bg_color, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(10)) + end, + widget = wibox.container.background, + id = 'background' + }, + layout = wibox.layout.align.vertical + } + + item:connect_signal( + "button::release", + function() + callback() + end + ) + + return item + end + + -- Create the power menu actions + local suspend_command = function() + awful.spawn("systemctl suspend") + capi.awesome.emit_signal("module::powermenu:hide") + end + + local logout_command = function() + capi.awesome.quit() + end + + local lock_command = function() + awful.spawn("dm-tool lock") + capi.awesome.emit_signal("module::powermenu:hide") + end + + local shutdown_command = function() + awful.spawn("shutdown now") + capi.awesome.emit_signal("module::powermenu:hide") + end + + local reboot_command = function() + awful.spawn("reboot") + capi.awesome.emit_signal("module::powermenu:hide") + end + + -- Create the buttons with their command and name etc + local shutdown_button = button("Shutdown", icondir .. "shutdown.svg", Theme_config.powermenu.shutdown_button_bg, + shutdown_command) + local reboot_button = button("Reboot", icondir .. "reboot.svg", Theme_config.powermenu.reboot_button_bg, reboot_command) + local suspend_button = button("Suspend", icondir .. "suspend.svg", Theme_config.powermenu.suspend_button_bg, + suspend_command) + local logout_button = button("Logout", icondir .. "logout.svg", Theme_config.powermenu.logout_button_bg, logout_command) + local lock_button = button("Lock", icondir .. "lock.svg", Theme_config.powermenu.lock_button_bg, lock_command) + + -- Signals to change color on hover + Hover_signal(shutdown_button.background) + Hover_signal(reboot_button.background) + Hover_signal(suspend_button.background) + Hover_signal(logout_button.background) + Hover_signal(lock_button.background) + + -- The powermenu widget + local powermenu = wibox.widget { + { + { + profile_picture, + profile_name, + spacing = dpi(50), + layout = wibox.layout.fixed.vertical + }, + { + { + shutdown_button, + reboot_button, + logout_button, + lock_button, + suspend_button, + spacing = dpi(30), + layout = wibox.layout.fixed.horizontal + }, + halign = "center", + valign = "center", + widget = wibox.container.place + }, + layout = wibox.layout.fixed.vertical + }, + halign = "center", + valign = "center", + widget = wibox.container.place + } + + -- Container for the widget, covers the entire screen + local powermenu_container = wibox { + widget = powermenu, + screen = s, + type = "splash", + visible = false, + ontop = true, + bg = Theme_config.powermenu.container_bg, + height = s.geometry.height, + width = s.geometry.width, + x = s.geometry.x, + y = s.geometry.y + } + + -- Close on rightclick + powermenu_container:buttons( + gears.table.join( + awful.button( + {}, + 3, + function() + capi.awesome.emit_signal("module::powermenu:hide") + end + ) + ) + ) + + -- Close on Escape + local powermenu_keygrabber = awful.keygrabber { + autostart = false, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + if key == 'Escape' then + capi.awesome.emit_signal("module::powermenu:hide") + end + end + } + + -- Signals + capi.awesome.connect_signal( + "module::powermenu:show", + function() + if s == capi.mouse.screen then + powermenu_container.visible = true + powermenu_keygrabber:start() + end + end + ) + + capi.awesome.connect_signal( + "module::powermenu:hide", + function() + powermenu_keygrabber:stop() + powermenu_container.visible = false + end + ) +end diff --git a/awesome/src/modules/titlebar/titlebar.lua b/awesome/src/modules/titlebar/titlebar.lua new file mode 100644 index 0000000..68a1b7e --- /dev/null +++ b/awesome/src/modules/titlebar/titlebar.lua @@ -0,0 +1,447 @@ +----------------------------------- +-- This is the titlebar module -- +----------------------------------- + +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gears = require("gears") +local wibox = require("wibox") + +local capi = { + awesome = awesome, + client = client +} + +-- Icon directory path +local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/titlebar/" + +awful.titlebar.enable_tooltip = true +awful.titlebar.fallback_name = 'Client' + +-- Normal AND Focus(active/inactive) have to be set or errors will appear in stdout +Theme.titlebar_close_button_normal = icondir .. "close.svg" +Theme.titlebar_close_button_focus = icondir .. "close.svg" +Theme.titlebar_minimize_button_normal = icondir .. "minimize.svg" +Theme.titlebar_minimize_button_focus = icondir .. "minimize.svg" +Theme.titlebar_maximized_button_normal = icondir .. "maximize.svg" +Theme.titlebar_maximized_button_active = icondir .. "maximize.svg" +Theme.titlebar_maximized_button_inactive = icondir .. "maximize.svg" + +local create_buttons = function(c) + local buttons = gears.table.join( + awful.button( + {}, + 1, + function() + c:activate { context = 'titlebar', action = 'mouse_move' } + end + ), + awful.button( + {}, + 3, + function() + c:activate { context = 'titlebar', action = 'mouse_resize' } + end + ) + ) + return buttons +end + +local create_titlebar = function(c, size, position) + local close_button = awful.titlebar.widget.closebutton(c) + local minimize_button = awful.titlebar.widget.minimizebutton(c) + local maximize_button = awful.titlebar.widget.maximizedbutton(c) + + local tb + + if position == "left" then + local titlebar = awful.titlebar(c, { + position = "left", + bg = Theme_config.titlebar.bg, + size = size + }) + + tb = wibox.widget { + { + { + { + close_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.close_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "closebutton" + }, + { + maximize_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.maximize_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "maximizebutton" + }, + { + minimize_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.minimize_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "minimizebutton" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical, + id = "spacing" + }, + margins = dpi(5), + widget = wibox.container.margin, + id = "margin" + }, + { + buttons = create_buttons(c), + layout = wibox.layout.flex.vertical + }, + { + awful.titlebar.widget.iconwidget(c), + margins = dpi(5), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical, + id = "main" + } + + titlebar:setup { tb, layout = wibox.layout.fixed.horizontal } + + elseif position == "top" then + local titlebar = awful.titlebar(c, { + position = "top", + bg = Theme_config.titlebar.bg, + size = size + }) + + tb = wibox.widget { + { + awful.titlebar.widget.iconwidget(c), + margins = dpi(5), + widget = wibox.container.margin + }, + { + { + awful.titlebar.widget.titlewidget(c), + valign = "center", + halign = "center", + layout = wibox.container.place, + }, + buttons = create_buttons(c), + fill_space = true, + layout = wibox.layout.stack + }, + { + { + { + minimize_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.minimize_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "minimizebutton" + }, + { + maximize_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.maximize_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "maximizebutton" + }, + { + close_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.close_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "closebutton" + }, + spacing = dpi(10), + layout = wibox.layout.fixed.horizontal, + id = "spacing" + }, + margins = dpi(5), + widget = wibox.container.margin, + id = "margin" + }, + layout = wibox.layout.align.horizontal, + id = "main" + } + + titlebar:setup { tb, layout = wibox.layout.fixed.vertical } + end + + if not tb then return end + + close_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.close_button.hover_border + local cb = tb:get_children_by_id("closebutton")[1] + cb.border_color = Theme_config.titlebar.close_button.hover_border + cb.bg = Theme_config.titlebar.close_button.hover_bg + end + ) + + close_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local cb = tb:get_children_by_id("closebutton")[1] + cb.border_color = Theme_config.titlebar.close_button.border_color + cb.bg = Theme_config.titlebar.close_button.bg + end + ) + + minimize_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.minimize_button.hover_border + local mb = tb:get_children_by_id("minimizebutton")[1] + mb.border_color = Theme_config.titlebar.minimize_button.hover_border + mb.bg = Theme_config.titlebar.minimize_button.hover_bg + end + ) + + minimize_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local mb = tb:get_children_by_id("minimizebutton")[1] + mb.border_color = Theme_config.titlebar.minimize_button.border_color + mb.bg = Theme_config.titlebar.minimize_button.bg + end + ) + + maximize_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.maximize_button.hover_border + local mb = tb:get_children_by_id("maximizebutton")[1] + mb.border_color = Theme_config.titlebar.maximize_button.hover_border + mb.bg = Theme_config.titlebar.maximize_button.hover_bg + end + ) + + maximize_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local mb = tb:get_children_by_id("maximizebutton")[1] + mb.border_color = Theme_config.titlebar.maximize_button.border_color + mb.bg = Theme_config.titlebar.maximize_button.bg + end + ) +end + +local create_titlebar_dialog_modal = function(c, size, position) + local close_button = awful.titlebar.widget.closebutton(c) + local minimize_button = awful.titlebar.widget.minimizebutton(c) + local maximize_button = awful.titlebar.widget.maximizedbutton(c) + + local tb + + if position == "left" then + local titlebar = awful.titlebar(c, { + position = "left", + bg = Theme_config.titlebar.bg, + size = size + }) + + tb = wibox.widget { + { + { + close_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.close_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "closebutton" + }, + margins = dpi(5), + widget = wibox.container.margin, + id = "margin" + }, + { + buttons = create_buttons(c), + layout = wibox.layout.flex.vertical + }, + { + awful.titlebar.widget.iconwidget(c), + margins = dpi(5), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical, + id = "main" + } + + titlebar:setup { tb, layout = wibox.layout.fixed.horizontal } + + elseif position == "top" then + local titlebar = awful.titlebar(c, { + position = "top", + bg = Theme_config.titlebar.bg, + size = size + }) + + tb = wibox.widget { + { + awful.titlebar.widget.iconwidget(c), + margins = dpi(5), + widget = wibox.container.margin + }, + { + { + awful.titlebar.widget.titlewidget(c), + valign = "center", + halign = "center", + layout = wibox.container.place, + }, + buttons = create_buttons(c), + fill_space = true, + layout = wibox.layout.stack + }, + { + { + close_button, + widget = wibox.container.background, + border_color = Theme_config.titlebar.close_button.border_color, + border_width = dpi(2), + shape = function(cr, height, width) + gears.shape.rounded_rect(cr, width, height, dpi(6)) + end, + id = "closebutton" + }, + margins = dpi(5), + widget = wibox.container.margin, + id = "margin" + }, + layout = wibox.layout.align.horizontal, + id = "main" + } + + titlebar:setup { tb, layout = wibox.layout.fixed.vertical } + end + + if not tb then return end + + close_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.close_button.hover_border + local cb = tb:get_children_by_id("closebutton")[1] + cb.border_color = Theme_config.titlebar.close_button.hover_border + cb.bg = Theme_config.titlebar.close_button.hover_bg + end + ) + + close_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local cb = tb:get_children_by_id("closebutton")[1] + cb.border_color = Theme_config.titlebar.close_button.border_color + cb.bg = Theme_config.titlebar.close_button.bg + end + ) + + minimize_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.minimize_button.hover_border + local mb = tb:get_children_by_id("minimizebutton")[1] + mb.border_color = Theme_config.titlebar.minimize_button.hover_border + mb.bg = Theme_config.titlebar.minimize_button.hover_bg + end + ) + + minimize_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local mb = tb:get_children_by_id("minimizebutton")[1] + mb.border_color = Theme_config.titlebar.minimize_button.border_color + mb.bg = Theme_config.titlebar.minimize_button.bg + end + ) + + maximize_button:connect_signal( + "mouse::enter", + function() + c.border_color = Theme_config.titlebar.maximize_button.hover_border + local mb = tb:get_children_by_id("maximizebutton")[1] + mb.border_color = Theme_config.titlebar.maximize_button.hover_border + mb.bg = Theme_config.titlebar.maximize_button.hover_bg + end + ) + + maximize_button:connect_signal( + "mouse::leave", + function() + c.border_color = Theme_config.window.border_normal + local mb = tb:get_children_by_id("maximizebutton")[1] + mb.border_color = Theme_config.titlebar.maximize_button.border_color + mb.bg = Theme_config.titlebar.maximize_button.bg + end + ) +end + +capi.client.connect_signal( + "request::titlebars", + function(c) + if c.type == "dialog" then + create_titlebar_dialog_modal(c, dpi(35), User_config.titlebar_position) + elseif c.type == "modal" then + create_titlebar_dialog_modal(c, dpi(35), User_config.titlebar_position) + else + create_titlebar(c, dpi(35), User_config.titlebar_position) + end + + if not c.floating or c.maximized or c.fullscreen then + if User_config.titlebar_position == "left" then + awful.titlebar.hide(c, "left") + elseif User_config.titlebar_position == "top" then + awful.titlebar.hide(c, "top") + end + end + end +) + +capi.client.connect_signal( + "property::floating", + function(c) + if c.floating and not (c.maximized or c.fullscreen) then + if User_config.titlebar_position == "left" then + awful.titlebar.show(c, "left") + elseif User_config.titlebar_position == "top" then + awful.titlebar.show(c, "top") + end + else + if User_config.titlebar_position == "left" then + awful.titlebar.hide(c, "left") + elseif User_config.titlebar_position == "top" then + awful.titlebar.hide(c, "top") + end + end + end +) diff --git a/awesome/src/theme/theme_config.lua b/awesome/src/theme/theme_config.lua index fd737ac..b395b6c 100644 --- a/awesome/src/theme/theme_config.lua +++ b/awesome/src/theme/theme_config.lua @@ -16,59 +16,59 @@ Theme_config = {} ]] -- ---#region Widget Settings +-- #region Widget Settings Theme_config.audio = { bg = color["Yellow200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.battery = { bg = color["Purple200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.bluetooth = { bg = color["Blue200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.clock = { bg = color["Orange200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.cpu_freq = { bg = color["Blue200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.cpu_temp = { fg = color["Grey900"], bg_low = color["Green200"], bg_mid = color["Orange200"], - bg_high = color["Red200"], + bg_high = color["Red200"] } Theme_config.cpu_usage = { bg = color["Blue200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.date = { bg = color["Teal200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.gpu_usage = { bg = color["Green200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.gpu_temp = { fg = color["Grey900"], bg_low = color["Green200"], bg_mid = color["Orange200"], - bg_high = color["Red200"], + bg_high = color["Red200"] } Theme_config.kblayout = { @@ -81,13 +81,13 @@ Theme_config.kblayout = { fg_long = color["Red200"], fg_short = color["Purple200"], bg_selected = color["DeepPurple200"], - fg_selected = color["Grey900"], + fg_selected = color["Grey900"] } } Theme_config.layout_list = { bg = color["LightBlue200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.network = { @@ -98,16 +98,16 @@ Theme_config.network = { Theme_config.power_button = { bg = color["Red200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.ram_info = { bg = color["Red200"], - fg = color["Grey900"], + fg = color["Grey900"] } Theme_config.systray = { - bg = "#3A475C", + bg = "#3A475C" } Theme_config.taglist = { @@ -118,7 +118,7 @@ Theme_config.taglist = { bg_focus = color["Grey100"], bg_focus_pressed = "#dddddd", bg_focus_hover = color["Grey100"], - fg_focus = color["Grey900"], + fg_focus = color["Grey900"] } Theme_config.tasklist = { @@ -129,9 +129,9 @@ Theme_config.tasklist = { bg_focus = color["Grey100"], bg_focus_pressed = "#dddddd", bg_focus_hover = color["Grey100"], - fg_focus = color["Grey900"], + fg_focus = color["Grey900"] } ---#endregion +-- #endregion --[[ ======================= @@ -143,7 +143,7 @@ Theme_config.tasklist = { ]] -- ---#region Module Settings +-- #region Module Settings Theme_config.calendar = { bg = color["Grey900"], fg = color["Grey100"], @@ -164,14 +164,15 @@ Theme_config.calendar = { border_width = dpi(2), shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(8)) - end, + end }, task = { bg = color["Purple200"], + bg_past = color["Grey600"], fg = color["Grey900"], shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(4)) - end, + end }, weekdays = { bg = color["Grey900"], @@ -182,14 +183,76 @@ Theme_config.calendar = { fg = color["Grey900"], shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(4)) - end, + end }, add_task = { bg = color["LightBlue200"], fg = color["Grey900"], shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(4)) - end, + end + }, + task_info = { + icon_color = color["Blue200"], + bg = color["Grey900"], + fg = color["White"], + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(12)) + end + } +} + +Theme_config.desktop = { + context_menu = { + icon_color = color["Purple200"], + entry_bg = color["Grey900"], + entry_fg = color["Pink200"], + bg = color["Grey900"], + fg = color["Pink200"], + border_color = color["Grey800"], + border_width = dpi(2), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(12)) + end + } +} + +Theme_config.network_manager = { + bg = color["Grey900"], + border_color = color["Grey800"], + border_width = dpi(2), + wifi_icon_color = color["DeepOrange200"], + wifi_bg = color["Grey800"], + wifi_fg = color["Orange200"], + ap_border_color = color["Grey800"], + ap_border_width = dpi(2), + airplane_icon_color = color["Orange200"], + refresh_icon_color = color["Orange200"], + power_icon_color = color["Orange200"], + refresh_bg = color["Grey900"], + power_bg = color["Grey900"], + access_point = { + icon_color = color["Red200"], + button_color = color["Grey900"], + icon_color2 = color["Grey900"], + bg = color["Grey900"], + fg = color["Red200"], + border_color = color["Grey800"], + border_width = dpi(2), + device_shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(4)) + end + }, + form = { + bg = color["Grey900"], + fg = color["Grey100"], + close_bg = color["Red200"], + icon_fg = color["Grey900"], + border_color = color["Grey800"], + border_width = dpi(2), + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, dpi(8)) + end } } @@ -223,7 +286,7 @@ Theme_config.notification = { fg_close = color["Teal200"], bg_close = color["Grey900"], title_border_color = color["Grey800"], - title_border_width = dpi(2), + title_border_width = dpi(2) } Theme_config.notification_center = { @@ -235,7 +298,7 @@ Theme_config.notification_center = { -- Clear all button clear_all_button = { bg = color["Blue200"], - fg = color["Grey900"], + fg = color["Grey900"] }, -- DnD button @@ -245,7 +308,7 @@ Theme_config.notification_center = { disabled = color["Grey700"], enabled = color["Purple200"], border_disabled = color["Grey800"], - border_enabled = color["Purple200"], + border_enabled = color["Purple200"] }, -- Notification_list @@ -305,7 +368,7 @@ Theme_config.notification_center = { }, -- Spacing line widget spacing_line = { - color = color["Grey800"], + color = color["Grey800"] }, -- Status bar widgets @@ -324,13 +387,11 @@ Theme_config.notification_center = { volume_color = color["Yellow200"], microphone_color = color["Blue200"], backlight_color = color["Pink200"], - battery_color = color["Purple200"], + battery_color = color["Purple200"] }, -- Time Date widget - time_date = { - - }, + time_date = {}, -- Weather widget weather = { @@ -343,7 +404,7 @@ Theme_config.notification_center = { shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(12)) end - }, + } } Theme_config.bluetooth_controller = { @@ -367,6 +428,10 @@ Theme_config.bluetooth_controller = { container_border_color = color["Grey800"], container_border_width = dpi(4), container_bg = color["Grey900"], + refresh_icon_color = color["Grey900"], + refresh_bg = color["LightBlue200"], + power_icon_color = color["Grey900"], + power_bg = color["Blue200"] } Theme_config.brightness_osd = { @@ -376,11 +441,11 @@ Theme_config.brightness_osd = { border_width = dpi(4), bar_bg_active = color["Blue200"], bar_bg = color["Grey800"], - icon_color = color["Blue200"], + icon_color = color["Blue200"] } Theme_config.center_bar = { - bg = color["Grey900"], + bg = color["Grey900"] } Theme_config.dock = { @@ -389,16 +454,17 @@ Theme_config.dock = { element_focused_hover_bg = color["Grey800"], element_focused_hover_fg = color["Grey100"], bg = color["Grey900"], + cm_icon = color["LightBlue200"], indicator_bg = color["Grey600"], indicator_focused_bg = color["YellowA200"], indicator_urgent_bg = color["RedA200"], indicator_maximized_bg = color["GreenA200"], indicator_bg_mindicator_minimized_bginimized = color["BlueA200"], - indicator_fullscreen_bg = color["PurpleA200"], + indicator_fullscreen_bg = color["PurpleA200"] } Theme_config.left_bar = { - bg = color["Grey900"], + bg = color["Grey900"] } Theme_config.powermenu = { @@ -408,11 +474,11 @@ Theme_config.powermenu = { reboot_button_bg = color["Red200"], suspend_button_bg = color["Yellow200"], lock_button_bg = color["Green200"], - logout_button_bg = color["Orange200"], + logout_button_bg = color["Orange200"] } Theme_config.right_bar = { - bg = color["Grey900"], + bg = color["Grey900"] } Theme_config.titlebar = { @@ -423,7 +489,7 @@ Theme_config.titlebar = { fg = color["Grey100"], hover_border = color["Red800"], hover_bg = color["Red800"] .. "bb", - hover_fg = color["Red800"], + hover_fg = color["Red800"] }, minimize_button = { border_color = "#00000000", @@ -431,7 +497,7 @@ Theme_config.titlebar = { bg = "#00000000", hover_border = color["Orange800"], hover_fg = color["Orange800"], - hover_bg = color["Orange800"] .. "bb", + hover_bg = color["Orange800"] .. "bb" }, maximize_button = { border_color = "#00000000", @@ -439,8 +505,8 @@ Theme_config.titlebar = { bg = "#00000000", hover_border = color["Green800"], hover_fg = color["Green800"], - hover_bg = color["Green800"] .. "bb", - }, + hover_bg = color["Green800"] .. "bb" + } } Theme_config.volume_controller = { @@ -479,7 +545,7 @@ Theme_config.volume_controller = { gears.shape.rounded_rect(cr, width, height, dpi(4)) end, volume_fg = color["Purple200"], - microphone_fg = color["Blue200"], + microphone_fg = color["Blue200"] } Theme_config.volume_osd = { @@ -489,7 +555,7 @@ Theme_config.volume_osd = { border_width = dpi(4), bar_bg_active = color["Purple200"], bar_bg = color["Grey800"], - icon_color = color["Purple200"], + icon_color = color["Purple200"] } Theme_config.window_switcher = { @@ -514,6 +580,7 @@ Theme_config.application_launcher = { bg = "#313131", fg = color["Grey100"], hover_bg = color["Grey700"], + cm_icon_color = color["Pink200"] }, searchbar = { bg = color["Grey900"], @@ -531,7 +598,7 @@ Theme_config.application_launcher = { border_active = color["LightBlue200"], shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, dpi(4)) - end, + end } } @@ -557,7 +624,7 @@ Theme_config.context_menu = { icon_color_hover = color["Teal200"] } } ---#endregion +-- #endregion --[[ ======================== @@ -568,7 +635,7 @@ Theme_config.context_menu = { ]] -- ---#region General Settings +-- #region General Settings Theme_config.window = { border_width = dpi(2), @@ -601,7 +668,7 @@ Theme_config.hotkeys = { font = User_config.font.bold, group_margin = dpi(20), label_bg = color["Cyan200"], - label_fg = color["Grey900"], + label_fg = color["Grey900"] } ---#endregion +-- #endregion diff --git a/awesome/src/theme/user_config.lua b/awesome/src/theme/user_config.lua index 0323b20..dd7d56d 100644 --- a/awesome/src/theme/user_config.lua +++ b/awesome/src/theme/user_config.lua @@ -45,7 +45,7 @@ User_config = { "MEDIA_PLAYER" More information at: https://lazka.github.io/pgi-docs/UPowerGlib-1.0/enums.html#UPowerGlib.DeviceKind.KEYBOARD ]] -- - battery_kind = "LINE_POWER", + battery_kind = "BATTERY", --[[ If your battery is not found you can specify its path here. @@ -98,6 +98,8 @@ User_config = { specify = "JetBrainsMono Nerd Font" }, + gtk_settings = "lxappearance", + --[[ The icon theme name must be exactly as the folder is called The folder can be in any $XDG_DATA_DIRS/icons/[icon_theme_name] @@ -147,6 +149,8 @@ User_config = { ]] -- modkey = "Mod4", + music_player = "flatpak run com.spotify.Client", + --[[ This is the naming sheme used for the powermenu and maybe some other places in the future. Example: @@ -168,6 +172,8 @@ User_config = { ethernet = "eno1" }, + screen_settings = "arandr", + --[[ This is the program that will be executed when hitting the print key. ]] -- @@ -198,7 +204,6 @@ User_config = { "backlight" }, - --[[ If true the taskbar will shot the client name instead of the class name. Default: false @@ -210,6 +215,8 @@ User_config = { ]] -- terminal = "alacritty", + text_editor = "code", + --[[ Add every client that should get no titlebar. Use xprop WM_ClASS to get the class of the window. @@ -222,6 +229,7 @@ User_config = { } ]] -- titlebar_exception = { + "protonvpn" }, --[[ @@ -235,7 +243,7 @@ User_config = { This is the path to your wallpaper. home is $HOME, you can also use an absolute path. ]] -- - wallpaper = home .. "/.config/awesome/src/assets/fuji.jpg", + wallpaper = home .. "/Bilder/Hintergründe/784194.jpg", --[[ This is the weather widget. @@ -246,11 +254,13 @@ User_config = { unit = "metric" or "imperial" ]] weather_secrets = { - key = "", - city_id = "", + key = "e71b00168ca7219563dde4514a425b14", + city_id = "2864118", unit = "metric" }, + web_browser = "brave-browser", + --[[ You can configure your bar's here, if you leave it empty the bar will not be shown. If you have multiple monitors you can add [N] where N is to the table below to get a per screen configuration. @@ -276,7 +286,7 @@ User_config = { "Tasklist" <-- Shows all programs per tag !The order goes from left to right! ]] - widgets = { + crylia_bar = { [1] = { left_bar = { "Tiling Layout", @@ -296,8 +306,11 @@ User_config = { "Clock", "Power Button" } - }, - [2] = { + } + }, + + crylia_wibox = { + [1] = { left_bar = { "Tiling Layout", "Taglist" @@ -306,13 +319,14 @@ User_config = { "Tasklist" }, right_bar = { - "Ram Usage", + "Systray", + "Battery", + "Bluetooth", "Audio", - "Keyboard Layout", "Network", + "Keyboard Layout", "Date", "Clock", - "Power Button" } } } diff --git a/awesome/src/tools/dbus/bluetooth_dbus.lua b/awesome/src/tools/dbus/bluetooth_dbus.lua index 6b288e6..78574cb 100644 --- a/awesome/src/tools/dbus/bluetooth_dbus.lua +++ b/awesome/src/tools/dbus/bluetooth_dbus.lua @@ -98,6 +98,13 @@ return function() end ) + capi.awesome.connect_signal( + "bluetooth::stop", + function() + Adapter:StopDiscovery() + end + ) + AdapterProperties:connect_signal( function(data) if data.Powered ~= nil then diff --git a/awesome/src/tools/helpers/audio.lua b/awesome/src/tools/helpers/audio.lua index d1cb847..834ca6b 100644 --- a/awesome/src/tools/helpers/audio.lua +++ b/awesome/src/tools/helpers/audio.lua @@ -1,27 +1,42 @@ local awful = require("awful") +local pulse = require("pulseaudio_dbus") local capi = { awesome = awesome, } ---[[ local lgi = require("lgi") +local lgi = require("lgi") local pulseaudio = require("lua_libpulse_glib") -local ppretty = require("pl.ppretty") local pa = pulseaudio.new() -local ctx = pa:context("My Test App") +local ctx = pa:context("awesome") -ctx:connect(nil, function(state) +print(ctx) +--[[ ctx:connect(nil, function(state) if state == 4 then print("Connection is ready") ctx:get_sinks(function(sinks) - ppretty.dump(sinks) + print(sinks[1]) end) end end) ]] +--local address = pulse.get_address() + +--[[ local connection = pulse.get_connection(address) + +local core = pulse.get_core(connection) + +local sink = pulse.get_device(connection, core:get_sinks()[1]) + +sink:set_muted(false) + +--assert(not sink:is_muted()) + +sink:set_volume_percent({ 75 }) ]] + awful.spawn.with_line_callback( [[bash -c "LC_ALL=C pactl subscribe"]], { diff --git a/awesome/src/tools/helpers/gpu_temp.lua b/awesome/src/tools/helpers/gpu_temp.lua index ccef4a0..0fe45be 100644 --- a/awesome/src/tools/helpers/gpu_temp.lua +++ b/awesome/src/tools/helpers/gpu_temp.lua @@ -9,6 +9,7 @@ watch( [[ bash -c "nvidia-smi -q -d TEMPERATURE | grep 'GPU Current Temp' | awk '{print $5}'"]], 3, function(_, stdout) + if not stdout:gsub("\n", "") then return end capi.awesome.emit_signal("update::gpu_temp", stdout:match("%d+"):gsub("\n", "")) end ) diff --git a/awesome/src/tools/helpers/gpu_usage.lua b/awesome/src/tools/helpers/gpu_usage.lua index a91f1a3..c019bad 100644 --- a/awesome/src/tools/helpers/gpu_usage.lua +++ b/awesome/src/tools/helpers/gpu_usage.lua @@ -10,6 +10,7 @@ watch( 3, function(_, stdout) stdout = stdout:match("%d+") + if not stdout then return end capi.awesome.emit_signal("update::gpu_usage", stdout) end ) diff --git a/awesome/src/tools/ical_parser.lua b/awesome/src/tools/ical_parser.lua index e7ac7a0..dfe042b 100644 --- a/awesome/src/tools/ical_parser.lua +++ b/awesome/src/tools/ical_parser.lua @@ -3,6 +3,8 @@ local gobject = require("gears.object") local gtable = require("gears.table") local naughty = require("naughty") +local color = require("src.theme.colors") + local json = require("src.lib.json-lua.json-lua") local ical = { mt = {} } @@ -108,13 +110,11 @@ end function ical:add_calendar(file) local handler = io.open(file, "r") if not handler then return end - -- Check if the line is a BEGIN:VCALENDAR local v, k = handler:read("l"):match("([A-Z]+):([A-Z]+)") - local vcal = {} if v:match("BEGIN") and k:match("VCALENDAR") then - vcal = self._private.parser.VCALENDAR(handler) + vcal = self._private.parser:VCALENDAR(handler) table.insert(self.VCALENDAR, vcal) self._private.add_to_cache(file, vcal) end @@ -122,11 +122,11 @@ end function ical.new(args) args = args or {} - local ret = gobject {} + local ret = gobject { enable_properties = true, enable_auto_signals = true } gtable.crush(ret, ical, true) local path = gfilesystem.get_configuration_dir() .. "src/config/calendar.json" local handler = io.open(path, "r") - if not handler then return end + if not handler then return ret end local json_data = json:decode(handler:read("a")) handler:close() if not (type(json_data) == "table") then return end @@ -135,7 +135,32 @@ function ical.new(args) ret._private.cache[v.file] = v.VCALENDAR table.insert(ret.VCALENDAR, v.VCALENDAR) end - return ical + + local function get_random_color() + local colors = { + color["Blue200"], + color["Red200"], + color["Green200"], + color["Yellow200"], + color["Purple200"], + color["Orange200"], + color["Pink200"], + color["Cyan200"], + color["Lime200"], + color["Teal200"], + color["Indigo200"], + color["LightBlue200"], + color["BlueGrey200"], + color["DeepOrange200"], + color["DeepPurple200"], + } + + return colors[math.random(1, 15)] + end + + ret.color = get_random_color() + + return ret end function ical._private.parser:VEVENT(handler) @@ -150,32 +175,34 @@ function ical._private.parser:VEVENT(handler) local v, k = line:match("(.*):(.*)") if v:match("CREATED") then - VEVENT.CREATED = self._private.parser.to_datetime(k) + VEVENT.CREATED = self.to_datetime(k) elseif v:match("LAST-MODIFIED") then - VEVENT.LAST_MODIFIED = self._private.parser.to_datetime(k) + VEVENT.LAST_MODIFIED = self.to_datetime(k) elseif v:match("DTSTAMP") then - VEVENT.DTSTAMP = self._private.parser.to_datetime(k) + VEVENT.DTSTAMP = self.to_datetime(k) elseif v:match("UID") then VEVENT.UID = k elseif v:match("SUMMARY") then VEVENT.SUMMARY = k + elseif v:match("STATUS") then + VEVENT.STATUS = k elseif v:match("RRULE") then VEVENT.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), - UNTIL = self._private.parser.to_datetime(k:match("UNTIL=([TZ0-9]+)")), + UNTIL = self.to_datetime(k:match("UNTIL=([TZ0-9]+)")), WKST = k:match("WKST=([A-Z]+)"), COUNT = k:match("COUNT=([0-9]+)"), INTERVAL = k:match("INTERVAL=([0-9]+)") } elseif v:match("DTSTART") then VEVENT.DTSTART = { - DTSTART = self._private.parser.to_datetime(k), + DTSTART = self.to_datetime(k), TZID = v:match("TZID=([a-zA-Z-\\/]+)"), VALUE = v:match("VALUE=([A-Z]+)") } elseif v:match("DTEND") then VEVENT.DTEND = { - DTEND = self._private.parser.to_datetime(k), + DTEND = self.to_datetime(k), TZID = v:match("TZID=([a-zA-Z-\\/]+)"), VALUE = v:match("VALUE=([A-Z]+)") } @@ -183,6 +210,8 @@ function ical._private.parser:VEVENT(handler) VEVENT.TRANSP = k elseif v:match("LOCATION") then VEVENT.LOCATION = k + elseif v:match("SEQUENCE") then + VEVENT.SEQUENCE = k elseif v:match("DESCRIPTION") then VEVENT.DESCRIPTION = k elseif v:match("URL") then @@ -192,7 +221,7 @@ function ical._private.parser:VEVENT(handler) } elseif v:match("BEGIN") then if k:match("VALARM") then - VEVENT.VALARM = self._private.parser:VALARM(handler) + VEVENT.VALARM = self:VALARM(handler) end elseif v:match("UID") then VEVENT.UID = k @@ -258,9 +287,9 @@ function ical._private.parser:VCALENDAR(handler) VCALENDAR.VERSION = k elseif v:match("BEGIN") then if k:match("VTIMEZONE") then - VCALENDAR.VTIMEZONE = self._private.parser:VTIMEZONE(handler) + VCALENDAR.VTIMEZONE = self:VTIMEZONE(handler) elseif k:match("VEVENT") then - table.insert(VCALENDAR.VEVENT, self._private.parser:VEVENT(handler)) + table.insert(VCALENDAR.VEVENT, self:VEVENT(handler)) end end end @@ -286,9 +315,9 @@ function ical._private.parser:VTIMEZONE(handler) end if v:match("BEGIN") then if k:match("DAYLIGHT") then - VTIMEZONE.DAYLIGHT = self._private.parser:DAYLIGHT(handler) + VTIMEZONE.DAYLIGHT = self:DAYLIGHT(handler) elseif k:match("STANDARD") then - VTIMEZONE.STANDARD = self._private.parser:STANDARD(handler) + VTIMEZONE.STANDARD = self:STANDARD(handler) end end end @@ -308,13 +337,13 @@ function ical._private.parser:DAYLIGHT(handler) local v, k = line:match("(.*):(.*)") if v:match("TZOFFSETFROM") then - DAYLIGHT.TZOFFSETFROM = self._private.parser.offset(k) + DAYLIGHT.TZOFFSETFROM = self.offset(k) elseif v:match("TZOFFSETTO") then - DAYLIGHT.TZOFFSETTO = self._private.parser.offset(k) + DAYLIGHT.TZOFFSETTO = self.offset(k) elseif v:match("TZNAME") then DAYLIGHT.TZNAME = k elseif v:match("DTSTART") then - DAYLIGHT.DTSTART = self._private.parser.to_datetime(k) + DAYLIGHT.DTSTART = self.to_datetime(k) elseif v:match("RRULE") then DAYLIGHT.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), @@ -344,13 +373,13 @@ function ical._private.parser:STANDARD(handler) -- Break down each line into the property:value local v, k = line:match("(.*):(.*)") if v:match("TZOFFSETFROM") then - STANDARD.TZOFFSETFROM = self._private.parser.offset(k) + STANDARD.TZOFFSETFROM = self.offset(k) elseif v:match("TZOFFSETTO") then - STANDARD.TZOFFSETTO = self._private.parser.offset(k) + STANDARD.TZOFFSETTO = self.offset(k) elseif v:match("TZNAME") then STANDARD.TZNAME = k elseif v:match("DTSTART") then - STANDARD.DTSTART = self._private.parser.to_datetime(k) + STANDARD.DTSTART = self.to_datetime(k) elseif v:match("RRULE") then STANDARD.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), diff --git a/awesome/src/widgets/date.lua b/awesome/src/widgets/date.lua index 237407e..0665d87 100644 --- a/awesome/src/widgets/date.lua +++ b/awesome/src/widgets/date.lua @@ -7,17 +7,13 @@ local awful = require("awful") local dpi = require("beautiful").xresources.apply_dpi local gears = require("gears") local wibox = require("wibox") -require("src.core.signals") - -local capi = { - awesome = awesome, -} -- Icon directory path local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/date/" -- Returns the date widget -return function() +return function(s) + local cal = require("src.modules.calendar.init") { screen = s } local date_widget = wibox.widget { { @@ -63,13 +59,24 @@ return function() widget = wibox.container.background } + local calendar_popup = awful.popup { + widget = cal:get_widget(), + screen = s, + ontop = true, + bg = "#00000000", + visible = false, + } + -- Signals Hover_signal(date_widget) date_widget:buttons { gears.table.join( awful.button({}, 1, function() - capi.awesome.emit_signal("calendar::toggle", date_widget) + local geo = mouse.current_wibox:geometry() + calendar_popup.x = geo.x + calendar_popup.y = geo.y + Global_config.top_struts + calendar_popup.visible = not calendar_popup.visible end) ) } diff --git a/awesome/src/widgets/gpu_info.lua b/awesome/src/widgets/gpu_info.lua index fe20cea..4bb9cf0 100644 --- a/awesome/src/widgets/gpu_info.lua +++ b/awesome/src/widgets/gpu_info.lua @@ -18,6 +18,7 @@ local capi = { local icon_dir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/cpu/" return function(widget) + local gpu_usage_widget = wibox.widget { { { diff --git a/awesome/src/widgets/network.lua b/awesome/src/widgets/network.lua index 6afb7ff..0e702ad 100644 --- a/awesome/src/widgets/network.lua +++ b/awesome/src/widgets/network.lua @@ -334,11 +334,25 @@ return function() -- Signals Hover_signal(network_widget) - network_widget:connect_signal( - "button::press", - function() - awful.spawn("gnome-control-center wlan") - end + network_widget:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + capi.awesome.emit_signal("NM::toggle_container") + end + ), + awful.button( + {}, + 3, + nil, + function() + capi.awesome.emit_signal("NM::toggle_wifi") + end + ) + ) ) return network_widget diff --git a/awesome/src/widgets/taglist.lua b/awesome/src/widgets/taglist.lua index 9725a71..43efd80 100644 --- a/awesome/src/widgets/taglist.lua +++ b/awesome/src/widgets/taglist.lua @@ -110,16 +110,6 @@ local list_update = function(widget, buttons, _, _, objects) strategy = "exact", layout = wibox.container.constraint, }) - - --[[ awful.spawn.easy_async_with_shell( - "ps -o cmd " .. client.pid .. " | tail -n 1", - function(stdout) - local cmd = stdout:gsub("\n", "") - local app_info = Gio.AppInfo.create_from_commandline(cmd, client.name, {}) - local exec = Gio.AppInfo.get_executable(app_info) - icon:get_children_by_id("icon")[1].image = Get_icon(exec) - end - ) ]] end Hover_signal(tag_widget)