Introdução
Não é minha primeira experiência com o dwm, já usei ele uns tempos atrás. Como tive alguns problemas e um pouco de preguiça, confesso, na época acabei desistindo. Uns dias atrás estava com um tempo sobrando e resolvi testar o dwm novamente. Vou relatar como foi essa experiência, apenas como curiosidade mesmo.
Uma coisa que sempre me chamou a atenção no dwm é sua capacidade de customização. Mesmo sendo necessário bom conhecimento em C e o basicão de compilação (e eu não sei nada, definitivamente, nada de ambos), resolvi tentar mesmo assim. Dessa vez fiz tudo do zero. Sem usar o dwm-flexipatch ou me basear em config dos outros. Clonei o repositório e entrei no site do projeto suckless para procurar os patches com as funcionalidades que necessitava. Afinal, mesmo sendo possível utilizar o dwm puro, eu sinto falta de algumas opções que são padrão em outros twm, sem esquecer alguns recursos que eu considero básicos, como o fornecido pela dupla de patches ewmhtags + focusonnetactive.
Um layout diferente (master/stack)
Um aspecto que me gerou estranheza nos primeiros dias, foi a forma como o dwm organiza as janelas. Ele não funciona de forma livre como no i3, que você tem controle total de como as janelas são organizadas. Nem como no bspwm, que usa o esquema fibonacci (a divisão das janelas é automática). As janelas são organizadas em master/stack. Em um resumo meio tosco, elas sempre obedecem a janela master, a principal, que é a referência, enquanto as outras ficam como secundárias no lado direito da tela. E, sempre que se abre uma nova janela, ela vira a principal. Ou seja, ela abrirá com foco e na parte esquerda da tela, jogando a última janela master para a área das stack. No começo eu me confundia ao tentar trocar as janelas de lugar. Mas logo me acostumei. Existem patchs que mudam esse comportamento, um exemplo é o zoomswap.
Segue um pequeno esquema mostrando como funciona o layout.
+-----------------+-------+
| | |
| | stack |
| | |
| Master +-------|
| | |
| | stack |
| | |
+-----------------+-------+
Como podemos observar, a janela principal, a Master, ficam do lado esquerdo da tela, enquanto as stack, “secundárias”, ficam do lado direito. Se você abrir mais de uma janela, a que acabou de ser aberta será a janela em foco e ela abrirá na área da Master.
Repare que no desenho acima existe dois tamanhos de janela. A Master ocupa 55% da tela por padrão, enquanto as janelas stack, que ficam do lado direito, são ligeiramente menores. Esse é o comportamento padrão, se você quiser é só editar lá no config.def.h a seguinte linha:
static const float mfact = 0.55;
É só trocar o valor de “0.55” para “0.50” e todas as janelas ficam do mesmo tamanho.
Iniciando os trabalhos
Antes de mais nada é bom ressaltar que como o dwm é mão na massa, existem formas diferentes de se fazer as mesmas coisas que irei apresentar aqui. Por exemplo, ao invés de usar um único script com várias funções para exibir informações na barra, você pode usar o slstatus ou o dwmblocks. O que quero dizer com isso, é que não é porque fiz de uma forma que só exista ela ou que ela seja a melhor.
Sempre que se adiciona um novo patch, você corre o risco de se deparar com incompatibilidades ou falhas ao adicionar novas funcionalidades. Por padrão, é bem simples fazer isso. Basta entrar no site dwm - dynamic window manager | suckless.org software that sucks less, procurar um patch que tenha a função que você deseja e adicioná-lo com o comando
patch -p1 < dwm_patch.diff
Essa é a forma básica para quem não entende de C ou não vai fazer as modificações manualmente. Para remover, substitua o “-p1” por “-R”.
Eventualmente acontecerá algum erro e você se depara com a mensagem que assusta muita gente ao usar o dwm:
hunk(s) FAILED
Essa mensagem indica que ao tentar aplicar o patch que, basicamente, é modificar, remover e adicionar linhas aos arquivos config.def.h e dwm.c, ocorreu algum erro.
O patch pode falhar de várias formas diferentes. Desde um patch mal feito que será acusado de “patch malformed” até as duas mais comuns, que são “hunks FAILED – saving rejects to file config.def.h.rej” e “hunks FAILED – saving rejects to file dwm.c.rej”. Os dois exemplos indicam falha ao adicionar informações nos arquivos “config.def.h” e “dwm.c”. Normalmente esses erros aparecem por falha em modificar uma determinada linha, seja porque um patch anterior já modificou uma mesma linha ou porque a indicação no .diff está errada.
Outra causa para a falha pode ser um patch antigo. Nesse caso, as indicações para modificação podem estar desatualizadas em relação ao seu “config.def.h” ou ao “dwm.c”. De qualquer forma, quanto mais patches você vai adicionando, a tendência é aumentar o número de modificações manuais que você terá que fazer. Querendo ou não, você tem que modificar arquivos de configuração, afinal esse é o princípio do dwm, faça você mesmo.
Ao se deparar com um erro “hunks FAILED” você tem a opção de verificar os arquivos com final “.rej” e adicionar manualmente as informações as respectivos arquivos. O problema é, ao aplicar o patch, ele sempre modifica alguma coisa, se você encontrar erro e largar para lá, seu config.def.h ou o dwm.c ficaram com informações desnecessárias e, ao tentar compilar, ou você encontrará erros/falhas ou mensagens de avisos (warnings). Por isso, muita gente indica usar o git para adicionar novos patchs.
Não utilizei o git, fiz a modificações dos arquivos manualmente. Por sorte, não encontrei muito conteúdo para adicionar. Se não em engano, a maior quantidade de conteúdo que tive que adicionar, foram 10 linhas seguidas de código, isso para um único patch.
Gambiarra
Pesquisando sobre patchs para adicionar gaps (mesmo eu utilizando os gaps pouco), vi que existem dois mais comuns de serem usados: fullgaps e vanitygaps. O segundo achei muito exagerado, tem mais de 10 opções para aumentar, diminuir e controlar os gaps. De útil mesmo só tem as opções de toggle e smartgaps. Como achei exagerado (dá um volume grande e exagerado de informações desnecessárias no meu arquivo de configuração), parti para o fullgaps. A única desvantagem dele é a inexistência da opção de “toggle gaps”. O que contornei com uma gambiarra.
O fullgaps adiciona três opções ao seu config.def.h:
{ MODKEY, XK_minus, setgaps, {.i = -1 } }, /* Diminui o gaps em -1 */
{ MODKEY, XK_equal, setgaps, {.i = +1 } }, /* Aumenta os gaps em +1 */
{ MODKEY|ShiftMask, XK_0, setgaps, {.i = 0 } }, /* Remove/zera os gaps */
Suas funções são aumentar, diminuir e zerar (remove os gaps). Contornei o problema da falta do toggle alterando o valor da opção que, por padrão, aumenta o gaps em +1. Alterei para +8 (que é o tamanho dos gaps que utilizo). Dessa forma, se eu zerar os gaps com super+shift+0 eu consigo retornar para o valor padrão, que é 8, só usando a opção de aumentar. Ficou uma gambiarrinha boa kkkkkkk
Toggle monocle
Outra modificação que realizei, foi alterar a ordem dos layouts. Por padrão no config.def.h, o 1 é o tiling, o 2 é floating o 3 é o monocle. Dessa forma, a opção de toggle layout fica com o modo floating. Como uso muito pouco as janelas floating, troquei o modo monocle para a segunda opção e alterei os atalhos do monocle para super + m. Dessa forma, eu tenho um comportamento igual ao monocle do bspwm. Se eu estiver no tiling, super + m troca para o monocle e se eu usar o atalho novamente, retorno para o tiling.
Para fazer isso, basta trocar a ordem dos layouts na função “static const Layout layouts”. E depois alterar os atalhos que antes eram do floating para os que você forem você definiu para o monocle.
Definindo atalhos
Por padrão, para adicionar e modificar atalhos para funções e programas, é necessário editar o config.def.h. Existe no arquivo uma sessão chamada “Commands”, com um conteúdo mais ou menos assim (com mais coisa, claro. Só estou dando um exemplo):
static const char *termcdm[] = { "xfce4-terminal", NULL };
{ MODKEY, XK_Return, spawn, {.v = termcdm} },
No exemplo acima, primeiro definidos qual programa queremos abrir e no segundo, o atalho e a chamada para o programa. Veja que com super (modkey) + enter (return) eu abro o xfce4-terminal. Fazer esse procedimento para vários programas é trabalhoso e, se eu quiser modificar os atalhos, tenho que editar o arquivo e depois recompilar o dwm. Existe um patch, chamado restartsig que evita ter que reiniciar a sessão ao recompilar. Como acho isso trabalhoso, resolvi usar o sxhkd que já tenho instalado por causa do bspwm. Adicionei um novo arquivo para o sxhkd na pasta ~/.dwm e iniciei ele pelo script autostart com um
sxhkd -c ~/.dwm/sxhkd-dwm &
Dessa forma, consigo editar os atalhos facilmente e só preciso reiniciar o sxhdk e não é necessário recompilar o dwm só por causa de um atalho para algum programa/script específico.
A importância da saída dos comandos no terminal
Que fique claro, provavelmente, os problemas que encontrei aqui, foram causados por mim mesmo. Ao adicionar as informações manualmente nos arquivos de config.
Para quem está acostumado a usar terminal, mesmo que seja para uso básico, como o meu. Já deve ter aprendido a importância que se deve atribuir ao resultado dos comandos. Na compilação do dwm não pode ser diferente. Logo na primeira vez que compilei o ambiente, recebe três warnings. Como já disse no começo do texto, não entendo nada de C, só o básico de shell script. Os três warnings não eram difíceis de compreender, não. Dois se referiam a problemas de indentação e um a uma função sem uso. Os três warnings exibidos eram referências ao arquivo dwm.c.
Primeiro fui conferir os problemas de indentação. Era coisa simples de se resolver. Apenas dois if’s, em lugares diferentes do arquivo, que estavam em posições erradas. Corrigi a indentação e os warnings sumirão.
Já para corrigir a mensagem da função sem uso. Conferi meus patchs para ver se estava tudo certo e verifiquei os arquivos .rej para ver se não faltava nada. E, para completar, pesquisei na internet sobre a função. Não era nada demais, algum patch modificou meu dwm.c e tornou obsoleta a função. O warning estava avisando que ele não estava em uso. Como era linha de código sem uso e desnecessária, fui nas linhas indicadas, removi e compilei novamente. Tudo certo dessa vez, zero warnings.
Eu tive até um pouco de sorte. Como “noob”, certamente não saberia resolver algum problema/erro mais grave, como foram só warnings, e normalmente eles não comprometem o uso, e eu consegui resolver, não me deparei com nada que me impossibilitasse ou inviabilizasse o uso do dwm.
Um dwm pronto e fácil, o flexipatch
Ao contrário do dwm padrão, construído da forma que apresentei ao longo do texto, existe o dwm-flexipatch. Em síntese é um facilitador para quem é leigo ou não quer fazer tudo manualmente. O flexipatch também está disponível para o st (terminal padrão do projeto suckless) e para o dmenu (veja os links no final do post).
Eu diria que o flexipatch tem, no caso do dwm, apenas um inconveniente, o arquivo “patches.h” é muito grande. Logo, exige um pouco de paciência e leitura por parte do usuário. A vantagem é a ausência de incompatibilidade e a garantia de que, ao compilar, o processo vai resultar em sucesso sempre.
Outra forma de usar um dwm fácil, é pegar uma config pronta de outros usuários. Como a famosa compilação do user Sidhanth Rathod (siduck) chamada chadwm. A desvantagem nesse caso é ficar limitado a atalhos e configurações de terceiros.
Uma terceira alternativa, seria usar distros que fornecem o dwm já pronto para uso. Como o Archcraft (que usa o chadwm) ou o Axyl (que também tem uma versão com base no chadwm).
Uma rápida comparação
Uso já a alguns anos o i3wm como TWM principal e como secundário o bspwm. Com essa experiência de uso do dwm, uma coisa ficou bem clara para mim. Eu não conseguiria usar o dwm sem adicionar, pelo menos, uns 10 patchs. Isso porque recursos que considero básicos, como layout individual para cada área de trabalho, systray e abrir uma janela em outra área de trabalho com foco ou não e mover entre as janelas em áreas de trabalho diferentes com algum utilitário (dmenu ou rofi), são essenciais para meu uso. E considero isso, funções básicas de um ambiente. i3, bspwm, openbox, xfce etc. todos já tem essas funções por padrão.
Considerações finais
Depois de tudo o que fiz, pode parecer que fiquei semanas mexendo com o dwm. Na verdade, no processo todo, eu gastei uns três ou quatro dias. Fiz tudo com calma.
Após todo esse processo, será que vale a pena usar o dwm? Eu diria que sim. Se você se identifica com o jeito que o projeto é feito e tem conhecimento ou, se não tem, como eu, pelo menos tem paciência, dá para fazer um ambiente rápido, no sentido de ser muito responsivo, e muito customizável. E quando falo em “rápido”, não é leveza, é responsividade mesmo. Ele responde a tudo muito rápido, usar um atalho ou abrir um programa por exemplo.
É um twm que tem seu jeito próprio de ser. Logo, não será do agrado de todos. Dos dois window managers de compilação que testei, dwm e 2bwm, o dwm foi o único que consegui avançar kkkkkkkkk apanhei bonito do 2bwm (tá em beta ainda) e acabei desistindo dele porque não é tiling.
Certamente ele segue a risca as ideias do projeto suckless. Mesmo após eu adicionar uma boa quantidade de patches, o meu dwm continuou bastante simples e minimalista, se comparado ao bspwm e, principalmente, ao i3wm.
Dois recursos bem básicos para o meu uso do i3/bspwm, e que considero essenciais. Abrir uma janela em outra área de trabalho e, trocar o foco para ela ou não e trocar entre as áreas de trabalho/programas com o rofi ou o dmenu. Esses dois recursos, para conseguir utilizá-los no dwm, eu tive que adicionar três patchs (ewmhtags, focusonnetactive e switchtotag).
O que mais me desanima no dwm nem é adicionar os patchs, é mais as limitações mesmo. Porque tudo, incluindo o que considero funções básicas para meu uso, tem que adicionar algum patch. Um layout específico para casa área de trabalho, por exemplo, necessita do patch pertag e por ai vai.
Afinal, como ficou seu dwm?
Seguem dois prints do resultado dessa saga. Nada de muito sofisticado, curto sempre uns ambientes mais limpos mesmo, gosto mais das funcionalidades dos twm que do visual em si. Normalmente, só mudo um pouco o visual para harmonizar as cores e o papel de parede, o resto foco em atalhos, funções do ambiente etc.
Ah, quando subir minhas configs no github, crio um tópico no “Minha Personalização”.
No final, acabei utilizando 13 patchs : actualfullscreen, autostart, bar-height, ewmhtags, focusonnetactive, focusadjacenttag, fullgaps, movestack, pertag, status2dsystray, systraysize (peguei esse patch no r/suckless, não tem disponível no site), switchtotag e zoomswap.
Referências:
https://axyl-os.github.io/
https://dwm.suckless.org/
https://dwm.suckless.org/patches/
https://github.com/archcraft-os/archcraft-dwm
https://github.com/bakkeby/
https://github.com/bakkeby/dmenu-flexipatch
https://github.com/bakkeby/dwm-flexipatch
https://github.com/bakkeby/st-flexipatch
https://github.com/siduck/chadwm/
https://libreddit.slackjeff.com.br/r/suckless