USE SURF WITHOUT A WELDING HELMET Who here has lived to use `surf' in a darkened room and lived to tell the tale? I have, though my eyes are worse for wear for it. I'd been told it was a character building exercise: that momentary flash of white while `surf' loads a webpage will put hair on your chest, turn your automatic Subaru into a manual Honda Civic, and get your wife pregnant. Sure, the character of my cataracts was developing at a positively accelerated rate. I'd considered getting out the welding helmet, or else timing my blinks to coincide with that momentary blast of #FFFFFF just to avoid shock. I'd also done my customary web search to learn how to enable darkmode in `surf'. I found halfway answers: stylesheets would make the loaded page show in a darkmode. But still: a blinding whitescreen between when `surf' launches and when WebKit has finished loading the page persists. ,---- | /* Place these styles inside ~/.surf/styles/default.css to get | darkmode on every website. Code adapted from: | https://surf.suckless.org/stylesheets/darkmode_css/ */ | *,div,pre,textarea,body,input,td,tr,p { | background-color: #000000 !important; | background-image: none !important; | color: #bbbbbb !important; | } | h1,h2,h3,h4 { | background-color: #000000 !important; | color: #b8ddea !important; | } | img { | opacity: .5; | } | img:hover { | opacity: 1; | } `---- I decided to clone the repo and dig around the code for opportunities to extinguish the flame. To get things building properly on Void I had to install two new dependencies: `webkit2gtk-devel' and `gcr-devel'. I started my playing around by commenting out some code and adding print statements to see what runs where. Towards the bottom of `surf.c' I found that if I only invoked `showview' I could preserve that blinding whitescreen forever as long as the program is running (nice!). ,---- | c = newclient(NULL); | showview(NULL, c); | /* loaduri(c, &arg); */ | /* updatetitle(c); */ | /* gtk_main(); */ | /* cleanup(); */ `---- That lead me to look into `showview'. Immediately I noticed the `bgcolor' variable. I tried changing it from `GdkRGBA bgcolor = { 0 };' to `GdkRGBA bgcolor = { 1,0,0,1 };', using full-on red just as a test so I could see it. It made no difference. From here I went to the `createwindow' function, which is called from inside `showview'. I noticed that this function creates the GTK window which eventually contains the WebKit view. I found a place to set the default background color of the GTK window to black. After a `make', I found that this eliminated most of the white screen. `surf' launched in black, momentarily showed white, and then loaded the page. ,---- | GtkWidget * | createwindow(Client *c) | { Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! `---- From here, I went back to the `main' function and manually traced the function invokations below `showview'. This lead me to a few functions of interest: `loaduri', `loadchanged', and `newview)'. I soon understood the order of the presentation: the GTK window was created first, then it was filled with the WebKit view. WebKit loads the uri with `webkit_web_view_load_uri(c->view, url);' and then there are various loading signals from `WEBKIT_LOAD_STARTED' to `WEBKIT_LOAD_FINISHED'. I'd taken care of setting the GTK window background to black, thus achieving an amount of success. But the WebKit view stayed white while the page loaded. My quest to be fully enveloped by darkmode continued. For a while, my hypothesis was that I needed to adjust something around the WebKit load signals or maybe introduce my darkmode CSS stylesheet earlier, somehow, to get rid of the white flash that remained between the GTK window and the WebKit view. Maybe, I thought, the WebKit view allowed CSS styles even before the page loaded. I peeked back into the `newview' function and noticed therein how settings were applied to the WebKit view. I added `setstyle(c, getstyle(geturi(c)));' just before the return statement, thinking this stylesheet would avoid the whitescreen in the WebKit view. That didn't work, but I noticed this nearby: `setparameter(c, 0, DarkMode, &curconfig[DarkMode].val);' I found that this value could be set from `config.h'. I set the value to `1' and recompile under bated breath. Still no full darkmode. Now I'm a bit hazy about what happened next. I was in a frenzy! (Family and friends be damned that I didn't answer the phone for I was `hacking'!) But it seems that in the moment of despair that followed failure I dragged myself back to `showview'. I played with the `bgcolor' variable again, then looked more closely at the `showview' function's logic. The prize that I sought stood out like a toad in a hole: ,---- | if (curconfig[HideBackground].val.i) Happy helping ☃ here: You tried to output a spurious TAB character. This will break gopher. Please review your scripts. Have a nice day! `---- I moved briskly over to `config.h' and set `HideBackground' to `1'. I `make''d and ... voila! No blinding whitescreen of fire! I had found my full darkmode. It seems that setting the WebKit view background to a `GdkRGBA bgcolor = { 0 }' (as happens when the statement above evaluates) causes the view to have a black background. Combined this with the GTK window set with a black background and the whitescreen is entirely avoided. Summary ---------------------------------------------------------------------- To effect pretty good darkmode in `surf' (it will show a gray fill while the GTK window is built and the WebKit view loads), do the following: 1. Clone the repo. Install dependencies and get a successful `make'. 2. Modify `config.h' so `HideBackground' and `DarkMode' are both set to `{ .i = 1 }' 3. Create a default stylesheet at `~/.surf/styles/default.css' including the aforementioned darkmode styles. 4. Build surf. 5. Put away your welding helmet. To effect an even better darkmode in `surf' (it will show a black fill from launch up until page load), do the above *and* add the following snippet to line 1464, just before `createwindow' returns. ,---- | gtk_widget_modify_bg(GTK_WINDOW(w), GTK_STATE_NORMAL, &(GdkColor){0}); `---- Patch ---------------------------------------------------------------------- Below is a patch you can apply. Note that you'll still need to manually add a stylesheet to affect darkmode on the websites you visit. This patch only eliminates the whitescreens during `surf''s launch and load procedures. ,---- | From 25fedb98bc24067ce04d6b9daa49b4950ea4d3a2 Mon Sep 17 00:00:00 2001 | From: Scarlett McAllister <no+reply@roygbyte.com> | Date: Thu, 28 Dec 2023 13:44:21 -0400 | Subject: [PATCH] Add darkmode to GTK window | --- | config.def.h | 4 ++-- | surf.c | 1 + | 2 files changed, 3 insertions(+), 2 deletions(-) | diff --git a/config.def.h b/config.def.h | index 93cfeeb..0214d6e 100644 | --- a/config.def.h | +++ b/config.def.h | @@ -20,7 +20,7 @@ static Parameter defconfig[ParameterLast] = { | [Certificate] = { { .i = 0 }, }, | [CaretBrowsing] = { { .i = 0 }, }, | [CookiePolicies] = { { .v = "@Aa" }, }, | - [DarkMode] = { { .i = 0 }, }, | + [DarkMode] = { { .i = 1 }, }, | [DefaultCharset] = { { .v = "UTF-8" }, }, | [DiskCache] = { { .i = 1 }, }, | [DNSPrefetch] = { { .i = 0 }, }, | @@ -29,7 +29,7 @@ static Parameter defconfig[ParameterLast] = { | [FontSize] = { { .i = 12 }, }, | [FrameFlattening] = { { .i = 0 }, }, | [Geolocation] = { { .i = 0 }, }, | - [HideBackground] = { { .i = 0 }, }, | + [HideBackground] = { { .i = 1 }, }, | [Inspector] = { { .i = 0 }, }, | [Java] = { { .i = 1 }, }, | [JavaScript] = { { .i = 1 }, }, | diff --git a/surf.c b/surf.c | index f8c8dec..a6cb224 100644 | --- a/surf.c | +++ b/surf.c | @@ -1461,6 +1461,7 @@ createwindow(Client *c) | g_signal_connect(G_OBJECT(w), "window-state-event", | G_CALLBACK(winevent), c); | | + gtk_widget_modify_bg(GTK_WINDOW(w), GTK_STATE_NORMAL, &(GdkColor){0}); | return w; | } | | -- | 2.42.0 `----