├── keymaps
├── init.lua
├── mouse.lua
└── keyboard.lua
├── assets
├── icons
│ └── submenu.png
└── wallpapers
│ ├── wallpaper.png
│ ├── void-linux.jpg
│ ├── graphite-void.png
│ ├── graphite-ultrawide.png
│ └── ultrawide-wallpaper.png
├── ui
├── widgets
│ ├── init.lua
│ ├── clock.lua
│ ├── battery.lua
│ └── calendar.lua
├── init.lua
├── wallpaper.lua
├── menu.lua
├── dashboard.lua
├── theme.lua
└── panel.lua
├── utilities
├── scripts
│ └── startup.sh
├── focus.lua
├── autostart.lua
├── scratchpads.lua
├── bling.lua
├── layouts.lua
├── init.lua
├── helpers.lua
├── rules.lua
└── notifications.lua
├── .gitmodules
├── rc.lua
├── README.md
└── LICENSE.md
/keymaps/init.lua:
--------------------------------------------------------------------------------
1 | require("keymaps.mouse")
2 | require("keymaps.keyboard")
3 |
--------------------------------------------------------------------------------
/assets/icons/submenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/icons/submenu.png
--------------------------------------------------------------------------------
/assets/wallpapers/wallpaper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/wallpapers/wallpaper.png
--------------------------------------------------------------------------------
/assets/wallpapers/void-linux.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/wallpapers/void-linux.jpg
--------------------------------------------------------------------------------
/assets/wallpapers/graphite-void.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/wallpapers/graphite-void.png
--------------------------------------------------------------------------------
/assets/wallpapers/graphite-ultrawide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/wallpapers/graphite-ultrawide.png
--------------------------------------------------------------------------------
/assets/wallpapers/ultrawide-wallpaper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/devraza/aweful/HEAD/assets/wallpapers/ultrawide-wallpaper.png
--------------------------------------------------------------------------------
/ui/widgets/init.lua:
--------------------------------------------------------------------------------
1 | -- Load all the widgets
2 | require("ui.widgets.clock")
3 | require("ui.widgets.battery")
4 | require("ui.widgets.calendar")
5 |
--------------------------------------------------------------------------------
/utilities/scripts/startup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Everything else is just a systemd service.
4 | xrandr --output eDP-1 --off
5 | emacs --daemon
6 |
--------------------------------------------------------------------------------
/utilities/focus.lua:
--------------------------------------------------------------------------------
1 | -- Sloppy focus
2 | client.connect_signal(
3 | "mouse::enter",
4 | function(c)
5 | c:activate {context = "mouse_enter", raise = false}
6 | end
7 | )
8 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lain"]
2 | path = lain
3 | url = https://github.com/lcpz/lain
4 | [submodule "modules/bling"]
5 | path = modules/bling
6 | url = https://github.com/BlingCorp/bling
7 |
--------------------------------------------------------------------------------
/utilities/autostart.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local gears = require("gears")
3 |
4 | --- Autostart ---
5 | awful.spawn.with_shell(gears.filesystem.get_configuration_dir() .. "utilities/scripts/startup.sh")
6 |
--------------------------------------------------------------------------------
/ui/init.lua:
--------------------------------------------------------------------------------
1 | -- Load UI elements
2 | require("ui.menu")
3 | require("ui.wallpaper")
4 |
5 | -- Load widgets
6 | require("ui.widgets")
7 |
8 | -- Load panel
9 | require("ui.panel")
10 |
11 | -- Load the dashboard
12 | require("ui.dashboard")
13 |
--------------------------------------------------------------------------------
/ui/widgets/clock.lua:
--------------------------------------------------------------------------------
1 | local wibox = require("wibox")
2 | local beautiful = require("beautiful")
3 | local awful = require("awful")
4 |
5 | clock = wibox.widget.background()
6 | clock:set_widget(wibox.widget.textclock("%H\n%M"))
7 | clock:set_fg(beautiful.secondary)
8 |
--------------------------------------------------------------------------------
/utilities/scratchpads.lua:
--------------------------------------------------------------------------------
1 | local bling = require "modules.bling"
2 |
3 | scratch = bling.module.scratchpad {
4 | command = "alacritty --class spad -e tiny",
5 | rule = { instance = "spad" },
6 | sticky = true,
7 | autoclose = true,
8 | dont_focus_before_close = true,
9 | }
10 |
--------------------------------------------------------------------------------
/utilities/bling.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local bling = require("modules.bling")
3 |
4 | -- Bling layouts
5 | tag.connect_signal(
6 | "request::default_layouts",
7 | function()
8 | awful.layout.append_default_layouts(
9 | {
10 | bling.layout.centered,
11 | bling.layout.deck
12 | }
13 | )
14 | end
15 | )
16 |
--------------------------------------------------------------------------------
/utilities/layouts.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 |
3 | -- AwesomeWM
4 | tag.connect_signal(
5 | "request::default_layouts",
6 | function()
7 | awful.layout.append_default_layouts(
8 | {
9 | awful.layout.suit.tile,
10 | awful.layout.suit.floating,
11 | awful.layout.suit.magnifier,
12 | awful.layout.suit.fair.horizontal
13 | }
14 | )
15 | end
16 | )
17 |
--------------------------------------------------------------------------------
/utilities/init.lua:
--------------------------------------------------------------------------------
1 | -- Notifications loaded first for errors
2 | require("utilities.notifications")
3 |
4 | -- Helper functions
5 | require("utilities.helpers")
6 |
7 | -- Client rules
8 | require("utilities.rules")
9 |
10 | -- Autostart apps
11 | require("utilities.autostart")
12 |
13 | -- Layouts
14 | require("utilities.layouts")
15 |
16 | -- Bling, utilities for AwesomeWM
17 | require("utilities.bling")
18 |
19 | -- Sloppy focus
20 | require("utilities.focus")
21 |
22 | -- Scratchpads
23 | require "utilities.scratchpads"
24 |
--------------------------------------------------------------------------------
/ui/wallpaper.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local beautiful = require("beautiful")
3 | local wibox = require("wibox")
4 |
5 | -- Wallpaper
6 | screen.connect_signal(
7 | "request::wallpaper",
8 | function(s)
9 | awful.wallpaper {
10 | screen = s,
11 | widget = {
12 | image = beautiful.wallpaper,
13 | valign = "center",
14 | halign = "center",
15 | resize = false,
16 | widget = wibox.widget.imagebox
17 | }
18 | }
19 | end
20 | )
21 |
--------------------------------------------------------------------------------
/ui/menu.lua:
--------------------------------------------------------------------------------
1 | local hotkeys_popup = require("awful.hotkeys_popup")
2 | require("awful.hotkeys_popup.keys")
3 | require("awful.autofocus")
4 |
5 | -- AwesomeWM modules
6 | local awful = require("awful")
7 | local beautiful = require("beautiful")
8 | local menubar = require("menubar")
9 |
10 | -- Menu & Submenu --
11 | awesomemenu = {
12 | {
13 | "Hotkeys",
14 | function()
15 | hotkeys_popup.show_help(nil, awful.screen.focused())
16 | end
17 | },
18 | { "Config", editor .. " " .. awesome.conffile },
19 | { "Restart", awesome.restart },
20 | {
21 | "Quit",
22 | function()
23 | awesome.quit()
24 | end
25 | }
26 | }
27 |
28 | mainmenu =
29 | awful.menu (
30 | {
31 | items = {
32 | { "Awesome", awesomemenu },
33 | { "Terminal", terminal },
34 | { "Music", music_player },
35 | { "Monitor", monitor },
36 | { "Browser", browser }
37 | }
38 | }
39 | )
40 |
41 | -- Set terminal for applications which need it
42 | menubar.utils.terminal = terminal
43 |
--------------------------------------------------------------------------------
/ui/widgets/battery.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local lain = require("lain")
3 | local beautiful = require("beautiful")
4 | local dpi = beautiful.xresources.apply_dpi
5 |
6 | battery =
7 | lain.widget.bat {
8 | settings = function()
9 | widget:set_markup(colourise("Battery:\n", beautiful.primary) .. '' .. bat_now.perc .. "%")
10 | bat_notification_charged_preset = {
11 | bg = beautiful.bg_normal,
12 | timeout = 5,
13 | title = 'Battery full charged!',
14 | text = "You can now unplug the cable."
15 | }
16 | bat_notification_low_preset = {
17 | bg = beautiful.bg_normal,
18 | timeout = 5,
19 | title = 'Battery low!',
20 | text = "Plug in the cable."
21 | }
22 | bat_notification_critical_preset = {
23 | timeout = 5,
24 | bg = beautiful.bg_normal,
25 | title = 'Battery critical!',
26 | text = "Impending doom approaches!."
27 | }
28 | end,
29 | notify = "off",
30 | batteries = {"BAT1", "BAT2"}
31 | }
32 |
--------------------------------------------------------------------------------
/keymaps/mouse.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 |
3 | --- Mouse bindings ---
4 | -- Basic clicking functionality
5 | client.connect_signal(
6 | "request::default_mousebindings",
7 | function()
8 | awful.mouse.append_client_mousebindings(
9 | {
10 | awful.button(
11 | {},
12 | 1,
13 | function(c)
14 | c:activate {context = "mouse_click"}
15 | end
16 | ),
17 | awful.button(
18 | {modkey},
19 | 1,
20 | function(c)
21 | c:activate {context = "mouse_click", action = "mouse_move"}
22 | end
23 | ),
24 | awful.button(
25 | {modkey},
26 | 3,
27 | function(c)
28 | c:activate {context = "mouse_click", action = "mouse_resize"}
29 | end
30 | )
31 | }
32 | )
33 | end
34 | )
35 |
36 | -- Extras
37 | awful.mouse.append_global_mousebindings(
38 | {
39 | awful.button(
40 | {},
41 | 3,
42 | function()
43 | mainmenu:toggle()
44 | end
45 | ),
46 | awful.button({}, 4, awful.tag.viewprev),
47 | awful.button({}, 5, awful.tag.viewnext)
48 | }
49 | )
50 |
--------------------------------------------------------------------------------
/rc.lua:
--------------------------------------------------------------------------------
1 | -- Load luarocks if installed, otherwise do nothing
2 | pcall(require, "luarocks.loader")
3 |
4 | -- Autofocus and hotkeys_popup
5 | require("awful.hotkeys_popup.keys")
6 | require("awful.autofocus")
7 |
8 | -- AwesomeWM modules
9 | local gears = require("gears")
10 | local beautiful = require("beautiful")
11 | local dpi = require("beautiful.xresources").apply_dpi
12 |
13 | -- Initialize theme
14 | beautiful.init(gears.filesystem.get_configuration_dir() .. "ui/theme.lua")
15 |
16 | -- Variables --
17 |
18 | -- Screenshot directory
19 | screenshot_path = os.getenv("HOME") .. "/Pictures/Screenshots/"
20 | -- Terminal emulator
21 | terminal = "alacritty"
22 | -- Editor. This will be run directly
23 | editor = "emacsclient -c"
24 | -- Modkey. Can either be Mod4 (Super) or Mod1 (Alt)
25 | modkey = "Mod4"
26 | -- File manager, will be run directly
27 | file_manager = terminal .. " -e ranger"
28 | -- Music player, will be run directly
29 | music_player = terminal .. " -e ncmpcpp"
30 | -- Web browser
31 | browser = "qutebrowser"
32 | -- System monitor
33 | monitor = terminal .. " -e btm"
34 | -- Chat client
35 | chat = "discord-canary --no-sandbox --ignore-gpu-blocklist --disable-features=UseOzonePlatform --enable-features=VaapiVideoDecoder --use-gl=desktop --enable-gpu-rasterization --enable-zero-copy"
36 | -- PDF Viewer
37 | pdf = "zathura"
38 | -- Screen locker
39 | locker = "slock"
40 |
41 | -- User modules
42 | require("utilities")
43 | require("ui")
44 | require("keymaps")
45 |
--------------------------------------------------------------------------------
/utilities/helpers.lua:
--------------------------------------------------------------------------------
1 | local wibox = require("wibox")
2 | local beautiful = require("beautiful")
3 | local awful = require("awful")
4 | local naughty = require("naughty")
5 | local dpi = beautiful.xresources.apply_dpi
6 |
7 | function colourise(text, fg)
8 | if fg == "" then
9 | fg = beautiful.primary
10 | end
11 | return "" .. text .. ""
12 | end
13 |
14 | function icon(code, colour, size, but)
15 | return wibox.widget {
16 | font = beautiful.icon_font_sizeable .. " " .. size,
17 | markup = "" .. code .. "",
18 | align = "center",
19 | valign = "center",
20 | buttons = but,
21 | widget = wibox.widget.textbox,
22 | }
23 | end
24 |
25 | function text(text, size, colour)
26 | return wibox.widget {
27 | font = beautiful.font_sizeable .. "" .. size,
28 | markup = '' .. text .. "",
29 | align = "center",
30 | valign = "center",
31 | halign = "center",
32 | widget = wibox.widget.textbox
33 | }
34 | end
35 |
36 | function distext(text)
37 | return wibox.widget {
38 | font = beautiful.font,
39 | markup = '' .. text .. "",
40 | widget = wibox.widget.textbox
41 | }
42 | end
43 |
44 | function notify(title, description, outtime)
45 | return naughty.notify {
46 | border_color = beautiful.bg_normal,
47 | timeout = outtime,
48 | bg = beautiful.bg_normal,
49 | title = '' .. title .. "",
50 | text = description
51 | }
52 | end
53 |
--------------------------------------------------------------------------------
/utilities/rules.lua:
--------------------------------------------------------------------------------
1 | local ruled = require('ruled')
2 | local awful = require('awful')
3 |
4 | --- Rules ---
5 | ruled.client.connect_signal('request::rules', function()
6 | -- All clients will match this rule.
7 | ruled.client.append_rule {
8 | id = 'global',
9 | rule = {},
10 | properties = {
11 | focus = awful.client.focus.filter,
12 | raise = true,
13 | screen = awful.screen.preferred,
14 | placement = awful.placement.no_overlap+awful.placement.no_offscreen
15 | }
16 | }
17 |
18 | -- Floating clients.
19 | ruled.client.append_rule {
20 | id = 'floating',
21 | rule_any = {
22 | instance = { 'copyq', 'pinentry' },
23 | class = {
24 | 'Arandr', 'Blueman-manager', 'Gpick', 'Kruler', 'Sxiv',
25 | 'Tor Browser', 'Wpa_gui', 'veromix', 'xtightvncviewer'
26 | },
27 | name = { 'Event Tester', },
28 | role = { 'AlarmWindow', 'ConfigManager', 'pop-up', }
29 | },
30 | properties = { floating = true }
31 | }
32 |
33 | ruled.client.append_rule {
34 | rule = { class = 'Gcr-prompter' },
35 | properties = {
36 | placement = awful.placement.centered,
37 | floating = true,
38 | }
39 | }
40 | ruled.client.append_rule {
41 | rule = { class = 'discord' },
42 | properties = {
43 | screen = 1, tag = '4', switch_to_tags = true
44 | }
45 | }
46 | ruled.client.append_rule {
47 | rule = { class = 'qutebrowser' },
48 | properties = { screen = 1, tag = '2', switch_to_tags = true, fullscreen = true }
49 | }
50 | ruled.client.append_rule {
51 | rule = { class = 'zoom' },
52 | properties = { screen = 1, tag = '6', switch_to_tags = true, floating = true }
53 | }
54 | end)
55 |
56 |
--------------------------------------------------------------------------------
/utilities/notifications.lua:
--------------------------------------------------------------------------------
1 | local ruled = require("ruled")
2 | local awful = require("awful")
3 | local lain = require("lain")
4 | local naughty = require("naughty")
5 | local beautiful = require("beautiful")
6 | local dpi = beautiful.xresources.apply_dpi
7 |
8 | -- Notificaton on errors
9 | naughty.connect_signal(
10 | "request::display_error",
11 | function(message, startup)
12 | naughty.notification {
13 | urgency = "critical",
14 | title = "An error occured" .. (startup and " during startup"),
15 | message = message
16 | }
17 | end
18 | )
19 |
20 | -- Enable notifications
21 | ruled.notification.connect_signal(
22 | "request::rules",
23 | function()
24 | -- All notifications will match this rule.
25 | ruled.notification.append_rule {
26 | rule = {},
27 | properties = {
28 | screen = awful.screen.preferred,
29 | implicit_timeout = 5,
30 | }
31 | }
32 | end
33 | )
34 |
35 | naughty.connect_signal (
36 | "request::display", function(n)
37 | n.title = string.format("%s", n.title)
38 | n.margin = dpi(15)
39 | naughty.layout.box {
40 | notification = n,
41 | }
42 | end)
43 |
44 | -- MPD Notifications
45 | mpd_widget =
46 | lain.widget.mpd {
47 | timeout = 1,
48 | settings = function()
49 | mpd_notification_preset = {
50 | bg = beautiful.bg_normal,
51 | timeout = 1,
52 | fg = beautiful.text,
53 | title = '' .. "Now playing" .. "",
54 | text = mpd_now.title .. " - " .. mpd_now.artist
55 | }
56 | end
57 | }
58 |
--------------------------------------------------------------------------------
/ui/widgets/calendar.lua:
--------------------------------------------------------------------------------
1 | local wibox = require "wibox"
2 | local beautiful = require "beautiful"
3 | local dpi = beautiful.xresources.apply_dpi
4 | local styles = {}
5 |
6 | styles.month = {
7 | padding = 10,
8 | }
9 |
10 | styles.normal = {
11 | markup = function(t)
12 | return "" .. t .. ""
13 | end,
14 | }
15 |
16 | styles.focus = {
17 | fg_color = beautiful.secondary,
18 | markup = function(t)
19 | return "" .. t .. ""
20 | end,
21 | }
22 |
23 | styles.header = {
24 | markup = function(t)
25 | return "" .. t .. ""
26 | end,
27 | }
28 | styles.weekday = {
29 | markup = function(t)
30 | return "" .. t .. ""
31 | end,
32 | }
33 |
34 | local function decorate_cell(widget, flag, date)
35 | if flag == "monthheader" and not styles.monthheader then
36 | flag = "header"
37 | end
38 | local props = styles[flag] or {}
39 | if props.markup and widget.get_text and widget.set_markup then
40 | widget:set_markup(props.markup(widget:get_text()))
41 | end
42 | -- Change bg color for weekends
43 | local default_bg = beautiful.bg_normal
44 | local ret = wibox.widget {
45 | {
46 | widget,
47 | margins = (props.padding or 2) + (props.border_width or 0),
48 | widget = wibox.container.margin,
49 | },
50 | shape = props.shape,
51 | fg = props.fg_color or beautiful.fg_normal,
52 | widget = wibox.container.background,
53 | }
54 | return ret
55 | end
56 |
57 | calendar_widget = wibox.widget {
58 | date = os.date "*t",
59 | spacing = dpi(8),
60 | fn_embed = decorate_cell,
61 | widget = wibox.widget.calendar.month,
62 | }
63 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Aweful
2 | This repository contains my AwesomeWM configuration, made with lots of **Love**. Feel free to steal anything you need.
3 |
4 | ## Installation
5 |
6 | ### Dependencies
7 |
8 | **Aweful** requires that some programs be installed to the host system in order to be fully functional. Below is a list of those which fit this category.
9 |
10 | - `xclip`
11 | - `pamixer`
12 | - `rofi`
13 | - `scrot`
14 | - `xrdb`
15 |
16 | > Please keep in mind that all of these are optional for the configuration to load, but necessary if you want some functionality (for example, `scrot` is required for screenshots)
17 |
18 | > An appropriately placed `.Xresources` with colour configuration is also essential.
19 |
20 | #### Fonts
21 |
22 | **Aweful** depends on the fonts `Iosevka` and `Font Awesome 6 Pro`, so make sure to have them installed as well.
23 |
24 | ### User Configuration
25 |
26 | Additionally, all keys bound to an application (those in the **Applications** category) point to an easily customisable variable in `rc.lua` which contain the application to be launched. I recommend you go into the file and change the variables to your liking (e.g. change the 'browser' varianle to your choice of browser). Here's a list of all the variables that can be easily changed:
27 |
28 | - `terminal`
29 | - `editor`
30 | - `modkey`
31 | - `file_manager`
32 | - `music_player`
33 | - `browser`
34 | - `monitor`
35 | - `chat`
36 |
37 | > Further explanation of the variables is offered in the `rc.lua` file.
38 |
39 | ### Cloning
40 |
41 | **Aweful** utilises the `bling` and `lain` AwesomeWM modules, which are necessary for the config to load successfully. These are their seperate git repositories, so clone this repository with them as follows:
42 |
43 | ```
44 | git clone --recurse-submodules https://github.com/devraza/aweful
45 | ```
46 |
47 | Links to submodules are also provided in this document.
48 |
49 | ## Submodules
50 |
51 | The following submodules are used:
52 | - `bling` - Utilities for the awesome window manager - https://github.com/BlingCorp/bling
53 | - `lain` - Awesome WM complements - https://github.com/lcpz/lain
54 |
--------------------------------------------------------------------------------
/ui/dashboard.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local wibox = require("wibox")
3 | local gears = require("gears")
4 | local beautiful = require("beautiful")
5 | local dpi = beautiful.xresources.apply_dpi
6 |
7 | dashboard = awful.popup {
8 | widget = {
9 | {
10 | {
11 | {
12 | forced_height = dpi(70),
13 | forced_width = dpi(100),
14 | widget = wibox.container.background(wibox.container.place(battery))
15 | },
16 | bg = beautiful.bg_light,
17 | clip = true,
18 | widget = wibox.container.background
19 | },
20 | spacing = dpi(16),
21 | layout = wibox.layout.fixed.vertical,
22 | },
23 | {
24 | {
25 | forced_height = dpi(240),
26 | forced_width = dpi(220),
27 | widget = wibox.container.place(calendar_widget)
28 | },
29 | bg = beautiful.bg_light,
30 | clip = true,
31 | widget = wibox.container.background
32 | },
33 | {
34 | {
35 | {
36 | {
37 | forced_height = dpi(60),
38 | forced_width = dpi(60),
39 | widget = icon("\u{f023}", beautiful.tertiary, 20, {
40 | awful.button({}, 1, nil, function ()
41 | awful.spawn(locker)
42 | end)
43 | })
44 | },
45 | bg = beautiful.bg_light,
46 | clip = true,
47 | widget = wibox.container.background
48 | },
49 | {
50 | {
51 | forced_height = dpi(60),
52 | forced_width = dpi(60),
53 | widget = icon("\u{f011}", beautiful.negative, 20, {
54 | awful.button({}, 1, nil, function ()
55 | awful.spawn("sudo poweroff")
56 | end),
57 | awful.button({}, 3, nil, function ()
58 | awful.spawn("sudo reboot")
59 | end)
60 | })
61 | },
62 | bg = beautiful.bg_light,
63 | clip = true,
64 | widget = wibox.container.background
65 | },
66 | spacing = dpi(16),
67 | layout = wibox.layout.fixed.vertical,
68 | },
69 | {
70 | {
71 | {
72 | forced_height = dpi(60),
73 | forced_width = dpi(60),
74 | widget = icon("\u{f565}", beautiful.primary, 20, {
75 | awful.button({}, 1, nil, function ()
76 | delayed_screenshot {
77 | auto_save_delay = 5,
78 | file_path = screenshot_path .. os.date("%d.%m.%Y-%H:%M:%S") .. ".png",
79 |
80 | }
81 | end)
82 | })
83 | },
84 | bg = beautiful.bg_light,
85 | clip = true,
86 | widget = wibox.container.background
87 | },
88 | spacing = dpi(16),
89 | layout = wibox.layout.fixed.vertical,
90 | },
91 | spacing = dpi(16),
92 | layout = wibox.layout.fixed.horizontal,
93 | },
94 | spacing = dpi(16),
95 | layout = wibox.layout.fixed.horizontal,
96 | },
97 | border_width = dpi(16),
98 | border_color = beautiful.bg_normal,
99 | placement = awful.placement.centered,
100 | ontop = true,
101 | visible = false,
102 | }
103 |
--------------------------------------------------------------------------------
/ui/theme.lua:
--------------------------------------------------------------------------------
1 | local theme_assets = require("beautiful.theme_assets")
2 | local xresources = require("beautiful.xresources")
3 | local naughty = require("naughty")
4 | local ruled = require("ruled")
5 | local dpi = xresources.apply_dpi
6 | local xrdb = xresources.get_current_theme()
7 | local gears = require("gears")
8 | local themes_path = gears.filesystem.get_themes_dir()
9 | local icon_path = gears.filesystem.get_configuration_dir() .. "assets/icons/"
10 |
11 | -- Inherit default theme
12 | local theme = dofile(themes_path .. "default/theme.lua")
13 |
14 | -- Custom colours
15 | theme.primary = xrdb.color4
16 | theme.text = xrdb.foreground
17 | theme.secondary = xrdb.color5
18 | theme.tertiary = xrdb.color2
19 | theme.negative = xrdb.color1
20 | theme.positive = xrdb.color3
21 | theme.disabled = xrdb.color8
22 |
23 | -- Font and resizable font (append a size as a string)
24 | theme.font = "Iosevka SS12 12"
25 | theme.font_sizeable = "Iosevka SS12 "
26 |
27 | -- Icon font and resizable icon font (appand a size as a string)
28 | theme.icon_font = "Font Awesome 6 Pro 12.5"
29 | theme.icon_font_sizeable = "Font Awesome 6 Pro "
30 | theme.icon_color = theme.primary
31 |
32 | -- Theme variables
33 | theme.bg_normal = xrdb.background
34 | theme.bg_focus = theme.primary
35 | theme.bg_light = xrdb.color0
36 | theme.bg_dark = "#0d0d0d"
37 |
38 | theme.fg_normal = xrdb.foreground
39 | theme.fg_focus = theme.bg_normal
40 | theme.fg_urgent = theme.bg_normal
41 | theme.fg_minimize = theme.bg_normal
42 |
43 | theme.useless_gap = dpi(6)
44 | theme.border_width = dpi(2)
45 | theme.border_color_normal = theme.disabled
46 | theme.border_color_active = theme.primary
47 |
48 | theme.tooltip_fg = theme.fg_normal
49 | theme.tooltip_bg = theme.bg_normal
50 |
51 | -- Notifications
52 | theme.notification_bg = xrdb.background
53 | theme.notification_border_color = xrdb.background
54 | theme.notification_border_width = dpi(10)
55 |
56 | -- Snapping
57 | theme.snap_border_width = 1
58 | theme.snap_bg = theme.secondary
59 |
60 | -- Recolor layout icons:
61 | theme = theme_assets.recolor_layout(theme, theme.fg_normal)
62 |
63 | -- Define the icon theme for application icons.
64 | theme.icon_theme = nil
65 |
66 | -- Generate Awesome icon:
67 | theme.awesome_icon = theme_assets.awesome_icon(theme.menu_height, theme.disabled, theme.bg_normal)
68 |
69 | -- Taglist colours
70 | theme.taglist_fg_focus = theme.secondary
71 | theme.taglist_bg_focus = "#00000000"
72 | theme.taglist_fg_urgent = "#00000000"
73 | theme.taglist_bg_urgent = theme.secondary
74 |
75 | -- Screenshots
76 | theme.screenshot_frame_color = theme.secondary
77 |
78 | -- Increase spacing between taglist items
79 | theme.taglist_spacing = dpi(6)
80 |
81 | -- Tasklist
82 | theme.tasklist_fg_focus = theme.secondary
83 | theme.tasklist_fg_minimize = theme.disabled
84 | theme.tasklist_plain_task_name = true
85 | theme.tasklist_spacing = dpi(10)
86 |
87 | -- Menu
88 | theme.menu_submenu_icon = gears.color.recolor_image(icon_path .. "submenu.png", theme.fg_normal)
89 | theme.menu_bg_focus = theme.bg_normal
90 | theme.menu_fg_focus = theme.secondary
91 | theme.menu_height = dpi(30)
92 | theme.menu_width = dpi(150)
93 |
94 | -- Calender
95 | theme.calendar_font = theme.font
96 | theme.calendar_spacing = dpi(5)
97 |
98 | -- Disable taglist squares:
99 | local taglist_square_size = dpi(0)
100 | theme.taglist_squares_sel = theme_assets.taglist_squares_sel(taglist_square_size, theme.primary)
101 | theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel(taglist_square_size, theme.primary)
102 |
103 | -- Set the wallpaper
104 | theme.wallpaper = gears.filesystem.get_configuration_dir() .. "assets/wallpapers/wallpaper.png"
105 |
106 | -- Set different colors for urgent notifications.
107 | ruled.notification.connect_signal(
108 | "request::rules",
109 | function()
110 | ruled.notification.append_rule {
111 | rule = { urgency = "critical" },
112 | properties = {
113 | bg = theme.bg_normal,
114 | fg = theme.negative,
115 | }
116 | }
117 | end
118 | )
119 |
120 | -- Return the theme
121 | return theme
122 |
--------------------------------------------------------------------------------
/ui/panel.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local wibox = require("wibox")
3 | local beautiful = require("beautiful")
4 | local dpi = beautiful.xresources.apply_dpi
5 | local naughty = require("naughty")
6 | local gears = require("gears")
7 |
8 | --- Wibar ---
9 | screen.connect_signal(
10 | "request::desktop_decoration",
11 | function(s)
12 | -- Each screen has its own tag table.
13 | local names = {"1", "2", "3", "4", "5", "6"}
14 | local l = awful.layout.suit
15 | local layouts = {l.tile, l.tile, l.tile, l.tile, l.tile, l.floating}
16 | awful.tag(names, s, layouts)
17 |
18 | -- Prompt
19 | s.prompt = awful.widget.prompt()
20 |
21 | local layoutbox =
22 | awful.widget.layoutbox {
23 | screen = s,
24 | forced_width = dpi(20),
25 | -- Add buttons, allowing you to change the layout
26 | buttons = {
27 | awful.button(
28 | {},
29 | 1,
30 | function()
31 | awful.layout.inc(1)
32 | end
33 | ),
34 | awful.button(
35 | {},
36 | 3,
37 | function()
38 | awful.layout.inc(-1)
39 | end
40 | ),
41 | awful.button(
42 | {},
43 | 4,
44 | function()
45 | awful.layout.inc(1)
46 | end
47 | ),
48 | awful.button(
49 | {},
50 | 5,
51 | function()
52 | awful.layout.inc(-1)
53 | end
54 | )
55 | }
56 | }
57 |
58 | -- Layout icon
59 | s.layout =
60 | awful.widget.layoutbox {
61 | screen = s,
62 | buttons = {
63 | awful.button(
64 | {},
65 | 1,
66 | function()
67 | awful.layout.inc(1)
68 | end
69 | ),
70 | awful.button(
71 | {},
72 | 3,
73 | function()
74 | awful.layout.inc(-1)
75 | end
76 | ),
77 | awful.button(
78 | {},
79 | 4,
80 | function()
81 | awful.layout.inc(-1)
82 | end
83 | ),
84 | awful.button(
85 | {},
86 | 5,
87 | function()
88 | awful.layout.inc(1)
89 | end
90 | )
91 | }
92 | }
93 |
94 | -- Create a taglist widget
95 | s.taglist =
96 | awful.widget.taglist {
97 | screen = s,
98 | filter = awful.widget.taglist.filter.all,
99 | layout = {
100 | spacing = dpi(6),
101 | layout = wibox.layout.fixed.vertical
102 | },
103 | buttons = {
104 | awful.button(
105 | {},
106 | 1,
107 | function(t)
108 | t:view_only()
109 | end
110 | ),
111 | awful.button(
112 | {modkey},
113 | 1,
114 | function(t)
115 | if client.focus then
116 | client.focus:move_to_tag(t)
117 | end
118 | end
119 | ),
120 | awful.button({}, 3, awful.tag.viewtoggle),
121 | awful.button(
122 | {modkey},
123 | 3,
124 | function(t)
125 | if client.focus then
126 | client.focus:toggle_tag(t)
127 | end
128 | end
129 | ),
130 | awful.button(
131 | {},
132 | 4,
133 | function(t)
134 | awful.tag.viewprev(t.screen)
135 | end
136 | ),
137 | awful.button(
138 | {},
139 | 5,
140 | function(t)
141 | awful.tag.viewnext(t.screen)
142 | end
143 | )
144 | }
145 | }
146 |
147 | local aweful_icon = wibox.widget {
148 | image = beautiful.awesome_icon,
149 | resize = true,
150 | forced_width = dpi(17),
151 | widget = wibox.widget.imagebox,
152 | buttons = {
153 | awful.button({}, 1, nil, function ()
154 | if dashboard.visible == false then
155 | dashboard.visible = true
156 | else
157 | dashboard.visible = false
158 | end
159 | end)
160 | }
161 | }
162 |
163 | s.top_panel =
164 | awful.wibar {
165 | position = "left",
166 | width = dpi(34),
167 | forced_height = dpi(20),
168 | screen = s,
169 | widget = {
170 | layout = wibox.layout.align.vertical,
171 | {
172 | -- Top widgets
173 | wibox.container.margin(wibox.container.place(aweful_icon), 0, 0, dpi(9)),
174 | wibox.container.margin(wibox.container.place(s.taglist), 0, 0, dpi(-1)),
175 | layout = wibox.layout.fixed.vertical
176 | }, -- Center widget
177 | wibox.container.place(),
178 | {
179 | -- Bottom widgets
180 | layout = wibox.layout.fixed.vertical,
181 | wibox.container.margin(wibox.container.place(clock)),
182 | wibox.container.margin(wibox.container.place(layoutbox), 0, 0, dpi(16)),
183 | }
184 | }
185 | }
186 | end
187 | )
188 |
--------------------------------------------------------------------------------
/keymaps/keyboard.lua:
--------------------------------------------------------------------------------
1 | local awful = require("awful")
2 | local hotkeys_popup = require("awful.hotkeys_popup")
3 | local naughty = require("naughty")
4 | local beautiful = require("beautiful")
5 |
6 | --- Keybindings ---
7 | -- The defaults
8 | client.connect_signal(
9 | "request::default_keybindings",
10 | function()
11 | awful.keyboard.append_client_keybindings(
12 | {
13 | awful.key(
14 | { modkey },
15 | "f",
16 | function(c)
17 | c.fullscreen = not c.fullscreen
18 | c:raise()
19 | end,
20 | { description = "Toggle fullscreen", group = "Client" }
21 | ),
22 | awful.key(
23 | { modkey, "Shift" },
24 | "c",
25 | function(c)
26 | c:kill()
27 | end,
28 | { description = "Close client", group = "Client" }
29 | ),
30 | awful.key(
31 | { modkey },
32 | "w",
33 | awful.client.floating.toggle,
34 | { description = "Toggle floating", group = "Client" }
35 | ),
36 | awful.key(
37 | { modkey, "Shift" },
38 | "Return",
39 | function(c)
40 | c:swap(awful.client.getmaster())
41 | end,
42 | { description = "Move to top", group = "Client" }
43 | ),
44 | awful.key(
45 | {modkey},
46 | "o",
47 | function(c)
48 | c:move_to_screen()
49 | end,
50 | {description = "Move to screen", group = "Client"}
51 | ),
52 | awful.key(
53 | {modkey},
54 | "n",
55 | function(c)
56 | c.minimized = true
57 | end,
58 | {description = "Minimize", group = "Client"}
59 | ),
60 | awful.key(
61 | {modkey},
62 | "m",
63 | function(c)
64 | c.maximized = not c.maximized
65 | c:raise()
66 | end,
67 | {description = "Maximize", group = "Client"}
68 | ),
69 | awful.key(
70 | {modkey, "Control"},
71 | "m",
72 | function(c)
73 | c.maximized_vertical = not c.maximized_vertical
74 | c:raise()
75 | end,
76 | {description = "Maximize vertically", group = "Client"}
77 | ),
78 | awful.key(
79 | {modkey, "Shift"},
80 | "m",
81 | function(c)
82 | c.maximized_horizontal = not c.maximized_horizontal
83 | c:raise()
84 | end,
85 | {description = "Maximize horizontally", group = "Client"}
86 | )
87 | }
88 | )
89 | end
90 | )
91 |
92 | -- AwesomeWM keybinds
93 | awful.keyboard.append_global_keybindings(
94 | {
95 | awful.key({modkey}, "s", hotkeys_popup.show_help, {description = "Show help", group = "Awesome"}),
96 | awful.key({modkey, "Shift"}, "r", awesome.restart, {description = "Reload", group = "Awesome"}),
97 | awful.key({modkey, "Shift"}, "q", awesome.quit, {description = "Quit", group = "Awesome"}),
98 | awful.key(
99 | { modkey },
100 | "q",
101 | function ()
102 | if dashboard.visible == false then
103 | dashboard.visible = true
104 | else
105 | dashboard.visible = false
106 | end
107 | end,
108 | { description = "Toggle Dashboard", group = "Awesome" }
109 | ),
110 | awful.key(
111 | { modkey },
112 | "t",
113 | function ()
114 | scratch:toggle()
115 | end,
116 | { description = "Toggle Scratchpad", group = "Awesome" }
117 | ),
118 | awful.key(
119 | {modkey},
120 | "Return",
121 | function()
122 | awful.spawn(terminal)
123 | end,
124 | {description = "Terminal", group = "Awesome"}
125 | ),
126 |
127 | -- Audio control, using pamixer. Supports PipeWire PulseAudio server
128 | awful.key(
129 | {modkey, "Control"},
130 | "j",
131 | function()
132 | awful.spawn("pamixer -d 10")
133 | awful.spawn.easy_async_with_shell("pamixer --get-volume-human", function(stdout)
134 | notify("Volume", stdout:gsub("\n[^\n]*$", ""), 0.6)
135 | end)
136 | end,
137 | {description = "Volume -10%", group = "Volume"}
138 | ),
139 | awful.key(
140 | {modkey, "Control"},
141 | "k",
142 | function()
143 | awful.spawn("pamixer -i 10")
144 | awful.spawn.easy_async_with_shell("pamixer --get-volume-human", function(stdout)
145 | notify("Volume", stdout:gsub("\n[^\n]*$", ""), 0.6)
146 | end)
147 | end,
148 | {description = "Volume +10%", group = "Volume"}
149 | ),
150 | awful.key(
151 | {modkey, "Control"},
152 | "l",
153 | function()
154 | awful.spawn("pamixer -t")
155 | awful.spawn.easy_async_with_shell("pamixer --get-volume-human", function(stdout)
156 | notify("Volume", stdout:gsub("\n[^\n]*$", ""), 0.6)
157 | end)
158 | end,
159 | {description = "Toggle mute", group = "Volume"}
160 | ),
161 | awful.key (
162 | { modkey, "Control", "Shift" },
163 | "a",
164 | function()
165 | awful.spawn.with_shell("sudo poweroff")
166 | end,
167 | { description = "Poweroff", group = "Powermenu" }),
168 | awful.key (
169 | { modkey, "Control", "Shift" },
170 | "s",
171 | function()
172 | awful.spawn.with_shell("sudo reboot")
173 | end,
174 | { description = "Reboot", group = "Powermenu" }),
175 |
176 | -- Rofi
177 | awful.key(
178 | {modkey},
179 | "space",
180 | function()
181 | awful.spawn("rofi -show drun -dpi 96")
182 | end,
183 | {description = "Launch Application", group = "Rofi"}
184 | ),
185 | awful.key(
186 | {modkey, "Shift"},
187 | "space",
188 | function()
189 | awful.spawn("rofi -show run -dpi 96")
190 | end,
191 | {description = "Run Command", group = "Rofi"}
192 | ),
193 |
194 | -- MPC
195 | awful.key(
196 | { "Mod1", "Shift"},
197 | "h",
198 | function()
199 | awful.spawn("mpc prev")
200 | end,
201 | { description = "Previous track", group = "MPD" }
202 | ),
203 | awful.key(
204 | { "Mod1", "Shift"},
205 | "j",
206 | function()
207 | awful.spawn("mpc pause")
208 | end,
209 | { description = "Pause track", group = "MPD" }
210 | ),
211 | awful.key(
212 | { "Mod1", "Shift"},
213 | "k",
214 | function()
215 | awful.spawn("mpc play")
216 | end,
217 | { description = "Resume track", group = "MPD" }
218 | ),
219 | awful.key(
220 | { "Mod1", "Shift"},
221 | "l",
222 | function()
223 | awful.spawn("mpc next")
224 | end,
225 | { description = "Next track", group = "MPD" }
226 | ),
227 |
228 | awful.key(
229 | { "Mod1", "Shift"},
230 | "u",
231 | function()
232 | awful.spawn("mpc volume -10")
233 | end,
234 | { description = "Volume -10%", group = "MPD" }
235 | ),
236 | awful.key(
237 | { "Mod1", "Shift"},
238 | "i",
239 | function()
240 | awful.spawn("mpc volume +10")
241 | end,
242 | { description = "Volume +10%", group = "MPD" }
243 | ),
244 |
245 | -- Screenshot
246 | awful.key(
247 | {modkey, "Shift"},
248 | "a",
249 | function()
250 | timestamp = os.date("%d.%m.%Y-%H:%M:%S")
251 | awful.spawn.with_shell(
252 | "scrot " .. screenshot_path ..
253 | timestamp .. ".png -e 'xclip -t image/png -selection clipboard -i $f'"
254 | )
255 | end,
256 | { description = "Capture screen", group = "Screenshot" }
257 | ),
258 | awful.key(
259 | {modkey, "Shift"},
260 | "s",
261 | function()
262 | timestamp = os.date("%d.%m.%Y-%H:%M:%S")
263 | awful.spawn.with_shell(
264 | "scrot -s -f " .. screenshot_path ..
265 | timestamp .. ".png -e 'xclip -t image/png -selection clipboard -i $f'"
266 | )
267 | end,
268 | { description = "Capture area", group = "Screenshot" }
269 | ),
270 | awful.key(
271 | {modkey, "Shift"},
272 | "d",
273 | function()
274 | timestamp = os.date("%d.%m.%Y-%H:%M:%S")
275 | awful.spawn.with_shell(
276 | "scrot -u " .. screenshot_path ..
277 | timestamp .. ".png -e 'xclip -t image/png -selection clipboard -i $f'"
278 | )
279 | end,
280 | {description = "Capture window", group = "Screenshot"}
281 | ),
282 |
283 | -- Applications
284 | awful.key(
285 | {modkey},
286 | "a",
287 | function()
288 | awful.spawn(file_manager)
289 | end,
290 | {description = "File Manager", group = "Applications"}
291 | ),
292 | awful.key(
293 | {modkey},
294 | "x",
295 | function()
296 | awful.spawn.with_shell(pdf)
297 | end,
298 | {description = "PDF Viewer", group = "Applications"}
299 | ),
300 | awful.key(
301 | {modkey},
302 | "z",
303 | function()
304 | awful.spawn(music_player)
305 | end,
306 | {description = "Music Player", group = "Applications"}
307 | ),
308 | awful.key(
309 | {modkey},
310 | "c",
311 | function()
312 | awful.spawn(chat)
313 | end,
314 | {description = "Chat Client", group = "Applications"}
315 | ),
316 | awful.key(
317 | {modkey},
318 | "e",
319 | function()
320 | awful.spawn(editor)
321 | end,
322 | {description = "Editor", group = "Applications"}
323 | ),
324 | awful.key(
325 | {modkey},
326 | "b",
327 | function()
328 | awful.spawn(browser)
329 | end,
330 | {description = "Browser", group = "Applications"}
331 | ),
332 | awful.key(
333 | {modkey},
334 | "d",
335 | function()
336 | awful.spawn(monitor)
337 | end,
338 | {description = "System Monitor", group = "Applications"}
339 | ),
340 | awful.key(
341 | {modkey, "Shift"},
342 | "l",
343 | function()
344 | awful.spawn(locker)
345 | end,
346 | {description = "Screen Locker", group = "Applications"}
347 | ),
348 |
349 | -- Tags related keybindings
350 | awful.key({modkey}, "Left", awful.tag.viewprev, {description = "Previous tag", group = "Tag"}),
351 | awful.key({modkey}, "Right", awful.tag.viewnext, {description = "Next tag", group = "Tag"}),
352 | awful.key({modkey}, "Tab", awful.tag.history.restore, {description = "Alternate tags", group = "Tag"}),
353 |
354 | -- Focus related keybindings
355 | awful.key(
356 | {modkey},
357 | "j",
358 | function()
359 | awful.client.focus.byidx(1)
360 | end,
361 | {description = "Next client", group = "Client"}
362 | ),
363 | awful.key(
364 | {modkey},
365 | "k",
366 | function()
367 | awful.client.focus.byidx(-1)
368 | end,
369 | {description = "Previous client", group = "Client"}
370 | ),
371 | awful.key(
372 | {modkey},
373 | "Escape",
374 | function()
375 | awful.client.focus.history.previous()
376 | if client.focus then
377 | client.focus:raise()
378 | end
379 | end,
380 | {description = "Alternate clients", group = "Client"}
381 | ),
382 | awful.key(
383 | {modkey, "Control", "Mod1"},
384 | "k",
385 | function()
386 | awful.screen.focus_relative(1)
387 | end,
388 | {description = "Next screen", group = "Screen"}
389 | ),
390 | awful.key(
391 | {modkey, "Control", "Mod1"},
392 | "j",
393 | function()
394 | awful.screen.focus_relative(-1)
395 | end,
396 | {description = "Previous screen", group = "Screen"}
397 | ),
398 | awful.key(
399 | {modkey, "Shift"},
400 | "n",
401 | function()
402 | local c = awful.client.restore()
403 | -- Focus restored client
404 | if c then
405 | c:activate {raise = true, context = "key.unminimize"}
406 | end
407 | end,
408 | {description = "Unminimize", group = "Client"}
409 | ),
410 |
411 | -- Layout related keybindings
412 | awful.key(
413 | {modkey, "Shift"},
414 | "j",
415 | function()
416 | awful.client.swap.byidx(1)
417 | end,
418 | {description = "Swap next client", group = "Client"}
419 | ),
420 | awful.key(
421 | {modkey, "Shift"},
422 | "k",
423 | function()
424 | awful.client.swap.byidx(-1)
425 | end,
426 | {description = "Swap previous client", group = "Client"}
427 | ),
428 | awful.key({modkey}, "u", awful.client.urgent.jumpto, {description = "Urgent client", group = "Client"}),
429 | awful.key(
430 | {modkey},
431 | "l",
432 | function()
433 | awful.tag.incmwfact(0.05)
434 | end,
435 | {description = "Increase width", group = "Layout"}
436 | ),
437 | awful.key(
438 | {modkey},
439 | "h",
440 | function()
441 | awful.tag.incmwfact(-0.05)
442 | end,
443 | {description = "Decrease width", group = "Layout"}
444 | ),
445 | awful.key(
446 | {modkey},
447 | "i",
448 | function()
449 | awful.layout.inc(1)
450 | end,
451 | {description = "Next layout", group = "Layout"}
452 | ),
453 | awful.key(
454 | {modkey},
455 | "u",
456 | function()
457 | awful.layout.inc(-1)
458 | end,
459 | {description = "Previous layout", group = "Layout"}
460 | ),
461 |
462 | awful.key {
463 | modifiers = {modkey},
464 | keygroup = "numrow",
465 | description = "Go to tag",
466 | group = "Tag",
467 | on_press = function(index)
468 | local screen = awful.screen.focused()
469 | local tag = screen.tags[index]
470 | if tag then
471 | tag:view_only()
472 | end
473 | end
474 | },
475 | awful.key {
476 | modifiers = {modkey, "Shift"},
477 | keygroup = "numrow",
478 | description = "Client to tag",
479 | group = "Tag",
480 | on_press = function(index)
481 | if client.focus then
482 | local tag = client.focus.screen.tags[index]
483 | if tag then
484 | client.focus:move_to_tag(tag)
485 | end
486 | end
487 | end
488 | },
489 | }
490 | )
491 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at https://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------