From 5a8fa3ed354cec18a7e1dddb1e4c8d458b1001ae Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Fri, 5 May 2023 19:56:19 +0200 Subject: Add awesome for use with KDE --- .config/awesome/charitable/.gitignore | 7 + .config/awesome/charitable/README.md | 124 ++++ .config/awesome/charitable/init.lua | 160 +++++ .config/awesome/rc.lua | 721 ++++++++++----------- .config/awesome/theme.lua | 6 +- .config/awesome/todo.lua | 47 -- .config/systemd/user/plasma-awesome_x11.service | 11 + .../plasma-awesome_x11.service | 1 + .local/bin/awesome | 1 + .local/etc/wrapper.d/awesome.sh | 6 + 10 files changed, 639 insertions(+), 445 deletions(-) create mode 100644 .config/awesome/charitable/.gitignore create mode 100644 .config/awesome/charitable/README.md create mode 100644 .config/awesome/charitable/init.lua delete mode 100644 .config/awesome/todo.lua create mode 100644 .config/systemd/user/plasma-awesome_x11.service create mode 120000 .config/systemd/user/plasma-workspace.target.wants/plasma-awesome_x11.service create mode 120000 .local/bin/awesome create mode 100644 .local/etc/wrapper.d/awesome.sh diff --git a/.config/awesome/charitable/.gitignore b/.config/awesome/charitable/.gitignore new file mode 100644 index 0000000..edf2840 --- /dev/null +++ b/.config/awesome/charitable/.gitignore @@ -0,0 +1,7 @@ +.svn/* +*~ +*.bak +.vimrc* +*.swp +.idea +*.iml diff --git a/.config/awesome/charitable/README.md b/.config/awesome/charitable/README.md new file mode 100644 index 0000000..da4a924 --- /dev/null +++ b/.config/awesome/charitable/README.md @@ -0,0 +1,124 @@ +# Charitable + +Shared tags library for multiple monitors using AwesomeWM. +Sourced from https://github.com/frioux/charitable + +## Usage + +```lua +local charitable = require("charitable") + +-- Create tags and taglist +local taglist_buttons = gears.table.join( + awful.button({ }, 1, function(t) charitable.select_tag(t, awful.screen.focused()) end), + + awful.button({ }, 3, function(t) charitable.toggle_tag(t, awful.screen.focused()) end) +) + +local tags = charitable.create_tags( + { "1", "2", "3", "4", "5", "6", "7", "8", "9" }, + { + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[1], + } +) + +awful.screen.connect_for_each_screen(function(s) + -- Show an unselected tag when a screen is connected + for i = 1, #tags do + if not tags[i].selected then + tags[i].screen = s + tags[i]:view_only() + break + end + end + + s.mytaglist = awful.widget.taglist({ + screen = s, + filter = awful.widget.taglist.filter.all, + buttons = taglist_buttons, + source = function(screen, args) return tags end, + }) + + -- ... +end + +-- Keys setup +for i = 1, 9 do + globalkeys = gears.table.join(globalkeys, + -- View tag only. + awful.key({ modkey }, "#" .. i + 9, + function () charitable.select_tag(tags[i], awful.screen.focused()) end, + {description = "view tag #"..i, group = "tag"}), + -- Toggle tag display. + awful.key({ modkey, "Control" }, "#" .. i + 9, + function () charitable.toggle_tag(tags[i], awful.screen.focused()) end, + {description = "toggle tag #" .. i, group = "tag"}), + -- Move client to tag. + awful.key({ modkey, "Shift" }, "#" .. i + 9, + function () + if client.focus then + local tag = tags[i] + if tag then + client.focus:move_to_tag(tag) + end + end + end, + {description = "move focused client to tag #"..i, group = "tag"}), + -- Toggle tag on focused client. + awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9, + function () + if client.focus then + local tag = tags[i] + if tag then + client.focus:toggle_tag(tag) + end + end + end, + {description = "toggle focused client on tag #" .. i, group = "tag"}) + ) +end + +-- ensure that removing screens doesn't kill tags +tag.connect_signal("request::screen", function(t) + t.selected = false + for s in screen do + if s ~= t.screen then + t.screen = s + return + end + end +end) + +-- work around bugs in awesome 4.0 through 4.3+ +-- see https://github.com/awesomeWM/awesome/issues/2780 +awful.tag.history.restore = function() end +``` + +## Description + +Typical AwesomeWM configuration implies that tags are per screen. This library +allows AwesomeWM to instead have tags that are shared across all connected +screens. This is how XMonad works by default. + +## Quick Reference + + * `charitable.create_tags` replaces [`awful.tag.new`](https://awesomewm.org/doc/api/classes/tag.html#awful.tag.new) + * `charitable.select_tag` replaces [`t:view_only()`](https://awesomewm.org/doc/api/classes/tag.html#tag:view_only) + * `charitable.toggle_tag` replaces [`awful.tag.viewtoggle`](https://awesomewm.org/doc/api/classes/tag.html#awful.tag.viewtoggle) + * `charitable.tag_move` is new + * `charitable.swap_screen` is new + +## History + +This was [originally](https://github.com/lammermann) implemented by Benjamin +Kober, and later [forked and updated](https://github.com/XLegion/sharetags) by +Alexey Solodkiy. This version has been updated to support AwesomeWM 4.x, and +have a better name. diff --git a/.config/awesome/charitable/init.lua b/.config/awesome/charitable/init.lua new file mode 100644 index 0000000..8c0cc9b --- /dev/null +++ b/.config/awesome/charitable/init.lua @@ -0,0 +1,160 @@ +-- @module sharetags +-- functions to share tags on multiple screens +local sharetags = {} + +--{{{ Grab environment we need +local capi = { screen = screen, client = client } + +local pairs = pairs +local ipairs = ipairs +local tag = require("awful.tag") +local awful = require("awful") + +--}}} + + +--{{{ Functions + +--{{{ create_tags: create a table of tags and bind them to screens +-- @param names : list to label the tags +-- @param layouts : list of layouts for the tags +-- @return table of tag objects +function sharetags.create_tags(names, layouts) + local tags = {} + local count = #names + if capi.screen.count() >= #names then + count = capi.screen.count() + 1 + end + + for tagnumber = 1, count do + tags[tagnumber] = tag.add(names[tagnumber], {}) + tags[tagnumber].number = tagnumber + + awful.layout.set(layouts[tagnumber], tags[tagnumber]) + end + return tags +end +--}}} + +--{{{ sharetags.tag_move: move a tag to a screen +-- @param t : the tag object to move +-- @param screen_target : the screen object to move to +function sharetags.tag_move(t, target_screen) + local ts = t or tag.selected() + + if not target_screen then return end + + local current_screen = ts.screen + + if current_screen and target_screen ~= current_screen then + -- switch for tag + local mynumber = ts.number + + -- sort tags + local index = #target_screen.tags + 1 + for i, screen_tag in pairs(target_screen.tags) do + local number = screen_tag.number + if number ~= nil and mynumber < number then + index = i + break + end + end + + -- save curren_screen tags + local selected_tags = current_screen.selected_tags + + ts.screen = target_screen + ts.index = index + + -- restore curren_screen tag + tag.viewmore(selected_tags, current_screen) + + + -- switch for all clients on tag + if #ts:clients() > 0 then + for _, c in ipairs(ts:clients()) do + if not c.sticky then + c.screen = target_screen + c:tags({ ts }) + + -- Fix maximized client if display sizes not equal + local is_maximized = c.maximized + if is_maximized then + c.maximized = false + c.maximized = true + end + else + awful.client.toggletag(ts, c) + end + end + end + end +end +--}}} + + +-- Open tag on screen +function sharetags.select_tag(t, target_screen) + local prev_focus = capi.client.focus; + local tag_screen = t.screen + local is_tag_select = t.selected; + local is_tag_moved = target_screen ~= tag_screen + + + if t.selected and target_screen ~= tag_screen and #tag_screen.selected_tags == 1 then + sharetags.swap_screen(tag_screen, target_screen) + else + sharetags.tag_move(t, target_screen) + t:view_only() + end + + + -- If there was a moving tag then the focus on the window is lost. Checking + -- if this is the same tag and thus restore focus on the window + if is_tag_moved and is_tag_select and #t:clients() > 0 and prev_focus then + capi.client.focus = prev_focus + end +end + +-- Toggle tag on screen +function sharetags.toggle_tag(t, screen) + if t.screen ~= screen then + sharetags.tag_move(t, screen) + if not t.selected then + tag.viewtoggle(t) + end + else + tag.viewtoggle(t) + end +end + +-- Swap all selected tags between two screens +function sharetags.swap_screen(s1, s2) + if #s1.selected_tags ~= 1 or #s2.selected_tags ~= 1 then + print("can't swap multiple selected tags yet") + end + + local t1 = s1.selected_tag + local t2 = s2.selected_tag + + -- hide both tags in scratch space + t1:swap(t2) + + -- Set selected in both screens to the correct count + if #s1.selected_tags ~= 1 then + for _, t in ipairs(s1.selected_tags) do + t.selected = false + end + end + + if #s2.selected_tags ~= 1 then + for _, t in ipairs(s2.selected_tags) do + t.selected = false + end + end + + t1.selected = true + t2.selected = true +end + +return sharetags diff --git a/.config/awesome/rc.lua b/.config/awesome/rc.lua index 6bd78da..950743b 100644 --- a/.config/awesome/rc.lua +++ b/.config/awesome/rc.lua @@ -1,28 +1,30 @@ +-- If LuaRocks is installed, make sure that packages installed through it are +-- found (e.g. lgi). If LuaRocks is not installed, do nothing. +pcall(require, "luarocks.loader") + -- Standard awesome library local gears = require("gears") local awful = require("awful") require("awful.autofocus") --- Widget and layout library local wibox = require("wibox") --- Theme handling library local beautiful = require("beautiful") --- Notification library local naughty = require("naughty") local menubar = require("menubar") -local hotkeys_popup = require("awful.hotkeys_popup").widget --- Enable hotkeys help widget for VIM and other apps --- when client with a matching name is opened: +local hotkeys_popup = require("awful.hotkeys_popup") require("awful.hotkeys_popup.keys") -local todo = require("todo") +-- Custom libraries +local charitable = require("charitable") --- Error handling +-- {{{ Error handling -- Check if awesome encountered an error during startup and fell back to -- another config (This code will only ever execute for the fallback config) if awesome.startup_errors then - naughty.notify({ preset = naughty.config.presets.critical, - title = "Oops, there were errors during startup!", - text = awesome.startup_errors }) + naughty.notify({ + preset = naughty.config.presets.critical, + title = "Oops, there were errors during startup!", + text = awesome.startup_errors, + }) end -- Handle runtime errors after startup @@ -41,205 +43,136 @@ do end -- }}} --- Variable definitions --- Load theme +-- {{{ Variable definitions beautiful.init(awful.util.getdir("config") .. "/theme.lua") --- This is used later as the default terminal and editor to run. -terminal = "termite" -editor = os.getenv("EDITOR") or "vim" -editor_cmd = terminal .. " -e " .. editor - -- Default modkey. --- Usually, Mod4 is the key with a logo between Control and Alt. --- If you do not like this or do not have such a key, --- I suggest you to remap Mod4 to another key using xmodmap or other tools. --- However, you can use another modifier like Mod1, but it may interact with others. modkey = "Mod4" -- Table of layouts to cover with awful.layout.inc, order matters. awful.layout.layouts = { awful.layout.suit.tile, - awful.layout.suit.tile.left, - awful.layout.suit.tile.bottom, - awful.layout.suit.tile.top, - awful.layout.suit.fair, - awful.layout.suit.fair.horizontal, - awful.layout.suit.spiral, - awful.layout.suit.spiral.dwindle, awful.layout.suit.max, - -- awful.layout.suit.max.fullscreen, awful.layout.suit.magnifier, + awful.layout.suit.floating, + -- awful.layout.suit.max.fullscreen, + -- awful.layout.suit.tile.left, + -- awful.layout.suit.tile.bottom, + -- awful.layout.suit.tile.top, + -- awful.layout.suit.fair, + -- awful.layout.suit.fair.horizontal, + -- awful.layout.suit.spiral, + -- awful.layout.suit.spiral.dwindle, -- awful.layout.suit.corner.nw, - -- awful.layout.suit.floating, -- awful.layout.suit.corner.ne, -- awful.layout.suit.corner.sw, -- awful.layout.suit.corner.se, } -- }}} --- Helper functions -local function client_menu_toggle_fn() - local instance = nil - - return function () - if instance and instance.wibox.visible then - instance:hide() - instance = nil - else - instance = awful.menu.clients({ theme = { width = 250 } }) - end - end -end --- }}} - --- Menu --- Create a launcher widget and a main menu -myawesomemenu = { - { "hotkeys", function() return false, hotkeys_popup.show_help end}, - { "manual", terminal .. " -e man awesome" }, - { "edit config", editor_cmd .. " " .. awesome.conffile }, - { "restart", awesome.restart }, - { "quit", function() awesome.quit() end} -} - -mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon }, - { "open terminal", terminal } - } - }) - -mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, - menu = mymainmenu }) - --- Menubar configuration -menubar.utils.terminal = terminal -- Set the terminal for applications that require it --- }}} - --- Keyboard map indicator and switcher -mykeyboardlayout = awful.widget.keyboardlayout() - --- Wibar --- Create a textclock widget -mytextclock = wibox.widget.textclock() - --- Add the GTD functionality -todo({}):attach(mytextclock) - +-- {{{ Wibar -- Create a wibox for each screen and add it local taglist_buttons = gears.table.join( - awful.button({ }, 1, function(t) t:view_only() end), - awful.button({ modkey }, 1, function(t) - if client.focus then - client.focus:move_to_tag(t) - end - end), - awful.button({ }, 3, awful.tag.viewtoggle), - awful.button({ modkey }, 3, function(t) - if client.focus then - client.focus:toggle_tag(t) - end - end), - awful.button({ }, 4, function(t) awful.tag.viewprev(t.screen) end), - awful.button({ }, 5, function(t) awful.tag.viewnext(t.screen) end) - ) + awful.button({ }, 1, function(t) charitable.select_tag(t, awful.screen.focused()) end), + awful.button({ }, 3, function(t) charitable.toggle_tag(t, awful.screen.focused()) end) +) local tasklist_buttons = gears.table.join( awful.button({ }, 1, function (c) if c == client.focus then c.minimized = true else - -- Without this, the following - -- :isvisible() makes no sense - c.minimized = false - if not c:isvisible() and c.first_tag then - c.first_tag:view_only() - end - -- This will also un-minimize - -- the client, if needed - client.focus = c - c:raise() + c:emit_signal( + "request::activate", + "tasklist", + {raise = true} + ) end end), - awful.button({ }, 3, client_menu_toggle_fn()), + awful.button({ }, 3, function() + awful.menu.client_list({ theme = { width = 250 } }) + end), awful.button({ }, 4, function () - awful.client.focus.byidx(-1) + awful.client.focus.byidx(1) end), awful.button({ }, 5, function () - awful.client.focus.byidx(1) + awful.client.focus.byidx(-1) end)) -awful.tag.add("work", { screen = screen.primary, layout = awful.layout.suit.tile }) -awful.tag.add("social", { screen = screen.primary, layout = awful.layout.suit.max }) -awful.tag.add("web", { screen = screen.primary, layout = awful.layout.suit.max }) -awful.tag.add("email", { screen = screen.primary, layout = awful.layout.suit.magnifier }) -awful.tag.add("fun", { screen = screen.primary, layout = awful.layout.suit.max }) -awful.tag.add("media", { screen = screen.primary, layout = awful.layout.suit.max }) -awful.tag.add("vms", { screen = screen.primary, layout = awful.layout.suit.tile }) -awful.tag.add("scratch", { screen = screen.primary, layout = awful.layout.suit.tile }) - -sharedtaglist = screen.primary.tags +local tags = charitable.create_tags( + { "work", "social", "www", "email", "fun", "media", "vms", "scratch" }, + { + awful.layout.layouts[1], + awful.layout.layouts[1], + awful.layout.layouts[2], + awful.layout.layouts[3], + awful.layout.layouts[2], + awful.layout.layouts[2], + awful.layout.layouts[2], + awful.layout.layouts[4], + } +) awful.screen.connect_for_each_screen(function(s) + -- Show an unselected tag when a screen is connected + for i = 1, #tags do + if not tags[i].selected then + tags[i].screen = s + tags[i]:view_only() + break + end + end + -- Create an imagebox widget which will contain an icon indicating which layout we're using. -- We need one layoutbox per screen. s.mylayoutbox = awful.widget.layoutbox(s) s.mylayoutbox:buttons(gears.table.join( awful.button({ }, 1, function () awful.layout.inc( 1) end), awful.button({ }, 3, function () awful.layout.inc(-1) end), - awful.button({ }, 4, function () awful.layout.inc(-1) end), - awful.button({ }, 5, function () awful.layout.inc( 1) end))) + awful.button({ }, 4, function () awful.layout.inc( 1) end), + awful.button({ }, 5, function () awful.layout.inc(-1) end))) - -- Create a taglist widget - s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons) + -- Create a taglist widget + s.mytaglist = awful.widget.taglist { + screen = s, + filter = awful.widget.taglist.filter.all, + buttons = taglist_buttons, + source = function(screen, args) return tags end, + } -- Create a tasklist widget - s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons) - - -- Create the wibar for status information - s.mywibox_info = awful.wibar({ position = "top", screen = s }) - - -- Add widgets to the wibox - s.mywibox_info:setup { - layout = wibox.layout.align.horizontal, - { -- Left widgets - layout = wibox.layout.fixed.horizontal, - mylauncher, - s.mytaglist, - }, - { - layout = wibox.layout.fixed.horizontal - }, - { -- Right widgets - layout = wibox.layout.fixed.horizontal, - -- mykeyboardlayout, - wibox.widget.systray(), - mytextclock, - s.mylayoutbox, - }, - } - - -- Create a wibar for the task list - s.mywibox_tasks = awful.wibar({ position = "bottom", screen = s }) - - s.mywibox_tasks:setup { - layout = wibox.layout.align.horizontal, - { layout = wibox.layout.fixed.horizontal, }, - s.mytasklist, - { layout = wibox.layout.fixed.horizontal, }, + s.mytasklist = awful.widget.tasklist { + screen = s, + filter = awful.widget.tasklist.filter.currenttags, + buttons = tasklist_buttons } + -- Create the wibox + s.mywibox = awful.wibar({ position = "bottom", screen = s }) + + -- Add widgets to the wibox + s.mywibox:setup { + layout = wibox.layout.align.horizontal, + { + layout = wibox.layout.fixed.horizontal, + spacing = 16, + s.mylayoutbox, + s.mytaglist, + s.mytasklist, + }, + } end) -- }}} --- Mouse bindings +-- {{{ Mouse bindings root.buttons(gears.table.join( awful.button({ }, 3, function () mymainmenu:toggle() end), - awful.button({ }, 4, awful.tag.viewprev), - awful.button({ }, 5, awful.tag.viewnext) + awful.button({ }, 4, awful.tag.viewnext), + awful.button({ }, 5, awful.tag.viewprev) )) -- }}} --- Key bindings +-- {{{ Key bindings globalkeys = gears.table.join( awful.key({ modkey, }, "s", hotkeys_popup.show_help, {description="show help", group="awesome"}), @@ -265,17 +198,18 @@ globalkeys = gears.table.join( awful.key({ modkey, }, "w", function () mymainmenu:show() end, {description = "show main menu", group = "awesome"}), + -- Layout manipulation awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end, {description = "swap with next client by index", group = "client"}), awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end, {description = "swap with previous client by index", group = "client"}), - awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_bydirection("right") end, + awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative(-1) end, {description = "focus the next screen", group = "screen"}), - awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_bydirection("left") end, + awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative( 1) end, {description = "focus the previous screen", group = "screen"}), - --awful.key({ modkey, }, "u", awful.client.urgent.jumpto, - -- {description = "jump to urgent client", group = "client"}), + awful.key({ modkey, }, "u", awful.client.urgent.jumpto, + {description = "jump to urgent client", group = "client"}), awful.key({ modkey, }, "Tab", function () awful.client.focus.history.previous() @@ -285,13 +219,24 @@ globalkeys = gears.table.join( end, {description = "go back", group = "client"}), - -- Standard program - awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end, - {description = "open a terminal", group = "launcher"}), - awful.key({ modkey, "Shift" }, "r", awesome.restart, - {description = "reload awesome", group = "awesome"}), - awful.key({ modkey, "Shift" }, "x", awesome.quit, - {description = "quit awesome", group = "awesome"}), + -- Standard program + awful.key( + { modkey, "Shift" }, "r", awesome.restart, + {description = "reload awesome", group = "awesome"} + ), + awful.key( + { modkey, "Shift" }, "q", awesome.quit, + {description = "quit awesome", group = "awesome"} + ), + + awful.key( + { modkey, }, "p", awful.spawn("ipass"), + { description = "Select password", group = "awesome" } + ), + awful.key( + { modkey, }, "o", awful.spawn("ipass-otp"), + { description = "Select password", group = "awesome" } + ), awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end, {description = "increase master width factor", group = "layout"}), @@ -315,8 +260,9 @@ globalkeys = gears.table.join( local c = awful.client.restore() -- Focus restored client if c then - client.focus = c - c:raise() + c:emit_signal( + "request::activate", "key.unminimize", {raise = true} + ) end end, {description = "restore minimized", group = "client"}) @@ -333,7 +279,7 @@ clientkeys = gears.table.join( {description = "close", group = "client"}), awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle , {description = "toggle floating", group = "client"}), - awful.key({ modkey, "Shift" }, "Return", function (c) c:swap(awful.client.getmaster()) end, + awful.key({ modkey, "Shift" }, "Return", function (c) c:swap(awful.client.getmaster()) end, {description = "move to master", group = "client"}), awful.key({ modkey, }, "o", function (c) c:move_to_screen() end, {description = "move to screen", group = "client"}), @@ -366,261 +312,249 @@ clientkeys = gears.table.join( {description = "(un)maximize horizontally", group = "client"}) ) --- Bind all key numbers to tags. --- Be careful: we use keycodes to make it work on any keyboard layout. --- This should map on the top row of your keyboard, usually 1 to 9. -for i = 1, 9 do - globalkeys = gears.table.join(globalkeys, - -- View tag only. - awful.key({ modkey }, "#" .. i + 10, - function () - local screen = awful.screen.focused() - local tag = sharedtaglist[i] - if tag then - awful.tag.setscreen(screen, tag) - tag:view_only() - end - end, - {description = "view tag #"..i, group = "tag"}), - -- Toggle tag display. - awful.key({ modkey, "Control" }, "#" .. i + 10, - function () - local tag = sharedtaglist[i] - if tag then - awful.tag.viewtoggle(tag) - end - end, - {description = "toggle tag #" .. i, group = "tag"}), - -- Move client to tag. - awful.key({ modkey, "Shift" }, "#" .. i + 10, - function () - if client.focus then - local tag = sharedtaglist[i] - if tag then - client.focus:move_to_tag(tag) - end - end - end, - {description = "move focused client to tag #"..i, group = "tag"}), - -- Toggle tag on focused client. - awful.key({ modkey, "Control", "Shift" }, "#" .. i + 10, - function () - if client.focus then - local tag = sharedtaglist[i] - if tag then - client.focus:toggle_tag(tag) - end - end - end, - {description = "toggle focused client on tag #" .. i, group = "tag"}) - ) +-- Bind numbers row +for i = 1, 8 do + globalkeys = gears.table.join(globalkeys, + -- View tag only. + awful.key( + { modkey }, + "#" .. i + 10, + function () charitable.select_tag(tags[i], awful.screen.focused()) end, + {description = "view tag #"..i, group = "tag"} + ), + + -- Toggle tag display. + awful.key( + { modkey, "Control" }, + "#" .. i + 10, + function () charitable.toggle_tag(tags[i], awful.screen.focused()) end, + {description = "toggle tag #" .. i, group = "tag"} + ), + -- Move client to tag. + + awful.key( + { modkey, "Shift" }, + "#" .. i + 10, + function () + if client.focus then + local tag = tags[i] + if tag then + client.focus:move_to_tag(tag) + end + end + end, + {description = "move focused client to tag #"..i, group = "tag"} + ), + + -- Toggle tag on focused client. + awful.key( + { modkey, "Control", "Shift" }, + "#" .. i + 10, + function () + if client.focus then + local tag = tags[i] + if tag then + client.focus:toggle_tag(tag) + end + end + end, + {description = "toggle focused client on tag #" .. i, group = "tag"} + ) + ) end clientbuttons = gears.table.join( - awful.button({ }, 1, function (c) client.focus = c; c:raise() end), - awful.button({ modkey }, 1, awful.mouse.client.move), - awful.button({ modkey }, 3, awful.mouse.client.resize)) + awful.button({ }, 1, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + end), + awful.button({ modkey }, 1, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + awful.mouse.client.move(c) + end), + awful.button({ modkey }, 3, function (c) + c:emit_signal("request::activate", "mouse_click", {raise = true}) + awful.mouse.client.resize(c) + end) +) -- Set keys root.keys(globalkeys) -- }}} --- Rules +-- {{{ Rules -- Rules to apply to new clients (through the "manage" signal). awful.rules.rules = { - -- All clients will match this rule. - { - rule = { }, - properties = { - border_width = beautiful.border_width, - border_color = beautiful.border_normal, - focus = awful.client.focus.filter, - raise = true, - keys = clientkeys, - buttons = clientbuttons, - screen = awful.screen.preferred, - placement = awful.placement.no_overlap+awful.placement.no_offscreen - } - }, - - -- Floating clients. - - { - rule_any = { - instance = { - "DTA", -- Firefox addon DownThemAll. - "copyq", -- Includes session name in class. - }, - class = { - "Arandr", - "Gpick", - "Kruler", - "MessageWin", -- kalarm. - "Sxiv", - "Wpa_gui", - "pinentry", - "veromix", - "xtightvncviewer" - }, - name = { - "Event Tester", -- xev. - }, - role = { - "AlarmWindow", -- Thunderbird's calendar. - "pop-up", -- e.g. Google Chrome's (detached) Developer Tools. - } - }, - properties = { - floating = true - } - }, - - -- Add titlebars to normal clients and dialogs - - -- { - -- rule_any = { - -- type = { - -- "normal", - -- "dialog" - -- } - -- }, - -- properties = { - -- titlebars_enabled = true - -- } - -- }, - - -- Application-specific rules - - -- www-client/chromium - { - rule_any = { - class = { - "chromium-browser-chromium", - "Chromium-browser-chromium", - } - }, - properties = { - tag = sharedtaglist[3] - }, - }, - - -- www-client/firefox - { - rule_any = { - class = { - "Navigator", - "Firefox Developer Edition" - } - }, - properties = { - tag = sharedtaglist[3] - }, - }, - - -- net-im/signal-desktop - { - rule_any = { - class = { - "Signal", - } - }, - properties = { - tag = sharedtaglist[2] + -- All clients will match this rule. + { rule = { }, + properties = { border_width = beautiful.border_width, + border_color = beautiful.border_normal, + focus = awful.client.focus.filter, + raise = true, + keys = clientkeys, + buttons = clientbuttons, + screen = awful.screen.preferred, + placement = awful.placement.no_overlap+awful.placement.no_offscreen + } }, - }, - - -- media-video/mpv - { - rule_any = { - class = { - "gl", - "mpv", - } - }, - properties = { - tag = sharedtaglist[6] - }, - }, - - { properties = { tag = sharedtaglist[4] }, rule_any = { class = { "claws-mail", "Claws-mail" } } }, - { properties = { tag = sharedtaglist[5] }, rule_any = { name = { "Blizzard Battle.net" } } }, - { properties = { tag = sharedtaglist[5] }, rule_any = { name = { "World of Warcraft" } } }, - { properties = { tag = sharedtaglist[5] }, rule_any = { name = { "Guild Wars" } } }, - - -- Set Firefox to always map on the tag named "2" on screen 1. - -- { rule = { class = "Firefox" }, - -- properties = { screen = 1, tag = "2" } }, - - -- Jellyfin - { - rule = { - class = "jellyfin", - -- class = {, - -- "Chromium-browser-chromium", - -- }, - }, - properties = { - tag = sharedtaglist[6], - maximized = true, - }, - }, - - -- Kodi - { - rule = { - class = "Kodi", - -- class = {, - -- "Chromium-browser-chromium", - -- }, - }, - properties = { - tag = sharedtaglist[6], - maximized = true, - }, - }, - - -- World of Warcraft - { - rule_any = { - class = { - "wow.exe", - }, - }, - properties = { - tag = sharedtaglist[5], - fullscreen = true, + + -- KDE Rules + { -- Remove the default desktop + rule_any = { + name = { "^Desktop " } + }, + properties = { + hidden = true, + }, + }, + { -- Make the KDE shell play nicely + rule_any = { + class = { + "plasmashell", + }, + }, + properties = { + floating = true, + border_width = 0, + focus = false, + }, + }, + { -- Center KDE applets + rule_any = { + class = { + "krunner", + }, + }, + properties = { + floating = true, + border_width = 0, + placement = awful.placement.centered, + }, + }, + + { -- Remove borders from windows where it doesn't fit (housestyles ought to be banned, tho) + rule_any = { + class = { + "nextcloud", + } + }, + properties = { + border_width = 0, + }, + }, + + { -- Tag rules for www + rule_any = { + class = { + "chromium", + "firefox", + "qutebrowser", + }, + }, + properties = { + tag = "www", + }, + }, + + { -- Tag rules for email + rule_any = { + class = { + "thunderbird", + }, + }, + properties = { + tag = "email", + }, + }, + + { -- Tag rules for media + rule_any = { + class = { + "mpv", + } + }, + properties = { + tag = "media", + }, + }, + + -- Floating clients. + { rule_any = { + instance = { + "DTA", -- Firefox addon DownThemAll. + "copyq", -- Includes session name in class. + "pinentry", + }, + class = { + "Arandr", + "Blueman-manager", + "Gpick", + "Kruler", + "MessageWin", -- kalarm. + "Sxiv", + "Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size. + "Wpa_gui", + "veromix", + "xtightvncviewer"}, + + -- Note that the name property shown in xprop might be set slightly after creation of the client + -- and the name shown there might not match defined rules here. + name = { + "Event Tester", -- xev. + }, + role = { + "AlarmWindow", -- Thunderbird's calendar. + "ConfigManager", -- Thunderbird's about:config. + "pop-up", -- e.g. Google Chrome's (detached) Developer Tools. + } + }, properties = { floating = true }}, + + -- Add titlebars to normal clients and dialogs + { rule_any = {type = { "normal", "dialog" } + }, properties = { titlebars_enabled = false } }, - } + + -- Set Firefox to always map on the tag named "2" on screen 1. + -- { rule = { class = "Firefox" }, + -- properties = { screen = 1, tag = "2" } }, } -- }}} --- Signals +-- {{{ Signals -- Signal function to execute when a new client appears. client.connect_signal("manage", function (c) -- Set the windows at the slave, -- i.e. put it at the end of others instead of setting it master. -- if not awesome.startup then awful.client.setslave(c) end - if awesome.startup and - not c.size_hints.user_position + if awesome.startup + and not c.size_hints.user_position and not c.size_hints.program_position then -- Prevent clients from being unreachable after screen count changes. awful.placement.no_offscreen(c) end end) +-- ensure that removing screens doesn't kill tags +tag.connect_signal("request::screen", function(t) + t.selected = false + for s in screen do + if s ~= t.screen then + t.screen = s + return + end + end +end) + -- Add a titlebar if titlebars_enabled is set to true in the rules. client.connect_signal("request::titlebars", function(c) -- buttons for the titlebar local buttons = gears.table.join( awful.button({ }, 1, function() - client.focus = c - c:raise() + c:emit_signal("request::activate", "titlebar", {raise = true}) awful.mouse.client.move(c) end), awful.button({ }, 3, function() - client.focus = c - c:raise() + c:emit_signal("request::activate", "titlebar", {raise = true}) awful.mouse.client.resize(c) end) ) @@ -653,10 +587,7 @@ end) -- Enable sloppy focus, so that focus follows mouse. client.connect_signal("mouse::enter", function(c) - if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier - and awful.client.focus.filter(c) then - client.focus = c - end + c:emit_signal("request::activate", "mouse_enter", {raise = false}) end) client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) diff --git a/.config/awesome/theme.lua b/.config/awesome/theme.lua index 3ee3de6..694887c 100644 --- a/.config/awesome/theme.lua +++ b/.config/awesome/theme.lua @@ -23,9 +23,9 @@ theme.fg_focus = theme.fg_normal theme.fg_urgent = theme.fg_normal theme.fg_minimize = theme.fg_normal -theme.useless_gap = dpi(0) -theme.border_width = dpi(1) -theme.border_normal = "#000000" +theme.useless_gap = dpi(4) +theme.border_width = dpi(2) +theme.border_normal = "#555555" theme.border_focus = "#5778c1" theme.border_marked = "#91231c" diff --git a/.config/awesome/todo.lua b/.config/awesome/todo.lua deleted file mode 100644 index 83cf2d8..0000000 --- a/.config/awesome/todo.lua +++ /dev/null @@ -1,47 +0,0 @@ -local capi = { - mouse = mouse, - screen = screen, -} -local naughty = require("naughty") - ------------------------------------------- --- todo.txt popup widget ------------------------------------------- - -local todo = {} - -function todo:new(args) - return setmetatable({}, {__index = self}) -end - -function todo:show() - local f = assert(io.open("/home/tyil/documents/todo.txt", "rb")) - local content = f:read("*all"):gsub("%s+$", "") - f:close() - - self.notification = naughty.notify({ - title = "Todo", - text = content, - timeout = 0, - hover_timeout = 0.5, - screen = capi.mouse.screen, - position = self.position, - }) -end - -function todo:hide() - if self.notification then - naughty.destroy(self.notification) - self.notification = nil - self.num_lines = 0 - end -end - -function todo:attach(widget) - widget:connect_signal('mouse::enter', function() self:show() end) - widget:connect_signal('mouse::leave', function() self:hide() end) -end - -return setmetatable(todo, { - __call = todo.new, -}) diff --git a/.config/systemd/user/plasma-awesome_x11.service b/.config/systemd/user/plasma-awesome_x11.service new file mode 100644 index 0000000..add09db --- /dev/null +++ b/.config/systemd/user/plasma-awesome_x11.service @@ -0,0 +1,11 @@ +[Install] +WantedBy=plasma-workspace.target + +[Unit] +Description=AwesomeWM for use as WM for KDE +Before=plasma-workspace.target + +[Service] +ExecStart=%h/.local/bin/awesome +Slice=session.slice +Restart=on-failure diff --git a/.config/systemd/user/plasma-workspace.target.wants/plasma-awesome_x11.service b/.config/systemd/user/plasma-workspace.target.wants/plasma-awesome_x11.service new file mode 120000 index 0000000..376c5dd --- /dev/null +++ b/.config/systemd/user/plasma-workspace.target.wants/plasma-awesome_x11.service @@ -0,0 +1 @@ +/home/tyil/.config/systemd/user/plasma-awesome_x11.service \ No newline at end of file diff --git a/.local/bin/awesome b/.local/bin/awesome new file mode 120000 index 0000000..3da827c --- /dev/null +++ b/.local/bin/awesome @@ -0,0 +1 @@ +../share/wrapper.sh \ No newline at end of file diff --git a/.local/etc/wrapper.d/awesome.sh b/.local/etc/wrapper.d/awesome.sh new file mode 100644 index 0000000..5d72452 --- /dev/null +++ b/.local/etc/wrapper.d/awesome.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +WRAPPER_BINS=" + /usr/bin/awesome + /run/current-system/sw/bin/awesome +" -- cgit v1.1