Brute Force
Review:Not bad, actually! |
Review:Not bad, actually! |
A few days ago I wrote about how I moved from a all-inclusive environment (KDE Plasma) to Qtile, a tiling window manager, and all the things I did to have the amenities I missed from Plasma.
One thing there that may need further explanation is the section about color schemes because the concepts themselves are fairly unusual.
So, let's dig into it a bit more.
This is how a few apps look by default if you don't configure things:
One is a Qt app, and the other is a GTK app and they look ... bad?
I mean, I don't really care all that much, but not only are the widget styles totally different, but the colors are all over the place.
And the same happens to Qtile's bar, and my terminal (alacritty) and my tmuxer (zellij) and my web browser and so on.
Everything is a different color.
In Plasma, a comon color scheme is enforced on most apps (not in chrome, though) and it makes things much nicer.
So, what's the equivalent in the Window Manager world? There isn't one, really, but there are bits and pieces you can make into ... 80% of it.
Here's what I did.
First, you need a source of consistent color schemes. If you just really, really, really like a single one, then they may have a site full of configurations for different apps to force them to follow it.
For example: Dracula or Nord
But I wanted to be able to try a bunch and see which one I liked.
For this, there is nothing like base16
Base16 defines a standard. You will have 16 colors. Those colors mean things.
And so on.
Then it defines some other things, like "If you are doing a 'dark' scheme, colors go from darker to lighter" and so on.
Then they provide a collection of themes, which are each 16 colors following those rules.
For example, this is the Brogrammer Theme:
scheme: "Brogrammer"
author: "Vik Ramanujam (http://github.com/piggyslasher)"
base00: "1f1f1f"
base01: "f81118"
base02: "2dc55e"
base03: "ecba0f"
base04: "2a84d2"
base05: "4e5ab7"
base06: "1081d6"
base07: "d6dbe5"
base08: "d6dbe5"
base09: "de352e"
base0A: "1dd361"
base0B: "f3bd09"
base0C: "1081d6"
base0D: "5350b9"
base0E: "0f7ddb"
base0F: "ffffff"
Now, suppose you want an app to follow the "base 16 standard" to see how it looks in Brogrammer style.
All you need to do is take that app's config file and put the right color where it needs it.
So, for example, for the Alacritty terminal:
colors:
# Default colors
primary:
background: '0x1b1918'
foreground: '0xa8a19f'
# Colors the cursor will use if `custom_cursor_colors` is true
cursor:
text: '0x1b1918'
cursor: '0xa8a19f'
# Normal colors
normal:
black: '0x1b1918'
red: '0xf22c40'
green: '0x7b9726'
yellow: '0xc38418'
blue: '0x407ee7'
magenta: '0x6666ea'
cyan: '0x3d97b8'
white: '0xa8a19f'
Of course editing all the config files every time you want to change your color scheme is a pain.
So the base16 project also collects templates. Those are files that when combined with a theme generate the configuration file for an application.
This is the Alacritty template:
# Base16 {{scheme-name}} - alacritty color config
# {{scheme-author}}
colors:
# Default colors
primary:
background: '0x{{base00-hex}}'
foreground: '0x{{base05-hex}}'
# Colors the cursor will use if `custom_cursor_colors` is true
cursor:
text: '0x{{base00-hex}}'
cursor: '0x{{base05-hex}}'
# Normal colors
normal:
black: '0x{{base00-hex}}'
red: '0x{{base08-hex}}'
green: '0x{{base0B-hex}}'
yellow: '0x{{base0A-hex}}'
blue: '0x{{base0D-hex}}'
magenta: '0x{{base0E-hex}}'
cyan: '0x{{base0C-hex}}'
white: '0x{{base05-hex}}'
See those bits like {{base05-hex}}
? That one gets replaced with your theme's color 5.
But again, using the template for each app you want to theme is boring.
So you need a tool to do that. The one I use is called flavours
What flavours does is:
For example, this is my configuration for Alacritty:
[[items]]
file = "~/.config/alacritty/alacritty.yml"
template = "alacritty"
subtemplate = "default-256"
rewrite = false
It says:
~/.config/alacritty/alacritty.yml
alacritty
template default-256
(don't worry)That last bit is important. That file doesn't just have the theme, it has a lot of other important stuff, so I don't want it to just have the theme in it.
So, I had to edit it once and put these lines before and after where the theme goes:
# Start flavours
... theme goes here
# End flavours
So when I use flavours
to apply a theme it will only replace that bit and leave the rest.
Since alacritty notices when the config has changed, I don't need a hook
entry. In other cases you can use it. Here's mine for qtile, to let it know it should reread its config:
hook = "killall -USR1 qtile"
So, I configured this for a bunch of things, and at this point, I can just run something like flavours apply atelier-forest
and ...
Yeah, they are not perfect. I still need to tweak some stuff, but it's getting there.
Currently my flavours configuration coordinates these:
That's roughly every app I use (yes, I am migrating from Chrome to QuteBrowser for no good reason)
And because I am not ok, I wrote a couple of tiny things to make things easier for me.
A rofi-based theme picker called rofi-base16:
And a base 16 template for Zellij.
I also wrote an ugly script to set VS Code's theme but it's shameful, so will not be shown here.
Hopefully this explains something to someone. If it doesn't, well, it will help me when I inevitably forget how this works :-)
I am a long-term KDE user. How long term? Well, since 1997 or so with intermittencies. A couple of weeks ago, I switched my personal desktops to QTile.
Mandatory screenshot:
Well, I like to switch things around every few years. I have used Unity, and MATE, and even LxQt at some point, and I have noticed over the years that I don't tend to overlap windows, so tiling window managers are the natural progression of my usage.
For a few years I have used Krohnkite an awesome KWin extension that has really been a pleasure to use and proved me that a tiling WM, with a few reasonable keyboard shortcuts, was a workable solution.
Lately I have been building a homebrew laptop which has fairly limited hardware, but I want to use for real. So I also wanted to explore ways to lower resource usage.
Other related concerns:
But why QTile specifically:
So I will now describe painstakingly every decision I made as of today, and describe the important configuration, and bore anyone who tries to read this to tears, that's what.
In an attempt to make this a bit less annoying I will setup a problem, then describe the solution I found.
There are a number of ways you interact with your "desktop". You may want to logout. Or start an app. Or run a command. Or configure a bluetooth speaker. Or see the clipboard history. Or configure wifi.
In the desktop world, this all comes included in the package deal. In the Window Manager universe, you have to roll your own, and most setups end with a disparate collection of utilities, like blueman and network-manager and clipit and so on plus whatever the WM itself provides.
Well, but what if they could be the same thing?
What if in addition they could all share a lovely, customizable UI?
Enter rofi
the most common usage for rofi is as an app launcher, and it's great at that, but it's just scratching the surface:
Because of its flexible architecture, it can be used to configure your network using networkmanager-dmenu:
As your power/logout menu via rofi-power-menu
And much more. I also use it as a fronted to a pasword manager, a frontend to ssh, a simple Todo list, an emoji picker, as a fancy window switcher, and as a clipboard history manager using rofi-greenclip
Rofi starts so fast that it's often imposible to notice the difference between having a tool always running and with an icon in the systray and just having a button that launches rofi.
So, how do I use it in my ~/.config/qtile/config.py
?
Bound to some key shortcuts:
keys = [
# Launch things
Key([mod], 'p', lazy.spawn('rofi -show drun'), desc="Run app"),
Key([mod, "shift"], 'p', lazy.spawn('rofi -show run'), desc="Run Command"),
Key([mod], 's', lazy.spawn('rofi -show ssh'), desc="Ssh"),
Key([mod], 'e', lazy.spawn('rofi -show emoji'), desc="Emoji"),
Key([mod], 'v', lazy.spawn('rofi -modi "clipboard:greenclip print" -show'), desc="Clipboard")
Key([mod, alt], "Tab", lazy.spawn('rofi -show window'), desc="Move focus to next window"),
I also added a LaunchBar widget to my QTile bar where it replaces something like clipit, the blueman applet, a password manager and a todo app:
widget.LaunchBar(padding=0, text_only=True, font="Font Awesome 6 Free", fontsize=16, foreground="2e3440", progs=[
("", "rofi-bluetooth", "Bluetooth"),
("", "rofi -modi 'clipboard:greenclip print' -show", "Clipboard History"),
("", "rofi-pass", "Passwords"),
("", "rofi-todo -f /home/ralsina/todo.txt", "Todo"),
("", "flameshot gui", "Screenshot"),
]),
The first field that probably looks like a square in there are unicode characters displayed on the desktop using font awesome:
Also for mouse interactions with the Wlan widget:
widget.Wlan(format=" {percent:2.0%}",width=54, mouse_callbacks={'Button1': lazy.spawn('networkmanager_dmenu')}),
I even use it to show me the shortcut list in case I forgot any!
I could write some minor code and use it for other things too. Rofi is a magnificent example of a tool with a nice API that you can leverage to make it do many different things.
My display configurations are many. I use notebooks, so they all have one "default" configuration where they use their own screen.
In one case, it's all it can use.
In another, it's permanently docked to a monitor above its screen, but sometimes I close the notebook and the only display is the monitor.
In another it's usually docked to a monitor besides its screen, but it's shared with my work computer, so it loses and recovers that monitor dozens of times via a HDMI switch through the day as I switch tasks.
While QTile handles gracefully the addition and removal of displays in general, there are some issues.
Enter autorandr an awesome tool that will react to changes in your situation and do the right thing.
How?
autorandr -s two-monitors
autorandr -s closed-lid
autorandr -c
in your ~.xprofile
This is enough for most things, except the bar situation in QTile.
For that, I wrote two things. First a shell script that goes in ~/.config/autorandr/postswitch
This is a "hook" that gets executed after the display configuration changes. Here's mine:
#!/bin/bash -x
config="$AUTORANDR_CURRENT_PROFILE"
notify-send "Switched to config $AUTORANDR_CURRENT_PROFILE"
killall -USR1 qtile # Make qtile reread configuration
And why do I want qtile to reread its configuration? Because I want the systray to be on the "last" screen, which is always larger :-)
Here's the relevant fragment from ~/.config/qtile/conf.py
screen_count = len(subprocess.check_output(shlex.split("xrandr --listmonitors")).splitlines()) -1
screens = [
Screen(
bottom=bar.Bar(
[ ... # List of widgets for this bar
# Add systray in the LAST screen, otherwise invisible widget
widget.Systray(padding=10) if i==screen_count-1 else widget.Sep(linewidth=0),),
) for i in range(screen_count)]
This solution requires a minimum of setup for my standards (just configure your screens once and a bit of code) and a maximum of benefit:
I have seen it a few times in the past. I change WMs or desktops and suddenly chrome has no idea where my passwords went. They are there in passwords.google.com but chrome never autofills, and they are not listed in my local profile.
Make sure you are running gnome-keyring-daemon
and add this in ~/.config/chrome-flags.conf
--password-store=gnome
You want a password store that is not chrome. I have one in addition of chrome, using pass
This keeps my passwords encrypted in Git (you can use GitHub, I use my personal gitea) and you can access them from the command line, from a Chrome extension, or from a button in my desktop bar using rofi-pass
This ensures I never will lose access to my passwords, and maximizes the ways I can get to them while keeping things nice and secure.
While I know perfectly well how to mount devices in Linux, I'd rather they mount themselves.
Use udiskie it's lightweight, nicely integrated, and it just works well by default.
I want desktop notifications.
Use dunst it's lightweight, nicely integrated, and it just works well by default.
I want my screen to lock, but don't want anything fancy.
Use xss-lock
and slock
While slock in itself works great, xss-lock
integrates it with loginctl
so it works better. Just add this to your ~/.xprofile
:
xss-lock slock &
I want simple icons that are not very colorful, so they integrate with whatever color scheme I am using.
Since I am following more or less a nord color scheme I am using a combination of Nordzy icons and just using font-awesome
Here are some snippets from the qtile config. Where I am pointing icons to a specific folder, that folder contains copies of nordzy icons converted to PNG with transparent backgrounds:
bottom=bar.Bar(
[ ...
widget.GroupBox(highlight_method="block", foreground="2e3440", active="d08770", inactive="4c566a", this_current_screen_border="242831",this_screen_border="88c0d0"),
widget.BatteryIcon(theme_path="/home/ralsina/.config/qtile/battery_icons", background="d8dee9", mouse_callbacks=power_callbacks),
widget.Volume(fmt="",padding=0, theme_path="/home/ralsina/.config/qtile/battery_icons"),
widget.LaunchBar(padding=0, text_only=True, font="Font Awesome 6 Free", fontsize=16, foreground="2e3440", progs=[
("", "rofi-bluetooth", "Bluetooth"),
("", "rofi -modi 'clipboard:greenclip print' -show", "Clipboard History"),
("", "rofi-pass", "Passwords"),
("", "rofi-todo -f /home/ralsina/todo.txt", "Todo"),
("", "flameshot gui", "Screenshot"),
]),
],
background=["d8dee9"],
border_width=[1, 0, 0, 0], # Draw top and bottom borders
border_color=["b48ead","b48ead","b48ead","b48ead" ], # Borders are magenta
Then I configured styles and icons for gtk apps (using lxappearance
) and Qt apps (using qt5ct
) and things now look decent.
I want a coordinated color scheme in the disparate tools I am using.
Update: I wrote a more tutorial-like thing about this called Color Coordination Using Base16
Enter flavours, a tool to generate configurations for different things out of simple templates and predefined color schemes.
It already supported my terminal (alacritty) and rofi, just needed to create templates for my qtile config:
colors = {
"background": "#{{base00-hex}}",
"background-lighter": "#{{base01-hex}}",
"selection-background": "#{{base02-hex}}",
"comments": "#{{base03-hex}}",
"foreground-dark": "#{{base04-hex}}",
"foreground": "#{{base05-hex}}",
"foreground-light": "#{{base06-hex}}",
"background-light": "#{{base07-hex}}",
"variables": "#{{base08-hex}}",
"integers": "#{{base09-hex}}",
"bold": "#{{base0A-hex}}",
"strings": "#{{base0B-hex}}",
"quotes": "#{{base0C-hex}}",
"headings": "#{{base0D-hex}}",
"italic": "#{{base0E-hex}}",
"tags": "#{{base0F-hex}}",
}
And my tmuxer (zellij):
themes {
default {
fg "#{{base05-hex}}"
bg "#{{base00-hex}}"
black "#{{base00-hex}}"
red "#{{base08-hex}}"
green "#{{base0B-hex}}"
yellow "#{{base0A-hex}}"
blue "#{{base0D-hex}}"
magenta "#{{base0E-hex}}"
cyan "#{{base0C-hex}}"
white "#{{base05-hex}}"
orange "#{{base09-hex}}"
}
}
And put the right incantations in the flavours config (partial):
[[items]]
file = "~/.config/qtile/colors.py"
template = "ralsina"
subtemplate = "qtile"
rewrite = true
hook = "killall -USR1 qtile"
[[items]]
file = "~/.config/zellij/themes/default.kdl"
template = "ralsina"
subtemplate = "zellij"
rewrite = true
I will have to configure everything I want to follow my colour scheme but I can apply it to everything with a simple command like flavours apply monokai
As an extra, here's a script that lets you choose the color scheme using rofi:
#!/bin/sh
LAST_SCHEME=$(cat ~/.local/share/flavours/lastscheme)
SELECTED=$(flavours list | sed 's/\s/\n/g' | grep -n $LAST_SCHEME | cut -d: -f1)
flavours apply $(flavours list| sed 's/\s/\n/g' | rofi -dmenu -selected-row $SELECTED)
What can I say, I like it, it's not ugly, has all the functionality I wanted and uses around 400MB of RAM before I start chrome. I am quite enjoying it.
While this site (intentionally) has no comments, feel free to discuss this in Reddit
Cuando salían dos mangos, por diversos motivos me compré unas cuantas Raspberry Pi Zeros. De hecho, tengo seis, tres ZeroW (con wifi) y trees Zero 1.3 (sin wifi)
El problema es que los motivos por los que las compré no son válidos (microcluster educativo, una zero no puede correr como nodo de ningún soft de clustering moderno) así que tenía que encontrarles un uso.
Un día paveando encontré módulos de cámara Raspberry por una suma razonable (módulos 1.3, soy un rata) y dije "ok, seguramente puedo hacer webcams!"
Bueno, sí.
Primero simplemente armé una "cámara" pegando distintas cosas que tenía a mano, y el resultado es interesante:
La calidad de imagen es mejor que casi todas las webcams que tengo, con la excepción de una Lenovo thinkpad yoga blablabla, pero eso es una notebook de 3000 dólares, ESPERO que la webcam sea buena.
PERO, el ángulo del campo de visión es bastante angosto, así que es complicado usarlo como webcam para zoom o cosas así, a menos que la instales muy lejos.
De todas formas le hice una carcaza mejor de Thingiverse, la agarré con un soporte de celularflexible, que a su vez engancha en un pie impreso 3d para mi monitor... y quedó linda.
Por otro lado, también necesitaba cambiar la webcam horrenda que tenía conectada a Octoprint.
Hay muchos tutoriales, todos basados en el mísmo código primigenio que ha sido forkeado mil veces. Decidí finalmente usar ShowmeWebcam porque:
Puntos extra por ser configurable via puerto serie!
Pero... nada es fácil, nunca.
Soluciones:
También obviamente tuve que buscar como montar la cámara para que filme la impresora desde un ángulo razonable, y mi ciruja interno festeja otra batalla ganada:
Y sí, funciona MUCHO mejor que la webcam que tenía antes. La resolución es 1080p, 30fps, y reacciona muchísimo mejor a cambios en la iluminación sin quedar sobreexpuesta ni oscura.
Conclusión: Proyecto terminado, 9 puntos.
Review:That was a lot |