[wiki] [sites] [dwm][patch][single_tagset] Fix patch to make it work with last commit (67d76bd) || BrunoCooper17
commit 2b88d5a313d1e22560a930ea14166412f4d5e5c0
Author: BrunoCooper17 <BrunoCooper17_AT_outlook.com>
Date: Wed Jun 23 11:28:49 2021 -0500
[dwm][patch][single_tagset] Fix patch to make it work with last commit (67d76bd)
diff --git a/dwm.suckless.org/patches/single_tagset/dwm-single_tagset-20210623-67d76bd.diff b/dwm.suckless.org/patches/single_tagset/dwm-single_tagset-20210623-67d76bd.diff
new file mode 100644
index 00000000..4756174c
--- /dev/null
+++ b/dwm.suckless.org/patches/single_tagset/dwm-single_tagset-20210623-67d76bd.diff
_AT_@ -0,0 +1,552 @@
+From 116830e90487d53cbe44c05a8c0ffe8985e1509e Mon Sep 17 00:00:00 2001
+From: BrunoCooper17 <BrunoCooper17_AT_outlook.com>
+Date: Tue, 22 Jun 2021 22:31:37 -0500
+Subject: [PATCH] An updated single_tagset patch for dwm-6.2
+
+Description
+This patch addresses the multi-monitor setup. Instead of having separate tags for every monitor there is just one list of tags for all monitors. Instead of moving windows from one monitor to the other, the desired tag from the other monitor can just be selected and all windows will be drawn on the current monitor.
+
+Several deep changes needed to be made:
+
+Macro ISVISIBLE expects a second parameter, the monitor
+Monitor->clients and Monitor->stack were moved to the global variable Clientlist cl. All monitors refer to this one list.
+A new method attachclients was added. When changing between tags this function ensures that all clients are pointing to the right monitor.
+
+Authors
+Jan Christoph Ebersbach - jceb_AT_e-jc.de
+Mohammad Zeinali - mzeinali_AT_tutanota.com
+Jesus Mastache Caballero - <BrunoCooper17_AT_outlook.com>
+
+---
+ dwm.c | 226 ++++++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 171 insertions(+), 55 deletions(-)
+
+diff --git a/dwm.c b/dwm.c
+index b0b3466..10d7f6e 100644
+--- a/dwm.c
++++ b/dwm.c
+_AT_@ -49,7 +49,7 @@
+ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+ #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
+ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
+-#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
++#define ISVISIBLE(C, M) ((C->tags & M->tagset[M->seltags]))
+ #define LENGTH(X) (sizeof X / sizeof X[0])
+ #define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+ #define WIDTH(X) ((X)->w + 2 * (X)->bw)
+_AT_@ -82,6 +82,7 @@ typedef struct {
+ const Arg arg;
+ } Button;
+
++typedef struct Clientlist Clientlist;
+ typedef struct Monitor Monitor;
+ typedef struct Client Client;
+ struct Client {
+_AT_@ -124,9 +125,8 @@ struct Monitor {
+ unsigned int tagset[2];
+ int showbar;
+ int topbar;
+- Client *clients;
++ Clientlist *cl;
+ Client *sel;
+- Client *stack;
+ Monitor *next;
+ Window barwin;
+ const Layout *lt[2];
+_AT_@ -141,12 +141,18 @@ typedef struct {
+ int monitor;
+ } Rule;
+
++struct Clientlist {
++ Client *clients;
++ Client *stack;
++};
++
+ /* function declarations */
+ static void applyrules(Client *c);
+ static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
+ static void arrange(Monitor *m);
+ static void arrangemon(Monitor *m);
+ static void attach(Client *c);
++static void attachclients(Monitor *m);
+ static void attachstack(Client *c);
+ static void buttonpress(XEvent *e);
+ static void checkotherwm(void);
+_AT_@ -184,7 +190,7 @@ static void maprequest(XEvent *e);
+ static void monocle(Monitor *m);
+ static void motionnotify(XEvent *e);
+ static void movemouse(const Arg *arg);
+-static Client *nexttiled(Client *c);
++static Client *nexttiled(Client *c, Monitor *m);
+ static void pop(Client *);
+ static void propertynotify(XEvent *e);
+ static void quit(const Arg *arg);
+_AT_@ -268,6 +274,7 @@ static Display *dpy;
+ static Drw *drw;
+ static Monitor *mons, *selmon;
+ static Window root, wmcheckwin;
++static Clientlist *cl;
+
+ /* configuration, allows nested code to access above variables */
+ #include "config.h"
+_AT_@ -300,7 +307,7 @@ applyrules(Client *c)
+ {
+ c->isfloating = r->isfloating;
+ c->tags |= r->tags;
+- for (m = mons; m && m->num != r->monitor; m = m->next);
++ for (m = mons; m && (m->tagset[m->seltags] & c->tags) == 0; m = m->next);
+ if (m)
+ c->mon = m;
+ }
+_AT_@ -382,9 +389,9 @@ void
+ arrange(Monitor *m)
+ {
+ if (m)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ else for (m = mons; m; m = m->next)
+- showhide(m->stack);
++ showhide(m->cl->stack);
+ if (m) {
+ arrangemon(m);
+ restack(m);
+_AT_@ -403,15 +410,49 @@ arrangemon(Monitor *m)
+ void
+ attach(Client *c)
+ {
+- c->next = c->mon->clients;
+- c->mon->clients = c;
++ c->next = c->mon->cl->clients;
++ c->mon->cl->clients = c;
++}
++
++void
++attachclients(Monitor *m) {
++ /* attach clients to the specified monitor */
++ Monitor *tm;
++ Client *c;
++ unsigned int utags = 0;
++ Bool rmons = False;
++ if(!m)
++ return;
++
++ /* collect information about the tags in use */
++ for (tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ utags |= tm->tagset[tm->seltags];
++
++ for (c = m->cl->clients; c; c = c->next)
++ if(ISVISIBLE(c, m)) {
++ /* if client is also visible on other tags that are displayed on
++ * other monitors, remove these tags */
++ if(c->tags & utags) {
++ c->tags = c->tags & m->tagset[m->seltags];
++ rmons = True;
++ }
++ unfocus(c, True);
++ c->mon = m;
++ }
++
++ if (rmons)
++ for (tm = mons; tm; tm = tm->next)
++ if(tm != m)
++ arrange(tm);
++
+ }
+
+ void
+ attachstack(Client *c)
+ {
+- c->snext = c->mon->stack;
+- c->mon->stack = c;
++ c->snext = c->mon->cl->stack;
++ c->mon->cl->stack = c;
+ }
+
+ void
+_AT_@ -478,8 +519,8 @@ cleanup(void)
+ view(&a);
+ selmon->lt[selmon->sellt] = &foo;
+ for (m = mons; m; m = m->next)
+- while (m->stack)
+- unmanage(m->stack, 0);
++ while (m->cl->stack)
++ unmanage(m->cl->stack, 0);
+ XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ while (mons)
+ cleanupmon(mons);
+_AT_@ -565,7 +606,7 @@ configurenotify(XEvent *e)
+ drw_resize(drw, sw, bh);
+ updatebars();
+ for (m = mons; m; m = m->next) {
+- for (c = m->clients; c; c = c->next)
++ for (c = m->cl->clients; c; c = c->next)
+ if (c->isfullscreen)
+ resizeclient(c, m->mx, m->my, m->mw, m->mh);
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+_AT_@ -611,7 +652,7 @@ configurerequest(XEvent *e)
+ c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
+ if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
+ configure(c);
+- if (ISVISIBLE(c))
++ if (ISVISIBLE(c, m))
+ XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
+ } else
+ configure(c);
+_AT_@ -631,10 +672,31 @@ configurerequest(XEvent *e)
+ Monitor *
+ createmon(void)
+ {
+- Monitor *m;
++ Monitor *m, *tm;
++ int i;
+
++ /* bail out if the number of monitors exceeds the number of tags */
++ for (i=1, tm=mons; tm; i++, tm=tm->next);
++ if (i > LENGTH(tags)) {
++ fprintf(stderr, "dwm: failed to add monitor, number of tags exceeded
");
++ return NULL;
++ }
++ /* find the first tag that isn't in use */
++ for (i=0; i < LENGTH(tags); i++) {
++ for (tm=mons; tm && !(tm->tagset[tm->seltags] & (1<<i)); tm=tm->next);
++ if (!tm)
++ break;
++ }
++ /* reassign all tags to monitors since there's currently no free tag for the
++ * new monitor */
++ if (i >= LENGTH(tags))
++ for (i=0, tm=mons; tm; tm=tm->next, i++) {
++ tm->seltags ^= 1;
++ tm->tagset[tm->seltags] = (1<<i) & TAGMASK;
++ }
+ m = ecalloc(1, sizeof(Monitor));
+- m->tagset[0] = m->tagset[1] = 1;
++ m->cl = cl;
++ m->tagset[0] = m->tagset[1] = (1<<i) & TAGMASK;
+ m->mfact = mfact;
+ m->nmaster = nmaster;
+ m->showbar = showbar;
+_AT_@ -660,7 +722,7 @@ detach(Client *c)
+ {
+ Client **tc;
+
+- for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
++ for (tc = &c->mon->cl->clients; *tc && *tc != c; tc = &(*tc)->next);
+ *tc = c->next;
+ }
+
+_AT_@ -669,11 +731,11 @@ detachstack(Client *c)
+ {
+ Client **tc, *t;
+
+- for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
++ for (tc = &c->mon->cl->stack; *tc && *tc != c; tc = &(*tc)->snext);
+ *tc = c->snext;
+
+ if (c == c->mon->sel) {
+- for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
++ for (t = c->mon->cl->stack; t && !ISVISIBLE(t, c->mon); t = t->snext);
+ c->mon->sel = t;
+ }
+ }
+_AT_@ -709,7 +771,7 @@ drawbar(Monitor *m)
+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ }
+
+- for (c = m->clients; c; c = c->next) {
++ for (c = m->cl->clients; c; c = c->next) {
+ occ |= c->tags;
+ if (c->isurgent)
+ urg |= c->tags;
+_AT_@ -784,8 +846,8 @@ expose(XEvent *e)
+ void
+ focus(Client *c)
+ {
+- if (!c || !ISVISIBLE(c))
+- for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
++ if (!c || !ISVISIBLE(c, selmon))
++ for (c = selmon->cl->stack; c && !ISVISIBLE(c, selmon); c = c->snext);
+ if (selmon->sel && selmon->sel != c)
+ unfocus(selmon->sel, 0);
+ if (c) {
+_AT_@ -838,16 +900,16 @@ focusstack(const Arg *arg)
+ if (!selmon->sel || selmon->sel->isfullscreen)
+ return;
+ if (arg->i > 0) {
+- for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
++ for (c = selmon->sel->next; c && !ISVISIBLE(c, selmon); c = c->next);
+ if (!c)
+- for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
++ for (c = selmon->cl->clients; c && !ISVISIBLE(c, selmon); c = c->next);
+ } else {
+- for (i = selmon->clients; i != selmon->sel; i = i->next)
+- if (ISVISIBLE(i))
++ for (i = selmon->cl->clients; i != selmon->sel; i = i->next)
++ if (ISVISIBLE(i, selmon))
+ c = i;
+ if (!c)
+ for (; i; i = i->next)
+- if (ISVISIBLE(i))
++ if (ISVISIBLE(i, selmon))
+ c = i;
+ }
+ if (c) {
+_AT_@ -1107,12 +1169,12 @@ monocle(Monitor *m)
+ unsigned int n = 0;
+ Client *c;
+
+- for (c = m->clients; c; c = c->next)
+- if (ISVISIBLE(c))
++ for (c = m->cl->clients; c; c = c->next)
++ if (ISVISIBLE(c, m))
+ n++;
+ if (n > 0) /* override layout symbol */
+ snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+- for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
++ for (c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m))
+ resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 0);
+ }
+
+_AT_@ -1194,9 +1256,9 @@ movemouse(const Arg *arg)
+ }
+
+ Client *
+-nexttiled(Client *c)
++nexttiled(Client *c, Monitor *m)
+ {
+- for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
++ for (; c && (c->isfloating || !ISVISIBLE(c, m)); c = c->next);
+ return c;
+ }
+
+_AT_@ -1360,8 +1422,8 @@ restack(Monitor *m)
+ if (m->lt[m->sellt]->arrange) {
+ wc.stack_mode = Below;
+ wc.sibling = m->barwin;
+- for (c = m->stack; c; c = c->snext)
+- if (!c->isfloating && ISVISIBLE(c)) {
++ for (c = m->cl->stack; c; c = c->snext)
++ if (!c->isfloating && ISVISIBLE(c, m)) {
+ XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
+ wc.sibling = c->win;
+ }
+_AT_@ -1414,11 +1476,9 @@ sendmon(Client *c, Monitor *m)
+ if (c->mon == m)
+ return;
+ unfocus(c, 1);
+- detach(c);
+ detachstack(c);
+ c->mon = m;
+ c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
+- attach(c);
+ attachstack(c);
+ focus(NULL);
+ arrange(NULL);
+_AT_@ -1541,6 +1601,8 @@ setup(void)
+ screen = DefaultScreen(dpy);
+ sw = DisplayWidth(dpy, screen);
+ sh = DisplayHeight(dpy, screen);
++ if(!(cl = (Clientlist *)calloc(1, sizeof(Clientlist))))
++ die("fatal: could not malloc() %u bytes
", sizeof(Clientlist));
+ root = RootWindow(dpy, screen);
+ drw = drw_create(dpy, screen, root, sw, sh);
+ if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
+_AT_@ -1616,7 +1678,7 @@ showhide(Client *c)
+ {
+ if (!c)
+ return;
+- if (ISVISIBLE(c)) {
++ if (ISVISIBLE(c, c->mon)) {
+ /* show clients top down */
+ XMoveWindow(dpy, c->win, c->x, c->y);
+ if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
+_AT_@ -1656,7 +1718,23 @@ spawn(const Arg *arg)
+ void
+ tag(const Arg *arg)
+ {
++ Monitor *m;
++ unsigned int newtags;
+ if (selmon->sel && arg->ui & TAGMASK) {
++ newtags = arg->ui & TAGMASK;
++ for (m = mons; m; m = m->next)
++ /* if tag is visible on another monitor, move client to the new monitor */
++ if (m != selmon && m->tagset[m->seltags] & newtags) {
++ /* prevent moving client to all tags (MODKEY-Shift-0) when multiple monitors are connected */
++ if(newtags & selmon->tagset[selmon->seltags])
++ return;
++ selmon->sel->tags = newtags;
++ selmon->sel->mon = m;
++ arrange(m);
++ break;
++ }
++ /* workaround in case just one monitor is connected */
++
+ selmon->sel->tags = arg->ui & TAGMASK;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1677,7 +1755,7 @@ tile(Monitor *m)
+ unsigned int i, n, h, mw, my, ty;
+ Client *c;
+
+- for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++ for (n = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), n++);
+ if (n == 0)
+ return;
+
+_AT_@ -1685,7 +1763,7 @@ tile(Monitor *m)
+ mw = m->nmaster ? m->ww * m->mfact : 0;
+ else
+ mw = m->ww;
+- for (i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
++ for (i = my = ty = 0, c = nexttiled(m->cl->clients, m); c; c = nexttiled(c->next, m), i++)
+ if (i < m->nmaster) {
+ h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+ resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - (2*c->bw), 0);
+_AT_@ -1725,12 +1803,17 @@ togglefloating(const Arg *arg)
+ void
+ toggletag(const Arg *arg)
+ {
++ Monitor *m;
+ unsigned int newtags;
+
+ if (!selmon->sel)
+ return;
+ newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
+ if (newtags) {
++ /* prevent adding tags that are in use on other monitors */
++ for (m = mons; m; m = m->next)
++ if (m != selmon && newtags & m->tagset[m->seltags])
++ return;
+ selmon->sel->tags = newtags;
+ focus(NULL);
+ arrange(selmon);
+_AT_@ -1740,12 +1823,27 @@ toggletag(const Arg *arg)
+ void
+ toggleview(const Arg *arg)
+ {
++ Monitor *m;
+ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
+
+ if (newtagset) {
++ /* prevent displaying the same tags on multiple monitors */
++ for(m = mons; m; m = m->next)
++ if(m != selmon && newtagset & m->tagset[m->seltags])
++ return;
+ selmon->tagset[selmon->seltags] = newtagset;
+- focus(NULL);
++ attachclients(selmon);
+ arrange(selmon);
++ focus(NULL);
++
++ unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
++
++ if (newtagset) {
++ selmon->tagset[selmon->seltags] = newtagset;
++ attachclients(selmon);
++ arrange(selmon);
++ focus(NULL);
++ }
+ }
+ }
+
+_AT_@ -1844,7 +1942,7 @@ updateclientlist()
+
+ XDeleteProperty(dpy, root, netatom[NetClientList]);
+ for (m = mons; m; m = m->next)
+- for (c = m->clients; c; c = c->next)
++ for (c = m->cl->clients; c; c = c->next)
+ XChangeProperty(dpy, root, netatom[NetClientList],
+ XA_WINDOW, 32, PropModeAppend,
+ (unsigned char *) &(c->win), 1);
+_AT_@ -1874,8 +1972,10 @@ updategeom(void)
+ if (n <= nn) { /* new monitors available */
+ for (i = 0; i < (nn - n); i++) {
+ for (m = mons; m && m->next; m = m->next);
+- if (m)
++ if (m) {
+ m->next = createmon();
++ attachclients(m->next);
++ }
+ else
+ mons = createmon();
+ }
+_AT_@ -1895,16 +1995,13 @@ updategeom(void)
+ } else { /* less monitors available nn < n */
+ for (i = nn; i < n; i++) {
+ for (m = mons; m && m->next; m = m->next);
+- while ((c = m->clients)) {
+- dirty = 1;
+- m->clients = c->next;
+- detachstack(c);
+- c->mon = mons;
+- attach(c);
+- attachstack(c);
+- }
+ if (m == selmon)
+ selmon = mons;
++ for (c = m->cl->clients; c; c = c->next) {
++ dirty = True;
++ if (c->mon == m)
++ c->mon = selmon;
++ }
+ cleanupmon(m);
+ }
+ }
+_AT_@ -2038,13 +2135,32 @@ updatewmhints(Client *c)
+ void
+ view(const Arg *arg)
+ {
++ Monitor *m;
++ unsigned int newtagset = selmon->tagset[selmon->seltags ^ 1];
+ if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ return;
++ /* swap tags when trying to display a tag from another monitor */
++ if (arg->ui & TAGMASK)
++ newtagset = arg->ui & TAGMASK;
++ for (m = mons; m; m = m->next)
++ if (m != selmon && newtagset & m->tagset[m->seltags]) {
++ /* prevent displaying all tags (MODKEY-0) when multiple monitors
++ * are connected */
++ if (newtagset & selmon->tagset[selmon->seltags])
++ return;
++ m->sel = selmon->sel;
++ m->seltags ^= 1;
++ m->tagset[m->seltags] = selmon->tagset[selmon->seltags];
++ attachclients(m);
++ arrange(m);
++ break;
++ }
+ selmon->seltags ^= 1; /* toggle sel tagset */
+ if (arg->ui & TAGMASK)
+ selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+- focus(NULL);
++ attachclients(selmon);
+ arrange(selmon);
++ focus(NULL);
+ }
+
+ Client *
+_AT_@ -2054,7 +2170,7 @@ wintoclient(Window w)
+ Monitor *m;
+
+ for (m = mons; m; m = m->next)
+- for (c = m->clients; c; c = c->next)
++ for (c = m->cl->clients; c; c = c->next)
+ if (c->win == w)
+ return c;
+ return NULL;
+_AT_@ -2121,8 +2237,8 @@ zoom(const Arg *arg)
+ if (!selmon->lt[selmon->sellt]->arrange
+ || (selmon->sel && selmon->sel->isfloating))
+ return;
+- if (c == nexttiled(selmon->clients))
+- if (!c || !(c = nexttiled(c->next)))
++ if (c == nexttiled(selmon->cl->clients, selmon))
++ if (!c || !(c = nexttiled(c->next, selmon)))
+ return;
+ pop(c);
+ }
+--
+2.32.0
+
diff --git a/dwm.suckless.org/patches/single_tagset/index.md b/dwm.suckless.org/patches/single_tagset/index.md
index 496ecacb..8bc67af9 100644
--- a/dwm.suckless.org/patches/single_tagset/index.md
+++ b/dwm.suckless.org/patches/single_tagset/index.md
_AT_@ -18,6 +18,7 @@ Several deep changes needed to be made:
Download
--------
+* [dwm-single\_tagset-20210623-67d76bd.diff](dwm-single_tagset-20210623-67d76bd.diff)
* [dwm-single\_tagset-6.2.diff](dwm-single_tagset-6.2.diff)
* [dwm-single\_tagset-20160731-56a31dc.diff](dwm-single_tagset-20160731-56a31dc.diff)
* [dwm-6.1-single\_tagset.diff](dwm-6.1-single_tagset.diff) (16634b) (20140209)
_AT_@ -27,3 +28,4 @@ Authors
-------
* Jan Christoph Ebersbach - <jceb_AT_e-jc.de>
* Mohammad Zeinali - <mzeinali_AT_tutanota.com>
+* Jesus Mastache Caballero - <BrunoCooper17_AT_outlook.com>
Received on Wed Jun 23 2021 - 18:30:11 CEST
This archive was generated by hypermail 2.3.0
: Wed Jun 23 2021 - 18:36:43 CEST