How To: Awesome WM with Debian/Ubuntu


Recommended Posts

How to: Awesome WM 2.3.4 with Debian/Ubuntu/*buntu

First, install the awesome wm package ? apt-get install awesome (which will be the 2.3.4 version)

Once installation is complete, most of the customization will be done in the .awesomerc file.

This will be located in your ~/user directory

The default setup is simple to read, for the most part, and configuration parameters are plainly laid out.

To boot into your Awesome WM session, log out of your current desktop and you should be able to select it from your session menu. In my case, I edited the .Xsession file to include awesome and all relevant programs as my xclient session.

Here is my ~/.Xsession file:

gnome-power-manager &

nm-applet & 

gnome-screensaver &

feh --bg-scale /home/lance/images/wallpapers/shared/Geeky/1270448911455.jpg

sh /home/lance/.awesome/awesomeclock.sh &



exec awesome

The above file loads the gnome-power-manager for logouts and sleep mode, along with nm-applet for wireless networking. It also displays the default wallpaper using feh (which is installable by using apt-get install feh), and a script to display a clock with the current date.

The clock script is as follows:

#!/bin/sh

while true

do

    echo "0 widget_tell mystatusbar clock text " \

         "`date +"%A %B %d, %Y %l:%M %p"`" | awesome-client

    sleep 1

done

Paste the above text into a text file and save as awesomeclock.sh in your .awesome directory.

This is called by the .awesomerc config file, which I have added below. The statusbar section will call the widgets displayed. Paste this snippet at the bottom of the statusbar section to call the clock script. The .Xsession file will call the script at boot.

 textbox clock

        {

            text = "-"

            align = "right"

        }

     }

}

I have also installed dmenu, an application launcher that displays in your status bar. In my .awesomerc, I have set up the menu to launch using the Windows (Mod4) key +p. Just type the first few letters of the application to launch, and it will be displayed in the menu. Press Enter to execute.

I am still working on getting more widgets/status displays in the status bar to show cpu, mem, and disk space. Once I get it working, I will add it to this post.

BTW, visit http://awesome.naquadah.org/wiki/Main_Page for Awesome shortcuts and tips/tricks.

Also, to check that your .awesomerc file is correct, you can type awesome -k at the command prompt in the terminal. If it is not correct, errors will be displayed.

This is by no means an end-all-be-all intro to Awesome, just something to get your feet wet.

Here is my full .awesomerc:

screen 0
{
    styles
    {
        normal
        {
            font = "sans 7"
            fg = "#cccccc"
            bg = "#444444"
            border = "#555555"
        }
        focus
        {
            fg = "#000000"
            bg = "#666666"
            border = "#535d6c"
        }
        urgent
        {
            fg = "#111111"
            bg = "#ff4500"
        }
    }
    tags
    {
        tag main { }
        tag www{ }
        tag mail{ }
        tag media{ }
        tag term { }
        #tag  { }
        #tag 7 { }
        #tag 8 { }
        #tag 9 { }
    }
    layouts
    {
        layout tile { image = "/usr/share/awesome/icons/layouts/tilew.png" }
        layout tileleft { image = "/usr/share/awesome/icons/layouts/tileleftw.png" }
        layout tilebottom { image = "/usr/share/awesome/icons/layouts/tilebottomw.png" }
        layout tiletop { image = "/usr/share/awesome/icons/layouts/tiletopw.png" }
        layout max { image = "/usr/share/awesome/icons/layouts/maxw.png" }
        layout spiral { image = "/usr/share/awesome/icons/layouts/spiralw.png" }
        layout dwindle { image = "/usr/share/awesome/icons/layouts/dwindlew.png" }
        layout floating { image = "/usr/share/awesome/icons/layouts/floatingw.png" }
    }
    statusbar mystatusbar
    {
        position = "top"
        height = "17"

        taglist mytaglist
        {
            mouse
            {
                button = "1"
                command = "tag_view"
            }
            mouse
            {
                button = "1"
                modkey = {"Mod4"}
                command = "client_tag"
            }
            mouse
            {
                button = "3"
                command = "tag_toggleview"
            }
            mouse
            {
                button = "3"
                modkey = {"Mod4"}
                command = "client_toggletag"
            }
            mouse
            {
                button = "4"
                command = "tag_viewnext"
            }
            mouse
            {
                button = "5"
                command = "tag_viewprev"
            }
        }
        layoutinfo mylayoutinfo
        {
            mouse
            {
                button = "1"
                command = "tag_setlayout"
                arg = "+1"
            }
            mouse
            {
                button = "4"
                command = "tag_setlayout"
                arg = "+1"
            }
            mouse
            {
                button = "3"
                command = "tag_setlayout"
                arg = "-1"
            }
            mouse
            {
                button = "5"
                command = "tag_setlayout"
                arg = "-1"
            }
        }
        tasklist mytasklist
        {
            show_icons = false

            mouse
            {
                button = "4"
                command = "client_focusnext"
            }
            mouse
            {
                button = "5"
                command = "client_focusprev"
            }
            mouse
            {
                modkey = {"Mod4"}
                button = "4"
                command = "client_swapnext"
            }
            mouse
            {
                modkey = {"Mod4"}
                button = "5"
                command = "client_swapprev"
            }
        }
        iconbox logo
        {
           image = "/usr/share/awesome/icons/awesome16.png"
            mouse
            {
                button = "1"
                command = "spawn"
                arg = "exec x-terminal-emulator -e man awesome"
           }
        }
        textbox clock
        {
            text = "-"
            align = "right"
        }
     }
}

rules
{
    rule { name = "Gimp" float = true }
    rule { name = "MPlayer" float = true }
    rule { name = "Acroread" float = true }
    rule { name = "pinentry" float = true }
    rule { name = "gedit" float = true }
    rule { name = "pidgin" float = true }
}

mouse
{
    root
    {
        button = "3"
        command = "spawn"
        arg = "exec x-terminal-emulator"
    }
    root
    {
        button = "4"
        command = "tag_viewnext"
    }
    root
    {
        button = "5"
        command = "tag_viewprev"
    }
    client
    {
        modkey = {"Mod4"}
        button = "1"
        command = "client_movemouse"
    }
    client
    {
        modkey = {"Mod4"}
        button = "2"
        command = "client_zoom"
    }
    client
    {
        modkey = {"Mod4"}
        button = "3"
        command = "client_resizemouse"
    }
    titlebar
    {
        button = "1"
        command = "client_movemouse"
    }
    titlebar
    {
        button = "3"
        command = "client_resizemouse"
    }
}

keys
{
    key
    {
        modkey = {"Mod4"}
        key = "F1"
        command = "spawn"
        arg = "exec x-terminal-emulator -e man `for i in /usr/share/man/man?;do ls $i; done | cut -d. -f1 | awesome-menu 'See manual page for:'`"
    }
    key
    {
        modkey = {"Mod4"}
        key = "F2"
        command = "spawn"
        arg = "exec find /usr/bin -type f -executable ! -empty | sed 's,.*/,,' | awesome-menu -e 'exec ' Execute:"
    }
    key
    {
        modkey = {"Mod4"}
        key = "F3"
        command = "spawn"
        arg = "exec x-terminal-emulator -e ssh `cut -d' ' -f1 ~/.ssh/known_hosts | cut -d, -f1 | awesome-menu 'ssh to:'`"
    }
    key
    {
        modkey = {"Mod4"}
        key = "Return"
        command = "spawn"
        arg = "exec x-terminal-emulator"
    }
    key
    {
        modkey = {"Mod4"}
        key = "space"
        command = "tag_setlayout"
        arg = "+1"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "space"
        command = "tag_setlayout"
        arg = "-1"
    }
    key
    {
        modkey = {"Mod4"}
        key = "b"
        command = "statusbar_toggle"
    }
    key
    {
        modkey = {"Mod4"}
        key = "j"
        command = "client_focusnext"
    }
    key
    {
        modkey = {"Mod4"}
        key = "k"
        command = "client_focusprev"
    }
    key
    {
        modkey = {"Mod4"}
        key = "p"
        command = "spawn"
        arg = "dmenu_path | awesome-menu -e 'exec ' Execute:"
    }
     key
    {
        modkey = {"Mod4"}
        key = "Tab"
        command = "focus_history"
        arg = "-1"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "j"
        command = "client_swapnext"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "k"
        command = "client_swapprev"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "j"
        command = "screen_focus"
        arg = "+1"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "k"
        command = "screen_focus"
        arg = "-1"
    }
    key
    {
        modkey = {"Mod4"}
        key = "h"
        command = "tag_setmwfact"
        arg = "-0.05"
    }
    key
    {
        modkey = {"Mod4"}
        key = "l"
        command = "tag_setmwfact"
        arg = "+0.05"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "h"
        command = "tag_setnmaster"
        arg = "+1"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "l"
        command = "tag_setnmaster"
        arg = "-1"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "h"
        command = "tag_setncol"
        arg = "+1"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "l"
        command = "tag_setncol"
        arg = "-1"
    }
    key
    {
        modkey = {"Mod4"}
        key = "Escape"
        command = "tag_prev_selected"
    }
    key
    {
        modkey = {"Mod4"}
        key = "Left"
        command = "tag_viewprev"
    }
    key
    {
        modkey = {"Mod4"}
        key = "Right"
        command = "tag_viewnext"
    }
    key
    {
        modkey = {"Mod4"}
        key = "m"
        command = "client_togglemax"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "Return"
        command = "client_zoom"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "space"
        command = "client_togglefloating"
    }
    key
    {
        modkey = {"Mod4"}
        key = "s"
        command = "client_togglescratch"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "s"
        command = "client_setscratch"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "c"
        command = "client_kill"
    }
    key
    {
        modkey = {"Mod4", "Shift"}
        key = "q"
        command = "quit"
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "r"
        command = "restart"
    }
    key  # dmenu launcher
    {
        modkey = {"Mod4", "Shift"}
        key = "p"
        command = "spawn"
        arg = "dmenu_path | awesome-menu -e 'exec ' Execute:"
    }
    key
    {
       modkey = {"Mod4"}
       key = "0"
       command = "tag_view"
    }
    keylist
    {
        modkey = {"Mod4"}
        command = "tag_view"
        keylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
        arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
    }
    key
    {
        modkey = {"Mod4", "Control"}
        key = "0"
        command = "tag_toggleview"
    }
    keylist
    {
        modkey = {"Mod4", "Control"}
        command = "tag_toggleview"
        keylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
        arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
    }

    key
    {
        modkey = {"Mod4", "Shift"}
        key = "0"
        command = "client_tag"
    }
    keylist
    {
        modkey = {"Mod4", "Shift"}
        command = "client_tag"
        keylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
        arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
    }

    key
    {
        modkey = {"Mod4", "Shift", "Control"}
        key = "0"
        command = "client_toggletag"
    }
    keylist
    {
        modkey = {"Mod4", "Shift", "Control"}
        command = "client_toggletag"
        keylist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
        arglist = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
    }
   }
# vim: filetype=conf 

I may have left out something in this post. If there are any questions or you can't get something working, I'll try my best to answer. :)

  • Like 2
Link to comment
https://www.neowin.net/forum/topic/901758-how-to-awesome-wm-with-debianubuntu/
Share on other sites

Some common Awesome commands:

(Mod key - 'Windows' key)

Mod+space = rotate open screen layout

Mod+h or l = scale focused window left or right, makes the window larger or smaller

Right-click on the empty screen to launch terminal

Mod + F1 = terminal

Mod + F2 = Awesome Menu

Mod + b = statusbar toggle

Mod + Ctrl + R = Reload Awesome

Mod + Shift + Q = Quit to login screen

Those listed above are the ones I use the most. More shortcuts can be found in the 'key' section of the .awesomerc file.

Thanks for posting this (Y) As soon as I get some time I'll try it, I've never played with tiling wm's before.

No problem :). Ive been using Awesome off and on for a while - I seem to keep coming back to it. Hopefully my rudimentary guide will help out.

Awesome is an awesome window manager. Personally, I prefer dwm, though. (Y)

I like DWM as well. It is installed by default on #!, although I never could tweak it to my likings. I may give it another shot though - I have heard good things about it. Also Xmonad as well.

Love the background, but that's it. Sorry, looks a little too barebones for me! Thanks for the guide, though. A good learning experience!

I understand completely. I kept going more minimalistic in my DE/WMs, not sure you can go more minimalistic than this. ;)

I like minimal. I'm thinking I'll try this soon.

One question. In Ubuntu, Openbox has a feature I really like--holding down superkey brings up a little toggle where you can press the arrow keys to go through your open windows. I like avoiding the mouse as much as possible. Does Awesome do this, or at least can it be made to do this?

I like minimal. I'm thinking I'll try this soon.

One question. In Ubuntu, Openbox has a feature I really like--holding down superkey brings up a little toggle where you can press the arrow keys to go through your open windows. I like avoiding the mouse as much as possible. Does Awesome do this, or at least can it be made to do this?

Mod+J will change focus to the open windows, one by one. Mod + arrow keys will rotate through the different desktops.

I found some help on the interwebs about a load average/clock script that will display in the statusbar. For those that are unsure how a load average works, from our friends at wikipedia:

For example, one can interpret a load average of "1.73 0.50 7.98" on a single-CPU system as:

* during the last minute, the CPU was overloaded by 73% (1 CPU with 1.73 runnable processes, so that 0.73 processes had to wait for a turn)

* during the last 5 minutes, the CPU was underloaded 50% (no processes had to wait for a turn)

* during the last 15 minutes, the CPU was overloaded 698% (1 CPU with 7.98 runnable processes, so that 6.98 processes had to wait for a turn)

Add the following to the bottom of the 'statusbar' section in the .awesomerc

textbox uptime
        {
                style
                {
                    font = "sans 7"
                    fg = "#ffffff"
                }
                text = " 0.00 0.00 0.00 |"
                align = right
                text_align = right
                width = 0
                mouse
                {
                    button = "1"
                    command = "spawn"
                    arg = "exec x-terminal-emulator -e htop"
                }
        }
        textbox clock
        {
                style
                {
                    font = "sans 7"
                }
                text = " Day Mon 00, 00:00 "
                align = right
                text_align = left
                width = 0
        }

This will display the load average, and add a clock to the right of it. (this also adds a button that will launch htop, the process manager, when clicking on the load average)

The script that will pipe the information is:

#!/bin/sh
#
while true
do
    if [ -S ~/.awesome_ctl.0 ]; then
        while true
        do
            echo "0 widget_tell mystatusbar clock text `date +\"%a %b %d, %k:%M\"` "
            echo "0 widget_tell mystatusbar uptime text `uptime | sed 's/.*://; s/,//g'` "
            echo "" # an empty line flushes data inside awesome
            sleep 10
        done | awesome-client
    else
        sleep 1
    fi
done

Save this as .awesomeclock.sh (or whatever) and save it in the .awesome directory. Make sure to make it executable by running

chmod +x .awesomeclock.sh

from the terminal in the .awesome directory.

or

user@host:~/.awesome$ chmod +x .awesomeclock.sh

and add the following line to the .Xsession file

sh /home/lance/.awesome/awesomeclock.sh &

This will give the following result:

aetq9f.jpg

Hope this works...

  • 2 weeks later...

Since I have posted this hopefully helpful how-to, I have upgraded my Awesome setup from 2.3.4 to 3.4.1. This was a bigger chore than I had envisioned.

The config file itself went from an easy to understand text file to a config file driven by Lua. This brought some challenges, although the new config file allows for more customization and flexibility.

I had to use a user .ppa to upgrade the package itself, which once that was complete, my adventure began. After the installation was complete and I booted into my new Awesome setup, I had to start customizing. I found some very helpful tutorials on DesktopEvolution.org, posted by Darthlukan, which made the widget setup and statusbar customization fairly painless.

The .ppa is located here: http://ppa.launchpad.net/aguignard/ppa/ubuntu. Once enabled, update Synaptic and install Awesome 3.4.1.

To customize the statusbar to enable the cpu, mem, etc. widgets, follow the instructions laid out in Darthlukan's posts. He has made it very easy to follow. After all the widgets were installed and I almost achieved my customization goals, I still had one issue that bothered me. The open programs would display their icons in the status bar. I posed my question in several IRC and forum threads with no luck. I finally posted on Linuxquestions.org and was responded to by antegallya, which solved my issue. The following code had to be 'patched' into the /usr/share/awesom/lib/awful/widget/tasklist.lua file:

@@ -95,6 +95,10 @@
     local text = "<span font_desc='"..font.."'>"
     local name
     local status_image
+    local c_icon
+    if not args.hide_icon then
+        c_icon = c.icon
+    end
     if client.floating.get(c) and floating_icon then
         status_image = capi.image(floating_icon)
     end

@@ -120,7 +124,7 @@
         text = text .. name
     end
     text = text .. "</span>"
-    return text, bg, status_image, c.icon
+    return text, bg, status_image, c_icon
 end

To patch the file, add the code where there is a + symbol, and replace the code where the - symbol is.

For help, here is my .rc.lua, which was copied from /etc/xdg/awesome/rc.lua -

-- Standard awesome library
require("awful")
require("awful.autofocus")
require("awful.rules")
-- Theme handling library
require("beautiful")
-- Notification library
require("naughty")
-- Widget library
require("vicious")

-- Load Debian menu entries
require("debian.menu")

-- {{{ Variable definitions
-- Themes define colours, icons, and wallpapers
beautiful.init("/home/lance/.config/awesome/theme.lua")

-- This is used later as the default terminal and editor to run.
terminal = "terminator"
editor = os.getenv("EDITOR") or "editor"
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.
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
}
-- }}}

-- {{{ Tags
-- Define a tag table which hold all screen tags.
tags = {}
tagnames = { "fm", "net", "irc", "editor", "term" }
taglayouts = {
        awful.layout.suit.tile.left,
        awful.layout.suit.max,
        awful.layout.suit.max,
        awful.layout.suit.floating,
        awful.layout.suit.max }
for s = 1, screen.count() do
    -- Each screen has its own tag table.
    tags[s] = {}
    for tagnumber = 1, 5 do
        -- Add tags and name them.
        tags[s][tagnumber] = tag(tagnames[tagnumber])
        -- Add tags to screen one by one, giving them their layouts at the same time.
        tags[s][tagnumber].screen = s
        awful.layout.set(taglayouts[tagnumber], tags[s][tagnumber])
    end
    -- I'm sure you want to see at least one tag.
    tags[s][1].selected = true
end

-- }}}

-- {{{ Menu
-- Create a laucher widget and a main menu
myawesomemenu = {
   { "manual", terminal .. " -e man awesome" },
   { "edit config", editor_cmd .. " " .. awful.util.getdir("config") .. "/rc.lua" },
   { "restart", awesome.restart },
   { "quit", awesome.quit }
}

mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
                                    { "Debian", debian.menu.Debian_menu.Debian },
                                    { "open terminal", terminal }
                                  }
                        })

mylauncher = awful.widget.launcher({ image = image(beautiful.awesome_icon),
                                     menu = mymainmenu })
-- }}}

--Separators
spacer    = widget({ type = "textbox"})
separator = widget({ type = "textbox"})
spacer.text     =" "
separator.text  ="."

-- {{{ Wibox

-- Create a cpuwidget (usage%)
cpuicon = widget({ type= "imagebox" })
cpuicon.image = image("/home/lance/.config/awesome/icons/cpu.png")
-- Initialize widget
cpuwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(cpuwidget, vicious.widgets.cpu, "cpu-$1%", 2)

-- Create a memwidget (usage$ usedMB/TotalMB)
memicon = widget({ type =  "imagebox" })
memicon.image = image("/home/lance/.config/awesome/icons/mem.png")
-- Initialize widget
memwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(memwidget, vicious.widgets.mem, "mem-$1% ($2MB/$3MB)", 13)

-- Create a batwidget (status chrg%)
baticon = widget({ type = "imagebox" })
baticon.image = image("/home/lance/.config/awesome/icons/bat.png")
-- Initialize widget
batwidget = widget({ type = "imagebox" })
-- Register widget
vicious.register(batwidget, vicious.widgets.bat, "$1$2%", 31, "BAT0")

-- Create a textclock widget
clockicon = widget({ type = "imagebox" })
clockicon.image = image("/home/lance/.config/awesome/icons/time.png")
mytextclock = awful.widget.textclock({ align = "right" })

--Create a netwidget (usage)
dnicon = widget({ type = "imagebox" })
upicon = widget({ type = "imagebox" })
dnicon.image = image("/home/lance/.config/awesome/icons/down.png")
upicon.image = image("/home/lance/.config/awesome/icons/up.png")
-- Initialize widget
netwidget = widget({ type = "textbox" })
-- Register widget
vicious.register(netwidget, vicious.widgets.net, "up-${eth1 up_kb}kb/s / down-${eth1 down_kb}kb/s", 1)


-- Create a fswidget (usage)
fsicon = widget({ type = "imagebox" })
fsicon.image = image("/home/lance/.config/awesome/icons/disk.png")
-- Initialize widget
fswidget = widget({ type = "textbox" })
-- Register widget
vicious.register(fswidget, vicious.widgets.fs, "root- ${/ used_gb}gb / ${/ avail_gb}gb", 37)
-- Create a systray
--mysystray = widget({ type = "systray" })

-- Create a wibox for each screen and add it
mywibox = {}
mypromptbox = {}
mylayoutbox = {}
mytaglist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    awful.button({ }, 4, awful.tag.viewnext),
                    awful.button({ }, 5, awful.tag.viewprev)
                    )
mytasklist = {}
mytasklist.buttons = awful.util.table.join(
                     awful.button({ }, 1, function (c)
                                              if not c:isvisible() then
                                                  awful.tag.viewonly(c:tags()[1])
                                              end
                                              client.focus = c
                                              c:raise()
                                          end),
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance:hide()
                                                  instance = nil
                                              else
                                                  instance = awful.menu.clients({ width=250 })
                                              end
                                          end),
                     awful.button({ }, 4, function ()
                                              awful.client.focus.byidx(1)
                                              if client.focus then client.focus:raise() end
                                          end),
                     awful.button({ }, 5, function ()
                                              awful.client.focus.byidx(-1)
                                              if client.focus then client.focus:raise() end
                                          end))

for s = 1, screen.count() do
    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt({ layout = awful.widget.layout.horizontal.leftright })
    -- Create an imagebox widget which will contains an icon indicating which layout we're using.
    -- We need one layoutbox per screen.
    mylayoutbox[s] = awful.widget.layoutbox(s)
    mylayoutbox[s]:buttons(awful.util.table.join(
                           awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end),
                           awful.button({ }, 4, function () awful.layout.inc(layouts, 1) end),
                           awful.button({ }, 5, function () awful.layout.inc(layouts, -1) end)))
    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.label.all,mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(function(c)
                                              return awful.widget.tasklist.label.currenttags(c, s, { hide_icon = true })
                                          end, mytasklist.buttons)

    -- Create the wibox
    mywibox[s] = awful.wibox({ position = "top", height = "15", screen = s })
    -- Add widgets to the wibox - order matters
    mywibox[s].widgets = {
        {
            mylauncher,
            mytaglist[s],
            mypromptbox[s],
            layout = awful.widget.layout.horizontal.leftright
        },                                                                                                       
        mylayoutbox[s],
        mytextclock, spacer, clockicon,                 
        separator, spacer, cpuwidget, spacer, cpuicon, separator,
        spacer, memwidget, spacer, memicon, separator,
        spacer, netwidget, spacer, separator,
        spacer, fswidget, spacer, separator,
        s == 1 and mysystray or nil,
        mytasklist[s],
        layout = awful.widget.layout.horizontal.rightleft
    }
end
-- }}}

-- {{{ Mouse bindings
root.buttons(awful.util.table.join(
    awful.button({ }, 3, function () mymainmenu:toggle() end),
    awful.button({ }, 4, awful.tag.viewnext),
    awful.button({ }, 5, awful.tag.viewprev)
))
-- }}}

-- {{{ Key bindings
globalkeys = awful.util.table.join(
    awful.key({ modkey,           }, "Left",   awful.tag.viewprev       ),
    awful.key({ modkey,           }, "Right",  awful.tag.viewnext       ),
    awful.key({ modkey,           }, "Escape", awful.tag.history.restore),

    awful.key({ modkey,           }, "j",
        function ()
            awful.client.focus.byidx( 1)
            if client.focus then client.focus:raise() end
        end),
    awful.key({ modkey,           }, "k",
        function ()
            awful.client.focus.byidx(-1)
            if client.focus then client.focus:raise() end
        end),
    awful.key({ modkey,           }, "w", function () mymainmenu:show(true)        end),

    -- Layout manipulation
    awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end),
    awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end),
    awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end),
    awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end),
    awful.key({ modkey,           }, "u", awful.client.urgent.jumpto),
    awful.key({ modkey,           }, "Tab",
        function ()
            awful.client.focus.history.previous()
            if client.focus then
                client.focus:raise()
            end
        end),

    -- Standard program
    awful.key({ modkey,           }, "Return", function () awful.util.spawn(terminal) end),
    awful.key({ modkey, "Control" }, "r", awesome.restart),
    awful.key({ modkey, "Shift"   }, "q", awesome.quit),

    awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)    end),
    awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)    end),
    awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1)      end),
    awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1)      end),
    awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1)         end),
    awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1)         end),
    awful.key({ modkey,           }, "space", function () awful.layout.inc(layouts,  1) end),
    awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(layouts, -1) end),

    -- Prompt
    awful.key({ modkey },            "r",     function () mypromptbox[mouse.screen]:run() end),

    awful.key({ modkey }, "x",
              function ()
                  awful.prompt.run({ prompt = "Run Lua code: " },
                  mypromptbox[mouse.screen].widget,
                  awful.util.eval, nil,
                  awful.util.getdir("cache") .. "/history_eval")
              end)
)

clientkeys = awful.util.table.join(
    awful.key({ modkey,           }, "f",      function (c) c.fullscreen = not c.fullscreen  end),
    awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end),
    awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ),
    awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
    awful.key({ modkey,           }, "o",      awful.client.movetoscreen                        ),
    awful.key({ modkey, "Shift"   }, "r",      function (c) c:redraw()                       end),
    awful.key({ modkey,           }, "n",      function (c) c.minimized = not c.minimized    end),
    awful.key({ modkey,           }, "m",
        function (c)
            c.maximized_horizontal = not c.maximized_horizontal
            c.maximized_vertical   = not c.maximized_vertical
        end)
)

-- Compute the maximum number of digit we need, limited to 9
keynumber = 0
for s = 1, screen.count() do
   keynumber = math.min(9, math.max(#tags[s], keynumber));
end

-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, keynumber do
    globalkeys = awful.util.table.join(globalkeys,
        awful.key({ modkey }, "#" .. i + 9,
                  function ()
                        local screen = mouse.screen
                        if tags[screen][i] then
                            awful.tag.viewonly(tags[screen][i])
                        end
                  end),
        awful.key({ modkey, "Control" }, "#" .. i + 9,
                  function ()
                      local screen = mouse.screen
                      if tags[screen][i] then
                          awful.tag.viewtoggle(tags[screen][i])
                      end
                  end),
        awful.key({ modkey, "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then
                          awful.client.movetotag(tags[client.focus.screen][i])
                      end
                  end),
        awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
                  function ()
                      if client.focus and tags[client.focus.screen][i] then
                          awful.client.toggletag(tags[client.focus.screen][i])
                      end
                  end))
end

clientbuttons = awful.util.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))

-- Set keys
root.keys(globalkeys)
-- }}}

-- {{{ Rules
awful.rules.rules = {
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     focus = true,
                     keys = clientkeys,
                     buttons = clientbuttons } },
    { rule = { class = "MPlayer" },
      properties = { floating = true } },
    { rule = { class = "pinentry" },
      properties = { floating = true } },
    { rule = { class = "gimp" },
      properties = { floating = true } },
    -- Set Firefox to always map on tags number 2 of screen 1.
    -- { rule = { class = "Firefox" },
    --   properties = { tag = tags[1][2] } },
}
-- }}}

-- {{{ Signals
-- Signal function to execute when a new client appears.
client.add_signal("manage", function (c, startup)
    -- Add a titlebar
    -- awful.titlebar.add(c, { modkey = modkey })

    -- Enable sloppy focus
    c:add_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
    end)

    if not startup then
        -- Set the windows at the slave,
        -- i.e. put it at the end of others instead of setting it master.
        -- awful.client.setslave(c)

        -- Put windows in a smart way, only if they does not set an initial position.
        if not c.size_hints.user_position and not c.size_hints.program_position then
            awful.placement.no_overlap(c)
            awful.placement.no_offscreen(c)
        end
    end
end)

client.add_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.add_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
-- }}}

Hopefully, some will make the attempt to try a tiling WM, as I've never felt that I've had more control over my system. If there are any questions, feel free to post here again, and I will try to help to the best of my (limited) abilities.

BTW, here is a screenie of my statusbar with the widgets and icons disabled:

5xq2c5.jpg

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • I would never install install this build before rtm process. only 3 months to go. never install on your daily devices. just wait 3 months.
    • Motrix Next 3.9.6 by Razvan Serea Motrix Next is a modern, open-source cross-platform download manager built as the official next-generation successor to the original Motrix project. It has been completely rewritten using Tauri 2, Vue 3, TypeScript, and Rust, while still relying on the powerful Aria2 download engine for high-speed multi-protocol transfers. The app supports HTTP, HTTPS, FTP, BitTorrent, ED2K and magnet links, offering advanced features like multi-connection acceleration, task scheduling, bandwidth control, and batch download management. With a significantly reduced install size (around 20MB), it focuses on being lightweight, fast, and resource-efficient compared to traditional Electron-based download tools. Designed for Windows, macOS, and Linux, Motrix Next delivers a clean, modern UI inspired by Material Design 3 principles, with smooth animations and a minimal workflow. It improves usability through better download organization, system tray integration, and enhanced torrent handling including selective file downloads and tracker management. Motrix Next features: Multi-protocol downloads — HTTP, FTP, BitTorrent, Magnet, .torrent, ED2K, and Metalink tasks BitTorrent — Selective file download, DHT, peer exchange, encryption controls, metadata caching, GeoIP peer flags, and tracker probing Browser extension integration — Embedded Extension API with independent authentication, download confirmation, smart auto-submit, filename hints, referer/cookie forwarding, and real-time controls (Chrome Web Store · Edge Add-ons) Safe filename handling — Content-Disposition, RFC 2047, non-UTF-8, percent-encoded, and extensionless URL resolution with path traversal sanitization Download organization — Favorite and recent folders, optional file-type categorization, stale-record cleanup, and completed history backed by SQLite Concurrent downloads — Independent controls for active tasks, HTTP connections per server, segments per file, and BT peer limits Speed control — Global and per-task upload/download limits with day-of-week and time-of-day scheduling System integration — Tray operation, optional tray speed display, macOS Dock badge/progress, protocol handlers for magnet://, thunder://, and motrixnext:// Lightweight mode — Destroys the WebView on minimize-to-tray while Rust keeps the engine, task monitor, notifications, history, and extension routing alive Notifications and power options — Native task start/complete/failure notifications, keep-awake during downloads, and optional shutdown after completion Network controls — Scoped proxy support for downloads, app updates, and tracker updates, plus system proxy detection Auto-update channels — Stable, Beta, and Latest Across Channels policies with separate download and install phases Diagnostics — Structured logs, exportable diagnostic ZIPs, database integrity checks, automatic DB rebuild, and Linux GPU rendering fallback Personalization — Light/dark/system theme, 10 color schemes, 26 languages, and first-launch system language detection Motrix Next 3.9.6 changelog: New Features Clipboard management — App-owned copy actions no longer trigger the Add Task auto-detect popup. aria2 input compatibility — Multi-line aria2-style task input is supported for URLs with per-task options such as out=. BitTorrent IPv6 DHT — Added IPv6 DHT support and related configuration. File category URL patterns — File category rules can match URL patterns with validation and localized hints. Task status tags — Added clearer waiting and sharing states for task cards. Download event bridge — Added an aria2 WebSocket event bridge for faster download notifications. Improvements Improved task list transitions and preserved task state during tab switches. Kept RPC origin access enabled for local integrations. Restored AppImage stripping in release builds after beta validation. Added localized preference guidance across supported languages. Download: Motrix Next 64-bit | ARM64 | macOS ~20.0 MB (Open Source) Links: Website | macOS / Linux | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Segra 1.6.2 by Razvan Serea Segra is a free, open-source OBS-powered game recorder offering fast gameplay capture, instant clips, AI highlights, deep game integration, and seamless uploads—perfect for gamers, streamers, and content creators. Lightweight, fast, zero bloat. Segra key features: Automatic Game Recording: Begin capturing gameplay the moment your game launches, with zero manual setup. Instant Clipping: Save important moments instantly using a customizable hotkey—perfect for highlights, montages, or quick shares. Segra AI Highlights: Let Segra automatically detect kills, assists, deaths, and key events to generate polished highlight reels without manual editing. Gameplay Uploads: Upload recordings and clips directly to Segra.tv for fast sharing and cloud access. Deep Game Integration: Enjoy advanced game-data tracking across hundreds of supported titles, enabling smart highlight generation and stat-informed clipping. High-Performance Capture: Record up to 4K at 144 FPS using OBS-powered technology with minimal performance impact, supporting NVENC, AMD VCE, and custom quality controls. Segra Editor: Edit recordings easily with timeline controls, segment management, and event-based navigation to build the perfect clip. Customization Options: Adjust hotkeys, output formats, storage paths, codecs, capture quality, and performance settings for a tailored recording experience. Segra 1.6.2 changelog: UI: Improved the transition from the loading skeleton to the real content card. Security: Added Segra.dll code signing and automatic VirusTotal upload. Settings: Fixed the settings header to highlight Account when scrolled to the top. Recording: Updated OBSKit.NET to 1.4.1. Download: Segra 1.6.2 | 74.5 MB (Open Source) View: Segra Homepage | Github | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Hey Google, these are the Gemini features I want in 2026 by Aditya Tiwari Google Gemini has been around for over three years. The AI chatbot started its journey back in 2023 (as Bard) when ChatGPT was already a talk of the town. However, it quickly attracted criticism after misrepresenting facts about the James Webb Space Telescope. The search giant spent a year fine-tuning Bard before rebranding the chatbot and its underlying generative AI model to Gemini, drawing inspiration from NASA's first human spaceflight program. Note that Bard was initially powered by LaMDA and PaLM 2; Google has since added several new features and integrations to Gemini. That said, there is scope for improvement and a gap for new features. I have been using Gemini for a while now and have realized that the chatbot lacks several features, making it harder for me to research across topics. These are mostly function-over-form updates that can improve the overall experience. Delete individual messages from a conversation Image via DepositPhotos.com One good thing about Gemini is that it can maintain context throughout the conversation. But things might get chaotic when you want to ask a related question, but don't want it to be part of your conversation in the long run. You can't ask that related question in a fresh chat because Gemini will lose the active conversation context of what you're trying to research. If Google allowed you to delete individual question/answer pairs, you could simply ask about a sub-topic and remove it from the conversation to create a smooth flow of important stuff. Offline mode Image via DepositPhotos.com A big pain of using Gemini daily is that everything loads from the cloud. It takes time for your chats to appear, and you can't view your conversation history while offline. To get a better idea, you can open the Gemini app and see how it looks without an internet connection. While Gemini models run in the cloud, it wouldn't hurt if Google could store chats (at least the text part) on the device so we can refer to them when offline. Google can also offer a lightweight version of its AI model to help with basic drafting, summarization, and other tasks. It has the Gemini Nano model, which can perform on-device processing on Google Pixel, Samsung, and some other Android brands, but it's a system feature and not related to the cloud-based Gemini app. Make temporary chats permanent I can't thank Google enough for taking the time and effort to add incognito mode or temporary chat mode to the Gemini app. It lets you have conversations without worrying that the topics will end up in your chat history or used for model training (at least on paper). Google claims that it doesn't use your temporary chats to "personalize your Gemini experience or train Google’s AI models." However, the data is stored "up to 72 hours to respond to you and to process any feedback you choose to provide." That said, I often start researching something in a temporary chat, only to realize the chatbot's answer is good enough to refer to later. Sadly, Gemini doesn't have an option to make such temporary chats permanent. In other words, I won't be able to follow up on it if I close the temporary chat. I'm left with alternatives like copying the answers into notes or another app. My digital life will get a lot better if Gemini gets a button to make temporary chats permanent. Collapse answers for a cleaner view You're heavily invested in your research game and suddenly feel the need to go up in the chat to recall something. This is when the conversation thread starts to feel like an overwhelming, unending wall of questions and answers. What if Google added a way to collapse Q&A pairs in the Gemini chat thread? It would look quite clean and easy to navigate. You'll quickly get an overview of everything you have discussed with the chatbot. Add buttons to jump between messages Suggested mockup of the feature. This reminds me of a small but useful Gemini feature that Google could add to its chatbot: the ability to hop between prompts in a conversation. Just add simple up- and down-arrow buttons, similar to YouTube Shorts, so people can quickly scroll through the messages. A table of contents or Chat Overview It's hard to get a bird's-eye view of everything you have discussed with the chatbot during a lengthy conversation. This is where a table of contents, or Chat Overview, displayed at the top of the screen, possibly in a drop-down button, might come in handy. You'll be able to get an overview of the chat and jump between messages, serving as an alternative to the up/down arrow buttons. Temporary mode for Gemini Live Image: Google You can use Gemini Live to have real-time conversations with the chatbot, which feels like you're talking to someone in the same room. However, a downside is that Gemini Live doesn't work in Temporary Chat mode, so all your conversations end up in the chat history. Google should consider expanding the temporary chat mode to include Gemini Live. Default to a specific chat One thing that feels somewhat annoying to me is that Gemini always opens in a new chat, whether on web or mobile. Sometimes, you want to return to your last chat. Google can take cues from web browsers, which let you choose whether you want to go to a new tab or a specific web page(s). Gemini can also have options to default to a specific chat when reopened. That said, generative AI chatbots have endless possibilities given the vagueness of their work. You can mold them the way you want by attaching different connectors, adding custom instructions, and including source files. It remains to be seen what Google has in store for future updates and whether anything from this wishlist gets the green light. The search giant released a stream of new Gemini updates in recent months, including Gemini 3.5 Flash and Gemini Omni Spark, adding that it now has 13 products with more than a billion users each. What do you want to see in the Gemini app? Tell us in the comments.
    • Thank you for the post. Just a FYI that links to an outside site or promoting specific software is considered spamming here. Asking general questions is fine.
  • Recent Achievements

    • Conversation Starter
      sumytbe earned a badge
      Conversation Starter
    • One Year In
      B4dM1k3 earned a badge
      One Year In
    • One Year In
      DarkWun earned a badge
      One Year In
    • Dedicated
      Almohandis earned a badge
      Dedicated
    • Dedicated
      JuvenileDelinquent earned a badge
      Dedicated
  • Popular Contributors

    1. 1
      +primortal
      507
    2. 2
      +Edouard
      181
    3. 3
      PsYcHoKiLLa
      86
    4. 4
      Michael Scrip
      78
    5. 5
      Steven P.
      75
  • Tell a friend

    Love Neowin? Tell a friend!