bakkeby / patches

Collection of patches for dwm, st and dmenu
286 stars 30 forks source link

Flickering with the dwm-alpha-systray-6.2 patch #37

Closed stiftcast closed 3 years ago

stiftcast commented 3 years ago

When the patch is applied, the bar will flicker sometimes when focus is changed rapidly, either by calling focusstack() or moving with the mouse. Seems to happen more frequently if there is something in the status area. It does not occur when using the dwm-alpha-6.2 patch on it's own, or with dwm-systray-6.2 by itself either.

Running a compositor such as picom or xcompmgr seems to have no effect, as it does the same thing.

flicker

bakkeby commented 3 years ago

Thanks for the report and for the gif, that's very helpful.

It looks like this is specifically about the systray, at least I find it hard to replicate if I set the showsystray setting to 0 in config.h. Will dig around to see if I can find out some more.

bakkeby commented 3 years ago

Looks to be caused by this section clearing the status bar to avoid artefacts appearing beneath the systray.

void
drawbars(void)
{
    Monitor *m;

    if (showsystray) {
        /* Clear status bar to avoid artifacts beneath systray icons */
        drw_setscheme(drw, scheme[SchemeNorm]);
        drw_rect(drw, 0, 0, selmon->ww, bh, 1, 1);
        drw_map(drw, selmon->barwin, 0, 0, selmon->ww, bh);
    }

    for (m = mons; m; m = m->next)
        drawbar(m);

    if (showsystray)
        updatesystray();
}

I'll refactor, there shouldn't be any reason to do this every time the bar is drawn.

bakkeby commented 3 years ago

Hi @stiftcast, I have uploaded a new version of the patch now. Let me know if you encounter any other issues, thaks.

stiftcast commented 3 years ago

Hey @bakkeby thanks for looking into this. I tested the patch you uploaded against a fresh build, just noticed a few things. The patch seems to work fine with a single monitor, though since I am running a multi-monitor setup, it was causing some issues if the systraypinning option was set to 0 - where it's supposed to follow the focused monitor. It wasn't drawing, so I had to add back the last if statement to drawbars:

void
drawbars(void)
{
        Monitor *m;

        for (m = mons; m; m = m->next)
                drawbar(m);

        if (showsystray)
                updatesystray();
}

I notice when it's added back, it will start to flicker again when focusing rapidly.

However, I usually have that option set to greater than 0, as I prefer it pinned to one monitor, and have found that it works better if that if statement is omitted - so i've removed it again. If it is pinned to one monitor though, there seems to be a weird issue with the bars on the adjacent monitors, where they will be sometimes be overwritten with SchemeNorm:

bar

Removing these lines from updatesystray() helps solve it:

        /* Clear status bar to avoid artifacts beneath systray icons */
        drw_setscheme(drw, scheme[SchemeNorm]);
        drw_rect(drw, 0, 0, selmon->ww, bh, 1, 1);
        drw_map(drw, selmon->barwin, 0, 0, selmon->ww, bh);

But removing those lines will then cause artifacts to reappear beneath the systray - especially if the status text and the systray are pinned to the same monitor.

bakkeby commented 3 years ago

Thanks again.

Yes so the "systray follows active monitor" like the status by default I overlooked, I also prefer it to be pinned to one monitor.

In the clearing bit I should have used m instead of selmon, but it was overall not a particularly good solution. I ended up moving that logic to drawbar instead.

Another thing that was not a direct problem, but more of an annoyance, was how the bar would end up being drawn twice for the monitor the systray is on. I did some more refactoring to try and address that.

It should hopefully be more smooth now overall, but if you come across any other oddities just let me know.

stiftcast commented 3 years ago

Seems to be working quite well now. Noticed that it sometimes would still re-draw the bar if I spawed something for the systray, say nm-applet, on an adjacent monitor from where the systray was pinned. I made a little modification in clientmessage() that appears to fix the issue by using the value of systraytomon() instead of calling selmon directly, just so it only clears those artifacts & redraws on the monitor the systray is actually on. So far so good otherwise, flickering seems to have subsided now, thanks for all your hard work.

Monitor *m = systraytomon(NULL);
/* Clear status bar to avoid artifacts beneath systray icons */
drw_rect(drw, 0, 0, m->ww, bh, 1, 1);
drw_map(drw, m->barwin, 0, 0, m->ww, bh);
bakkeby commented 3 years ago

@stiftcast I think those lines are no longer needed actually, I'll remove them.