Ten list miałem zrobić gdzieś tak dopiero za dwa dni, ale z pewnych niezaleznych ode mnie przyczyn mam dzisiaj nieco więcej czasu, więc odwalę to wcześniej. Dzisiaj robię themesy.
Mamy generalnie prosty silnik do dyspozycji, który plasuje się gdzieś pomiędzy tym, co oferuje IceWM a Enlightenment/Sawfish. Z drobnymi odchyłami a'la fvwm, ale to już chyba oczywiste.
OK, co można zrobić? Można:
Zadecydować o przyciskach na pasku tytułowym. Maksymalnie 10, minimalnie 0. Nie ma się specjalnie wpływu na ich pozycję (wyjdzie w praniu). Przyciski można wypełnić kolorem albo gradientem, albo nałożyć piksmapę. A, na przyciskach można rysować wektorowe symbole. Tzn. definiuje się jakiś tam wektorowy obrazek, np. jakieś trójkąciki, i fvwm rysuje to na przycisku. Ja tam tego nie używam, ale warto wiedzieć, że można - wektorowe przyciski oczywiście znakomicie się skalują, i przy odpowiedniej konstrukcji można uzyskać coś, co np. nieco przypomina przyciski Win95 czy WindowMakera. Ja wolę mimo wszystko użyć tekstur przycisków. Chociaż jedno nie wyklucza drugiego.
Zadecydować o wyglącie paska tytułowego. Tekstury itp. Istnieją 2 metody, pokażę obydwie.
Yyy... no, ramka dookoła okna. Najsłabszy punkt całego theme-owania, najbardziej denerwujący i ograniczający. W Fvwm istnieje taka obwódka dookoła całego okna. Taka ramka. Obejmuje ona także pasek tytułowy. Można na nią nałożyć jakiś gradient czy regulować jej grubość, ale nie można np. wyłączyć ramki z boków okna. Dzięki czemu nie da się w 100% zaemulować takiego WindowMakera, który ramkę ma tylko pod oknem, z boków nie ma nic. Czegoś takiego nie da rady zrobić, można ramkę tylko co najwyżej całkowicie wyłączyć. Można albo kombinować i próbować to jakoś obejść (ale to i tak nic nie da), albo pogodzić się z tym i starać się jak najwięcej zrobić z tym, co fvwm oferuje.
Dobra. Teraz trochę suchych informacji. Wyróżniane są 2 stany okna - active/inactive. Każdemu można przypisać inaczej wyglądającą dekorację. Przyciski, jak to przyciski - aktywny/nieaktywny, i do tego dodatkowo stany wciśnięty/nie wciśnięty. Tak, istnieje stan "nieaktywny przycisk wciśnięty". Wciśnięcie przycisku w oknie nieaktywnym tak, aby go nie uaktywnić i aby pozostał nieaktywny jest może nieco wydumane, ale się zdarza. Nie ma za to stanu "hilight", czy też "mouse hover" gdy kursor myszy "wisi" nad jakimś przyciskiem. W niektórych WM przyciski wtedy się podświetlały czy inne takie efekty występowały. Szkoda, bo to takie fajne eye-candy.
Czyli reasumując - są przyciski, każdy ma 4 stany: ActiveUp, ActiveDown, InactiveUp, InactiveDown. Ilość stanów można ograniczyć, jeśli ich tyle nie potrzebujemy. A, jeśli użyje się MWM Hints, to dochodzą dodatkowe stany, np. przycisk maksymalizacji, kiedy okno jest zmaksymalizowane, może wyglądać nieco inaczej niż zwykle. Ale to teraz nieważne. A, jeszcze coś - pasek tytułowy to też przycisk. Taki duży, jak spacja na klawiaturze :)
A teraz coś, co po raz kolejny dowodzi że fvwm nie jest projektowany przez zwykłych, zdroworozsądkowych ludzi. Mianowicie numeracja przycisków:
1 3 5 7 9 xterm 0 8 6 4 2
Rozróżniamy przyciski lewe i prawe. To pośrodku to tytuł okna. Jak widać, przyciski są nieco dziwacznie numerowane, ale nie wpływa to specjalnie na funkcjonalność. Jak mówi manual, najwyższy nieparzysty numer wykorzystanego przycisku decyduje o ilości przycisków po lewej, najwyższy parzysty numer o przyciskach po prawej. Nie ma problemu ze zdefiniowaniem tylko przycisków po lewej, albo tylko po prawej stronie. W sumie to dosyć elegancki system, nieco przypominający ten z IceWM. Wszystkie przyciski mają formę kwadratów, o szerokości regulowanej wysokością paska tytułowego.
Dobra, przejdę teraz do rzeczy: Każde okno ma przypisany jakiś "Decor". Jeśli oknu nie przypisze się explicite żadnego Decor, to korzysta ono z "domyślnego" stylu. No dobra, dosyć teorii, zróbmy jakiś theme. Na pierwszy ogień pójdzie moja mozilla-modern (to, co tam na zrzutach ekranu było). Lubię ten styl, bo jest taki pastelowo-niebieskawy, leciutki i jednocześnie całkiem estetyczny. I genialnie integruje się z Mozillą w stylu "modern" :) W zasadzie, to to chyba jest modern2... ale nieważne.
Najpierw będą potrzebne "materiały" do strugania. Ja biorę je zwykle z tematów sawfisha. Dlaczego? Bo sawfisha długo używałem, i zebrałem sobie bazę kilkuset themes, z czego kilkadziesiąt było naprawdę fajnych. No więc biorę sobie ten sawfishowy theme, i pod gqview wybieram pliki, które mi się przydadzą. A przydadzą mi się jedynie piksmapy przycisków i paska tytułowego. Ewentualne piksmapy ramek bocznych okna nie będą mi potrzebne, bo i tak nie mam co z nimi zrobić. Hmm... właśnie patrzę na oryginalny, sawfishowy mozilla-modern-2, i widzę że mój został nieco okaleczony... co robimy, tworzymy wierną kopię sawfishowego stylu, czy jednak to, co ja sobie wydumałem?
E, robimy to, czego używam. Dobra, potrzebne pliki sobie skopiowałem, nieco zmieniłem im też nazwy na łatwiejsze do skojarzenia, i zamieszczam w załączniku. Wystarczy go wypakować do ~/.fvwm/images.
Nie rozumiem, czemu jest tam więcej tekstur niż wykorzystuję... chyba coś miałem z tym jeszcze zrobić... e, nieważne. Prowizorka i tak najdłużej trzyma :)
Nazwiemy tę dekorację po prostu "mozilla". Potrzebne nam tu będzie polecenie "AddToDecor". Definicję dekoracji zaczynamy poprzez:
AddToDecor mozilla
Od tej chwili fvwm oczekuje na podanie poleceń, które razem do kupy zdefiniują dekorację. Polecenia będą wykonywane w kolejności wpisania. Ale żeby podawane polecenia się wyróżniały od innych poleceń (żeby fvwm wiedział, że należą do dekoracji, a nie próbował ich od razu wykonywać) używa się "+ ". To popularne w fvwm - wystąpi też w funkcjach i menu. Używa się go, najogólniej rzecz biorąc, wszędzie tam gdzie zestawia się jakieś listy. Możemy zacząć wtedy używać poleceń definiujących wygląd dekoracji. O dekoracji można pomyśleć jak o specyficznej funkcji złożonej z listy instrukcji, z których każda jakoś wpływa na wygląd. Dozwolone w tym kontekście instrukcje to: ButtonStyle, AddButtonStyle, TitleStyle, AddTitleStyle, BorderStyle
Łatwo się zorientować, co definiuje każda z nich. "Specjalne" wersje Add* wymagają drobnego omówienia - np. "zwykły" TitleStyle jest, jak to mawiają, "fully destructive", czyli każde wywołanie TitleStyle posyła stary styl paska tytułowego w zaświaty. Funkcja "AddTitleStyle" nie niszczy starej definicji, ale po prostu dodaje kolejną warstwę. Nie można zapominać, że możemy przecież używać np. tekstur png z alpha-blendingiem, i najpierw należy położyć jakieś tło, albo z jakiegoś innego powodu nasza dekoracja składa się z warstw.
Wersje Add* nie tworzą nowego wyglądu, ale dodają nową warstwę. Tyle.
Dobra, za aktywny pasek tytułowy odpowiada w naszym przykładzie title.png, za nieaktywny pasek odpowiada title-.png. Przykładowa definicja wygląda tak:
AddToDecor mozilla + TitleStyle Active TiledPixmap mozilla/title.png + TitleStyle InActive TiledPixmap mozilla/title-.png
Jasne? Najpierw podaje się "podgrupę" którą opisujemy (Active, ActiveUp, ActiveDown, InactiveDown, !ActiveUp, !Inactive etc.). Np. "Active" oznacza od razu za jednym zamachem stan ActiveUp i ActiveDown, a !ActiveUp oznacza wszystkie stany oprócz ActiveUp. Nie wolno zapomnieć, że pasek tytułowy to przycisk jak każdy inny, i też posiada stan "wciśnięty". Czy jakoś tak. Ale że ja z tego nie korzystam, więc definiuję sobie tylko ogólne stany "aktywny" i "nieaktywny".
Kolejny parametr to TiledPixmap. Dopuszczalne są bodajże 3 rodzaje:
TiledPixmap - proste, "kafelkowana" piksmapa.
Gradient - Jakaś definicja gradientu. O gradientach trzeba by osobno pisać.
MultiPixmap - najnowszy "wynalazek", na dodatek wyszedł spod ręki kobiety. O nim będzie osobno.
A ostatni parametr to po prostu obrazek do wykorzystania. Tutaj podawana jest ścieżka względna, wyszukiwana w ImagePath.
I po tych trzech linijkach mamy już zdefiniowaną w pamięci dekorację "mozilla" która posiada jakiś aktywny i nieaktywny teksturowany pasek tytułowy. Teraz trzeba dodać przyciski. Ja lubię układ 1+2 - jeden przycisk po lewej (zamykanie okna), i dwa po prawej (minimalizacja i maksymalizacja). Do definicji dekoracji "mozilla" dodaję te linijki:
+ ButtonStyle 1 InActive Pixmap mozilla/close-.png + ButtonStyle 2 InActive Pixmap mozilla/max-.png + ButtonStyle 4 InActive Pixmap mozilla/min-.png + ButtonStyle 1 ActiveUp Pixmap mozilla/close.png + ButtonStyle 2 ActiveUp Pixmap mozilla/max.png + ButtonStyle 4 ActiveUp Pixmap mozilla/min.png + ButtonStyle 1 ActiveDown Pixmap mozilla/close+.png + ButtonStyle 2 ActiveDown Pixmap mozilla/max+.png + ButtonStyle 4 ActiveDown Pixmap mozilla/min+.png
Chyba nie trzeba specjalnie się rozpisywać? Proste, prawda? Zamiast numeru przycisku można też użyć "magicznych" słówek "All", "Left" czy "Right". Oprócz tego wygląd przycisku można zresetować, można skopiować jeden przycisk na drugi, można określić jego trójwymiarową obwódkę (raised/sunk/flat). Zamiast typu "Pixmap" można też użyć "Solid", "Vector", "Gradient", "TiledPixmap". Nie opisuję tego dokładniej, bo nie ma w tym wielkich haków i jest stosunkowo proste. Wszystko jest w manualu. A, istnieją jeszcze stany "toggled" dla niektórych przycisków (np. shade, maximize, stick itp.), ale ta dekoracja ich nie używa.
Teraz tylko trzeba dopracować wygląd. Po pierwsze, to należy "spłaszczyć" i pasek tytułowy, i przyszłe przyciski. Na razie są rysowane w "domyślnym" trybie fvwm, czyli pseudo-3d, co wygląda kretyńsko w przypadku tej dekoracji.
+ TitleStyle -- flat + ButtonStyle All -- UseTiTleStyle + ButtonStyle All -- flat
Tutaj muszę wyjaśnić. Te "--" oznaczają po prostu, że polecenie nie odnosi się do jakiegoś pojedynczego tytułu (np. aktywnego), ale że wpływa globalnie na całość. Szczegóły są w manualu. "flat" po prostu spłaszcza przyciski i usuwa ten brzydki trójwymiarowy "ramek" który by nam psuł efekt. A "UseTitleStyle" jest konieczny ze względu na specyfikę przycisków fvwm - otóż nie przylegają one do siebie. Między nimi jest standardowo przerwa właśnie na te ramki 3d i inne głupoty. Jak się zrobi "flat", to zostaje przestrzeń między przyciskami. "UseTitleStyle" rysuje pod przyciskami to, co było rysowane pod tytułem, i wszystko wygląda OK.
Teraz jeszcze poprawka ramki dookoła okna. Domyślnie w fvwm ma ona na rogach takie wydzielone, jakby "nacięciami", kawałki. Mi się to nie podoba.
+ BorderStyle -- HiddenHandles
I po sprawie.
Teraz jedyne co nam pozostało do zrobienia, to zdefiniowanie fontu, wysokości paska tytułowego, i kolorów dla ramki dookoła okien.
Najpierw przygotowuję 2 kolorsety, które będą zawierały "mozillopodobne" w tonacji gradienty. Kolorsety trzeba oczywiście zdefiniować poza dekoracją. Kolory sobie udumałem po krótkiej sesji w gimpie:
Colorset 1 VGradient 16 #dde2ea #bac5d0 Colorset 2 VGradient 16 #e3e8ef #edeff3
Definicje kolorsetów. Najpierw numer kolorsetu, potem typ (tutaj akurat prosty VerticalGradient), potem liczba kolorów w gradiencie (16), a potem kolory początkowy i końcowy, podane jako "hex triplets" (przekleiłem z gimpa). Potem magiczna linijka Style:
Style * HilightBorderColorset 1, HilightFore #576275, BorderColorset 2, ForeColor #7b89a4
Styl dla wszystkich okien ("*"), ustawia BorderColorset i ForeColor. BorderColorset to kolorset dla ramki okna, a ForeColor to m.in. kolor fontu w oknie. Wersje "Hilight*" odnoszą się do okien aktywnych, wersje "bez" do okien nieaktywnych. Jak widać, nazewnictwo opcji nie jest specjalnie spójne - pokochaj to albo znienawidź, ale tak już jest. Po tym mamy już wybrane sensowne kolory fontu oraz ramki. I ostatnia linijka:
Style * BorderWidth 4, HandleWidth 4
Wszystkie okna, szerokość ramki ustawiona na 4 piksele, szerokość "uchwytu" też na 4. Tutaj wychodzi subtelna różnica, której nie chcę teraz zgłębiać - powiedzmy, że fvwm rozróżnia ramkę z uchwytami (Handles) od takiej bez uchwytów. Dodatkowo jest to powiązane z oknami "transients", ale może nie będę straszył. Załóżmy, że dopóki się nie wie dokładnie co te opcje robią, to warto je ustawiać na identyczne wartości. No, to mamy już mniej-więcej wszystko zrobione. Tyle że mamy wygląd, za przeproszeniem, rozpieprzony po różnych sektorach - wszystkie okna mają już nowy kolor fontu i nowe grubości/kolory ramek, ale przyciski i inne takie nadal istnieją tylko w abstrakcyjnej strukturze Decor::mozilla. Żeby to zebrać do kupy wystarczy zrobić:
Style * UseDecor mozilla
I już. Dobra, sumując zmiany w plikach, ~/.fvwm/Theme:
Colorset 1 VGradient 16 #dde2ea #bac5d0 Colorset 2 VGradient 16 #e3e8ef #edeff3 AddToDecor mozilla + ButtonStyle 1 InActive Pixmap mozilla/close-.png + ButtonStyle 2 InActive Pixmap mozilla/max-.png + ButtonStyle 4 InActive Pixmap mozilla/min-.png + ButtonStyle 1 ActiveUp Pixmap mozilla/close.png + ButtonStyle 2 ActiveUp Pixmap mozilla/max.png + ButtonStyle 4 ActiveUp Pixmap mozilla/min.png + ButtonStyle 1 ActiveDown Pixmap mozilla/close+.png + ButtonStyle 2 ActiveDown Pixmap mozilla/max+.png + ButtonStyle 4 ActiveDown Pixmap mozilla/min+.png + TitleStyle Active TiledPixmap mozilla/title.png + TitleStyle InActive TiledPixmap mozilla/title-.png + TitleStyle -- flat + BorderStyle -- HiddenHandles + ButtonStyle All -- UseTiTleStyle + ButtonStyle All -- flat
~/.fvmw/Styles:
Style * HilightBorderColorset 1, HilightFore #576275, BorderColorset 2, ForeColor #7b89a4 Style * BorderWidth 4, HandleWidth 4 Style * UseDecor mozilla
Ups! Właśnie sprawdziłem, działa fajnie, tylko nie ma przycisków! Ale to proste. Przyciski pojawiają się dopiero wtedy, gdy przypisze się im jakieś funkcje. Więc przypiszmy im funkcje. Lewy przycisk (1) to zamykanie, skrajny prawy (2) to maksymalizacja, a ten drugi prawy (4) to minimalizacja. (BTW, przy liczeniu który przycisk jest który za każdym razem charakterystycznie macham dłonią ;)
Dobra, przypisania idą do pliku Bindings. ~/.fvwm/Bindings:
Mouse 1 1 A Close Mouse 1 2 A Maximize Mouse 1 4 A Iconify
Po tym pojawiają się przyciski. O, kolejny problem - są ucięte. Domyślny font to u mnie "fixed", jest za mały i tekstury paska są niższe, niż autor przewidział. Co musimy zrobić? Ustalić wysokość paska. Żeby nie przedłużać, sprawdzam wymiary naszej tekstury paska tytułowego. 19 pikseli. A więc gdzieś do ciała dekoracji "mozilla" trzeba dodać linijkę:
+ TitleStyle Height 19
(można definiować albo stałą wysokość, jak ja tutaj zrobiłem, albo zdefiniować minimalną, albo... ale to nieważne). Teraz powinno być OK. Jedyne co pozostało, to font. Można albo użyć:
Style * Font foo-shmoo
albo
DefaultFont fooshmoo
Różnica jest taka, że Style zmieni tylko font tytułowy określonych okienek, a DefaultFont ustawi font, który będzie używany wszędzie (chyba że wymusimy inny). A więc proponuję tutaj użyć DefaultFont. Takie polecenie powinno się znaleźć w General. Składnia opisu fontu jest normalna, X-owa, czyli np.
DefaultFont -*-arial-medium-r-normal-*
Jeśli ktoś ma szczęście i skompilował sobie fvwm z obsługą Xft/Xft2, to może cieszyć oczy antyaliasowanymi fontami. Te wybiera się za pomocą prefiksu "xft:", np.
DefaultFont xft:arial-11:bold
Oczywiście to wymaga poprawnie skonfigurowanego Xft (/etc/X11/XftConfig, oraz uruchomienie wcześniej xftcache żeby stworzył cache. O Xft2 nawet nie będę pisał, bo tego chyba jeszcze w dystrybucjach nie dają.) Działa bardzo zacnie :)
A więc moja propozycja to np.
~/.fvwm/GeneralDefaultFont xft:arial-11:bold
Dobra, więc po tym powinien już działać prosty theme.
Od razu dorzucę podobną dekorację "Icicle" (drugi załącznik)
AddToDecor Icicle + TitleStyle Active MultiPixmap Main (stretched) Icicle/title-a.png, \ LeftEnd Icicle/title-left-a.png, RightEnd Icicle/title-right-a.png + ButtonStyle 1 ActiveUp Pixmap Icicle/kill-button-a.png + ButtonStyle 2 ActiveUp Pixmap Icicle/max-button-a.png + ButtonStyle 4 ActiveUp Pixmap Icicle/min-button-a.png + ButtonStyle 6 ActiveUp Pixmap Icicle/menubutton-a.png + ButtonStyle 1 ActiveDown Pixmap Icicle/kill-button-c.png + ButtonStyle 2 ActiveDown Pixmap Icicle/max-button-c.png + ButtonStyle 4 ActiveDown Pixmap Icicle/min-button-c.png + ButtonStyle 6 ActiveDown Pixmap Icicle/menubutton-c.png + TitleStyle InActive MultiPixmap Main (stretched) Icicle/title-i.png, \ LeftEnd Icicle/title-left-i.png, RightEnd Icicle/title-right-i.png + ButtonStyle 1 Inactive Pixmap Icicle/kill-button-i.png + ButtonStyle 2 InActive Pixmap Icicle/max-button-i.png + ButtonStyle 4 InActive Pixmap Icicle/min-button-i.png + ButtonStyle 6 InActive Pixmap Icicle/menubutton-i.png + TitleStyle Height 22 -- flat + ButtonStyle All -- UseTitleStyle flat + BorderStyle -- HiddenHandles
Robione kubek-w-kubek tak samo, jak mozilla, tyle że pasek tytułowy jest zestawiony za pomocą MultiPixmap. Akurat ten przykład jest do niczego, bo wcale nie pokazuje co też MultiPixmap robi. Ale opiszę. MultiPixmap pozwala złożyć pasek tytułowy z kilku różnych tekstur.
Można określić główną część paska, lewą, prawą, zaraz na lewo od tekstu, zaraz na prawo od tekstu, pod lewymi przyciskami, pod prawymi przyciskami, pod samym tekstem tytułu. Może zestawię jakiś theme "na szybko"... <pięć minut na sesję z X-ami>
Ok, w trzecim załączniku idzie coś Crux-like:
AddToDecor Crux + TitleStyle Inactive MultiPixmap Main (Tiled) Crux/inactive:top-center-left.png, \ RightMain (Tiled) Crux/inactive:top-center-right.png, \ RightOfText Crux/inactive:top-center-mid.png, LeftButtons Crux/inactive:top-center-left.png + ButtonStyle All Inactive Pixmap Crux/inactive:button.png + ButtonStyle All InactiveDown Pixmap Crux/inactive:button-pressed.png + ButtonStyle 1 InactiveUp Pixmap Crux/inactive:menu-button.png + AddButtonStyle 1 InactiveUp Pixmap Crux/inactive:close-button.png + AddButtonStyle 2 InactiveUp Pixmap Crux/inactive:maximize-button.png + AddButtonStyle 4 InactiveUp Pixmap Crux/inactive:minimize-button.png + AddButtonStyle 6 InactiveUp Pixmap Crux/inactive:shade-button.png + TitleStyle Active MultiPixmap Main (Tiled) Crux/active:top-center-left.png, \ RightMain (Tiled) Crux/active:top-center-right.png, \ RightOfText Crux/active:top-center-mid.png, LeftButtons Crux/active:top-center-left.png + ButtonStyle All active Pixmap Crux/active:button.png + ButtonStyle All activeDown Pixmap Crux/active:button-pressed.png + ButtonStyle 1 activeUp Pixmap Crux/active:menu-button.png + ButtonStyle 1 activedown Pixmap Crux/active:menu-button-pressed.png + ButtonStyle 1 inactivedown Pixmap Crux/inactive:menu-button-pressed.png + AddButtonStyle 1 active Pixmap Crux/active:close-button.png + AddButtonStyle 2 active Pixmap Crux/active:maximize-button.png + AddButtonStyle 4 active Pixmap Crux/active:minimize-button.png + AddButtonStyle 6 active Pixmap Crux/active:shade-button.png + BorderStyle -- HiddenHandles + TitleStyle -- flat + ButtonStyle All -- flat usetitlestyle
No, ten theme lepiej wykorzystuje możliwości MultiPixmap. Dodatkowo robi użytek z AddButtonStyle (nakłada na "puste" tekstury przycisku same symbole), i całkiem ładnie redukuje ilość definicji tam, gdzie nie trzeba było mieszać. A, i theme zawiera czwarty przycisk na pozycji szóstej (Icicle zresztą też), pojawi się po zrobieniu np.
Mouse 1 6 A WindowShade
w FvwmConsole czy dopisaniu tego do "Bindings". Nie chciało mi się już kombinować z kolorem fontu czy ramki, ale to już drobnostka i "zadanie domowe". Potem można sobie w FvwmConsole wpisać np.
Style FvwmConsole UseDecor Crux Style xterm UseDecor Icicle
i mieć obydwa wystroje jednocześnie na ekranie.
Są pytania, zażalenia?
Czy ktoś w ogóle to jeszcze czyta? Bo tak coś czuję że to piszę dla siebie...