]> git.mdlowis.com Git - proto/anvil.git/commitdiff
reworked client handling
authorMichael D. Lowis <mike@mdlowis.com>
Thu, 1 Aug 2024 02:48:24 +0000 (22:48 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Thu, 1 Aug 2024 02:48:24 +0000 (22:48 -0400)
anvil.c
atoms
atoms.c
atoms.h
client.c

diff --git a/anvil.c b/anvil.c
index 435bd6556d86438d6d0bd883e8d3ff777af74539..c976eaed186366f7230e02471f8635592f36844b 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -80,7 +80,7 @@ Client* Focused = NULL;
 static void check_for_wm(void)
 {
     error_default = XSetErrorHandler(error_init);
-    XSelectInput(X.disp, X.root, SubstructureRedirectMask);
+    XSelectInput(X.disp, X.root, SubstructureRedirectMask|SubstructureNotifyMask);
     XSync(X.disp, False);
     XSetErrorHandler(error_panic);
     XSync(X.disp, False);
@@ -162,22 +162,22 @@ static void xconfigrequest(XEvent* e)
     wc.border_width = ev->border_width;
     wc.sibling = ev->above;
     wc.stack_mode = ev->detail;
-    Location loc = {0};
-    if (mons_find(ev->window, &loc))
-    {
-        /* only allow floating clients to resize on their own */
-        if ((loc.client->win == ev->window) && !loc.column)
-        {
-            loc.client->w = wc.width + FRAME_WIDTH_SUM;
-            loc.client->h = wc.height + FRAME_HEIGHT_SUM;
-            client_adjust(loc.client);
-            if (X.mode == M_RESIZE && Focused == loc.client)
-            {
-                mouse_tocorner(loc.client);
-            }
-        }
-    }
-    else
+//    Location loc = {0};
+//    if (mons_find(ev->window, &loc))
+//    {
+//        /* only allow floating clients to resize on their own */
+//        if ((loc.client->win == ev->window) && !loc.column)
+//        {
+//            loc.client->w = wc.width + FRAME_WIDTH_SUM;
+//            loc.client->h = wc.height + FRAME_HEIGHT_SUM;
+//            client_adjust(loc.client);
+//            if (X.mode == M_RESIZE && Focused == loc.client)
+//            {
+//                mouse_tocorner(loc.client);
+//            }
+//        }
+//    }
+//    else
     {
         XConfigureWindow(X.disp, ev->window, ev->value_mask, &wc);
     }
@@ -190,7 +190,7 @@ static void xclientmsg(XEvent* e)
     printf("CLIENT_MSG(w: 0x%lx a: '%s')\n", ev->window, XGetAtomName(X.disp, ev->message_type));
     if (ev->message_type == _NET_ACTIVE_WINDOW)
     {
-        mons_activate(ev->window);
+//        mons_activate(ev->window);
     }
 }
 
@@ -198,23 +198,23 @@ static void xpropnotify(XEvent* e)
 {
     XPropertyEvent* ev = &(e->xproperty);
     printf("PROP_NOTIFY(w: 0x%lx)\n", ev->window);
-    Location loc = {0};
-    if (mons_find(ev->window, &loc))
-    {
-        client_readprops(loc.client);
-        client_draw(loc.client);
-    }
+//    Location loc = {0};
+//    if (mons_find(ev->window, &loc))
+//    {
+//        client_readprops(loc.client);
+//        client_draw(loc.client);
+//    }
 }
 
 static void xenternotify(XEvent* e)
 {
     XCrossingEvent* ev = &(e->xcrossing);
-    Location loc = {0};
+//    Location loc = {0};
     printf("ENTER(w: 0x%lx s: %d m: %d d: %d)\n", ev->window, ev->state, ev->mode, ev->detail);
-    if (mons_find(ev->window, &loc))
-    {
-        client_focus(loc.client);
-    }
+//    if (mons_find(ev->window, &loc))
+//    {
+//        client_focus(loc.client);
+//    }
 }
 
 static void xexpose(XEvent* e)
@@ -223,11 +223,11 @@ static void xexpose(XEvent* e)
     if (ev->count == 0)
     {
         printf("EXPOSE(w: 0x%lx)\n", ev->window);
-        Location loc = {0};
-        if (mons_find(ev->window, &loc))
-        {
-            client_draw(loc.client);
-        }
+//        Location loc = {0};
+//        if (mons_find(ev->window, &loc))
+//        {
+//            client_draw(loc.client);
+//        }
     }
 }
 
@@ -235,11 +235,11 @@ static void xmapnotify(XEvent* e)
 {
     XMapEvent* ev = &(e->xmap);
     printf("MAP(e: 0x%lx w: 0x%lx)\n", ev->event, ev->window);
-    Location loc = {0};
-    if (mons_find(ev->window, &loc))// && loc.client->win == ev->window)
-    {
-        client_draw(loc.client);
-    }
+//    Location loc = {0};
+//    if (mons_find(ev->window, &loc))// && loc.client->win == ev->window)
+//    {
+//        client_draw(loc.client);
+//    }
 }
 
 
diff --git a/atoms b/atoms
index 15ef57fe8947b37acb5dc64d5677095551c1e6d6..8bdfbf3369df8f6c55613670b5b5c865cd2d67ea 100644 (file)
--- a/atoms
+++ b/atoms
@@ -1,3 +1,4 @@
+WM_STATE
 WM_NAME
 WM_ICON_NAME
 WM_NORMAL_HINTS
diff --git a/atoms.c b/atoms.c
index 7df75efd15c2d26ee7c2584c588a63d84ce90161..c4cbc1fa431b0393201ec07dfca881427857e945 100644 (file)
--- a/atoms.c
+++ b/atoms.c
@@ -1,4 +1,5 @@
 #include "anvil.h"
+Atom WM_STATE;
 Atom WM_NAME;
 Atom WM_ICON_NAME;
 Atom WM_NORMAL_HINTS;
@@ -14,6 +15,7 @@ Atom _NET_WM_WINDOW_TYPE;
 Atom _NET_WM_WINDOW_TYPE_DIALOG;
 
 void atoms_init(void) {
+    WM_STATE = XInternAtom(X.disp, "WM_STATE", False);
     WM_NAME = XInternAtom(X.disp, "WM_NAME", False);
     WM_ICON_NAME = XInternAtom(X.disp, "WM_ICON_NAME", False);
     WM_NORMAL_HINTS = XInternAtom(X.disp, "WM_NORMAL_HINTS", False);
diff --git a/atoms.h b/atoms.h
index a907d6a89ca75253cc1c1124f2157bb9b35ad0bb..017f7170c865cd8623752e23d602e487772bbf0e 100644 (file)
--- a/atoms.h
+++ b/atoms.h
@@ -1,4 +1,5 @@
 
+extern Atom WM_STATE;
 extern Atom WM_NAME;
 extern Atom WM_ICON_NAME;
 extern Atom WM_NORMAL_HINTS;
index aabfef77b906f63bf1ae776eb3dfb9ed8a9e0160..6b7e8e96067be9f4a266f1337688fbbafcf4ec99 100644 (file)
--- a/client.c
+++ b/client.c
@@ -1,5 +1,37 @@
 #include "anvil.h"
 
+static Client* FindClient(Window win);
+static void ReadProps(Client* c);
+static void Redraw(Client* c);
+
+void SetWMState(Client *c, int state)
+{
+    CARD32 data[2] = {state, None};
+    XChangeProperty(X.disp, c->win, WM_STATE, WM_STATE, 32, PropModeReplace, (unsigned char *)data, 2);
+}
+
+///* If we can't find a WM_STATE we're going to have to assume
+// * Withdrawn. This is not exactly optimal, since we can't really
+// * distinguish between the case where no WM has run yet and when the
+// * state was explicitly removed (Clients are allowed to either set the
+// * atom to Withdrawn or just remove it... yuck.) */
+//
+//long GetWMState(Client *c)
+//{
+//    Atom real_type;
+//    int real_format;
+//    long state = WithdrawnState;
+//    unsigned long items_read, items_left;
+//    unsigned char *data;
+//
+//    if (XGetWindowProperty(dsply, c->window, wm_state, 0L, 2L, False, wm_state, &real_type, &real_format, &items_read, &items_left, &data) == Success && items_read)
+//    {
+//        state = *(long *)data;
+//        XFree(data);
+//    }
+//    return state;
+//}
+
 void Client_Create(Window win)
 {
     (void)win;
@@ -18,6 +50,7 @@ void Client_Create(Window win)
 
         /* Reparent the window if applicable */
         c->frame = XCreateSimpleWindow(X.disp, X.root, c->x, c->y, c->w, c->h, 1, X.clr_bdr, X.clr_bg);
+        XAddToSaveSet(X.disp, c->win);
         XSelectInput(X.disp, c->frame,
             ExposureMask | EnterWindowMask |
             ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
@@ -28,13 +61,26 @@ void Client_Create(Window win)
         wa.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask;
         XChangeWindowAttributes(X.disp, c->win, CWEventMask | CWDontPropagate, &wa);
         XReparentWindow(X.disp, c->win, c->frame, BORDER_WIDTH, MIN_HEIGHT);
+        SetWMState(c, WithdrawnState);
 
-//        /* Map the window and draw the frame */
-//        XAddToSaveSet(X.disp, c->win);
-//        client_readprops(c);
-//        mons_addclient(c);
-//        client_show(c, 1);
-//        client_draw(c);
+//        /* set the state now based on attributes and hints */
+//        if (attr.map_state == IsUnmapped)
+//        {
+//            SetWMState(c, WithdrawnState);
+//        }
+//        else
+//        {
+//            SetWMState(c, NormalState);
+//            XWMHints* hints = XGetWMHints(X.disp, c->win);
+//            if (hints)
+//            {
+//                if (hints->flags & StateHint)
+//                {
+//                    SetWMState(c, hints->initial_state);
+//                }
+//                XFree(hints);
+//            }
+//        }
     }
 }
 
@@ -45,7 +91,15 @@ void Client_Destroy(Window win)
 
 void Client_Show(Window win)
 {
-    (void)win;
+    Client* c = FindClient(win);
+    printf("%p %p\n", Withdrawn, c);
+    if (c)
+    {
+        ReadProps(c);
+        XMapWindow(X.disp, c->frame);
+        XMapWindow(X.disp, c->win);
+        Redraw(c);
+    }
 }
 
 void Client_Hide(Window win)
@@ -72,6 +126,130 @@ void Client_Hide(Window win)
 
 }
 
+static void ReadProps(Client* c)
+{
+    Atom *protos = NULL, actual_type, *wintype;
+    int format, nprotos = 0;
+    unsigned long n, extra;
+
+    /* WM_NAME - window title */
+    xfree(c->name);
+    c->name = NULL;
+    XGetWindowProperty(
+        X.disp, c->win, XA_WM_NAME, 0, -1, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **)&c->name);
+
+    /* WM_HINTS - other non-dimensional attributes of the window */
+    XWMHints* hints = XGetWMHints(X.disp, c->win);
+    if (hints)
+    {
+        int ignored = (Focused == c ? XUrgencyHint : 0);
+        c->wm_flags = (hints->flags & ~ignored);
+        c->hints = *hints;
+    }
+    xfree(hints);
+
+    /* WM_NORMAL_HINTS - desired dimensional attributes of the window */
+    XGetWMNormalHints(X.disp, c->win, &(c->size_hints), &(c->hint_flags));
+
+    /* WM_PROTOCOLS - list of client message protocols this window responds to */
+    XGetWMProtocols(X.disp, c->win, &protos, &nprotos);
+    for (int i = 0; i < nprotos; i++)
+    {
+        if (protos[i] == WM_DELETE_WINDOW)
+        {
+            c->flags |= F_WM_DELETE;
+        }
+
+        // TODO: handle WM_TAKE_FOCUS
+    }
+    xfree(protos);
+
+    /* WM_CLASS - instance and class names of the window. informs WM about behavior of window */
+    // TODO: Read the class and instance of the window
+
+    /* WM_TRANSIENT_FOR - marks the window as a pop-up for another window */
+    // TODO: read the transient_for property and use ti to handle pop-ups better
+
+    /* WM_CLIENT_MACHINE - */
+    // TODO: read client machine property
+
+    /* check if the window is a dialog */
+    XGetWindowProperty(
+        X.disp, c->win, _NET_WM_WINDOW_TYPE, 0L, -1, False, XA_ATOM, &actual_type, &format, &n, &extra, (unsigned char **)&wintype);
+    if (wintype && *wintype == _NET_WM_WINDOW_TYPE_DIALOG)
+    {
+        c->flags |= F_DIALOG|F_FLOATING;
+    }
+    xfree(wintype);
+
+    /* The following properties are unused currently */
+    /* WM_ICON_NAME - window title when iconified */
+    /* WM_COLORMAP_WINDOWS - */
+}
+
+static void Redraw(Client* c)
+{
+    if (c->frame)
+    {
+        XSetWindowBackground(X.disp, c->frame, ((c->wm_flags & XUrgencyHint) ? X.clr_urgent : X.clr_bg));
+        XSetWindowBorderWidth(X.disp, c->frame, 0);
+        XSetWindowBorderWidth(X.disp, c->win, 0);
+        XDefineCursor(X.disp, c->frame, X.csr_point);
+        XClearWindow(X.disp, c->frame);
+
+        /* set border color */
+        XSetForeground(X.disp, DefaultGC(X.disp, X.screen), BlackPixel(X.disp, X.screen));
+        XSetFillStyle(X.disp, DefaultGC(X.disp, X.screen), FillSolid);
+
+        /* draw outer border */
+        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, 0, c->w, 0);
+        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, c->h-1, c->w, c->h-1);
+        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, 0, 0, c->h);
+        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), c->w-1, 0, c->w-1, c->h);
+
+        /* draw inner border */
+        if (!(c->flags & F_SHADED))
+        {
+            int bw = BORDER_WIDTH;
+            int mh = MIN_HEIGHT;
+            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
+                bw-1, mh-1, c->w-bw, mh-1);
+            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
+                bw-1, c->h-bw, c->w-bw, c->h-bw);
+            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
+                bw-1, mh-1, bw-1, c->h-bw);
+            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
+                c->w-bw, mh-1, c->w-bw, c->h-bw);
+        }
+
+        /* draw title text */
+        if (c->name) {
+            int ascent = abs(X.font_ext->max_logical_extent.y);
+            Xutf8DrawString(X.disp, c->frame, X.font,
+                DefaultGC(X.disp, X.screen),
+                BORDER_WIDTH,
+                2 + ascent,
+                c->name, strlen(c->name));
+        }
+    }
+
+    /* tell the window to redraw itself */
+//    XClearArea(X.disp, c->win, 0, 0, 0, 0, True);
+}
+
+static Client* FindClient(Window win)
+{
+    Client* curr = Withdrawn;
+    for (; curr; curr = curr->next)
+    {
+        if (curr->win == win || curr->frame == win)
+        {
+            break;
+        }
+    }
+    return curr;
+}
+
 
 
 
@@ -111,7 +289,7 @@ Client* client_add(Window win, XWindowAttributes* attr)
     c->y = attr->y;
     c->w = attr->width + FRAME_WIDTH_SUM;
     c->h = attr->height + FRAME_HEIGHT_SUM;
-    client_readprops(c);
+    ReadProps(c);
 
     /* Reparent the window if applicable */
     c->frame = XCreateSimpleWindow(X.disp, X.root, c->x, c->y, c->w, c->h, 1, X.clr_bdr, X.clr_bg);
@@ -130,59 +308,10 @@ Client* client_add(Window win, XWindowAttributes* attr)
     XAddToSaveSet(X.disp, c->win);
     mons_addclient(c);
     client_show(c, 1);
-    client_draw(c);
+    Redraw(c);
     return c;
 }
 
-void client_draw(Client* c)
-{
-    if (c->frame)
-    {
-        XSetWindowBackground(X.disp, c->frame, ((c->wm_flags & XUrgencyHint) ? X.clr_urgent : X.clr_bg));
-        XSetWindowBorderWidth(X.disp, c->frame, 0);
-        XSetWindowBorderWidth(X.disp, c->win, 0);
-        XDefineCursor(X.disp, c->frame, X.csr_point);
-        XClearWindow(X.disp, c->frame);
-
-        /* set border color */
-        XSetForeground(X.disp, DefaultGC(X.disp, X.screen), BlackPixel(X.disp, X.screen));
-        XSetFillStyle(X.disp, DefaultGC(X.disp, X.screen), FillSolid);
-
-        /* draw outer border */
-        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, 0, c->w, 0);
-        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, c->h-1, c->w, c->h-1);
-        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), 0, 0, 0, c->h);
-        XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen), c->w-1, 0, c->w-1, c->h);
-
-        /* draw inner border */
-        if (!(c->flags & F_SHADED))
-        {
-            int bw = BORDER_WIDTH;
-            int mh = MIN_HEIGHT;
-            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
-                bw-1, mh-1, c->w-bw, mh-1);
-            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
-                bw-1, c->h-bw, c->w-bw, c->h-bw);
-            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
-                bw-1, mh-1, bw-1, c->h-bw);
-            XDrawLine(X.disp, c->frame, DefaultGC(X.disp, X.screen),
-                c->w-bw, mh-1, c->w-bw, c->h-bw);
-        }
-
-        /* draw title text */
-        if (c->name) {
-            int ascent = abs(X.font_ext->max_logical_extent.y);
-            Xutf8DrawString(X.disp, c->frame, X.font,
-                DefaultGC(X.disp, X.screen),
-                BORDER_WIDTH,
-                2 + ascent,
-                c->name, strlen(c->name));
-        }
-    }
-
-    /* tell the window to redraw itself */
-//    XClearArea(X.disp, c->win, 0, 0, 0, 0, True);
-}
 
 void client_adjust(Client* c)
 {
@@ -203,7 +332,7 @@ printf("XResize(0x%lx, %d, %d)\n", c->win, c->w, c->h);
         XResizeWindow(X.disp, c->win, child_w, child_h);
     }
     mons_place(c);
-//    client_draw(c);
+//    Redraw(c);
 }
 
 void client_move(Client* c, int xdiff, int ydiff)
@@ -237,10 +366,10 @@ void client_focus(Client* c)
     Client* prev = Focused;
     Focused = c;
     XSetInputFocus(X.disp, c->win, RevertToPointerRoot, CurrentTime);
-    client_draw(Focused);
+    Redraw(Focused);
     if (prev)
     {
-        client_draw(prev);
+        Redraw(prev);
     }
 }
 
@@ -251,66 +380,6 @@ void client_show(Client* c, int show)
     mapfn(X.disp, c->win);
 }
 
-void client_readprops(Client* c)
-{
-    Atom *protos = NULL, actual_type, *wintype;
-    int format, nprotos = 0;
-    unsigned long n, extra;
-
-    /* WM_NAME - window title */
-    xfree(c->name);
-    c->name = NULL;
-    XGetWindowProperty(
-        X.disp, c->win, XA_WM_NAME, 0, -1, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **)&c->name);
-
-    /* WM_HINTS - other non-dimensional attributes of the window */
-    XWMHints* hints = XGetWMHints(X.disp, c->win);
-    if (hints)
-    {
-        int ignored = (Focused == c ? XUrgencyHint : 0);
-        c->wm_flags = (hints->flags & ~ignored);
-        c->hints = *hints;
-    }
-    xfree(hints);
-
-    /* WM_NORMAL_HINTS - desired dimensional attributes of the window */
-    XGetWMNormalHints(X.disp, c->win, &(c->size_hints), &(c->hint_flags));
-
-    /* WM_PROTOCOLS - list of client message protocols this window responds to */
-    XGetWMProtocols(X.disp, c->win, &protos, &nprotos);
-    for (int i = 0; i < nprotos; i++)
-    {
-        if (protos[i] == WM_DELETE_WINDOW)
-        {
-            c->flags |= F_WM_DELETE;
-        }
-
-        // TODO: handle WM_TAKE_FOCUS
-    }
-    xfree(protos);
-
-    /* WM_CLASS - instance and class names of the window. informs WM about behavior of window */
-    // TODO: Read the class and instance of the window
-
-    /* WM_TRANSIENT_FOR - marks the window as a pop-up for another window */
-    // TODO: read the transient_for property and use ti to handle pop-ups better
-
-    /* WM_CLIENT_MACHINE - */
-    // TODO: read client machine property
-
-    /* check if the window is a dialog */
-    XGetWindowProperty(
-        X.disp, c->win, _NET_WM_WINDOW_TYPE, 0L, -1, False, XA_ATOM, &actual_type, &format, &n, &extra, (unsigned char **)&wintype);
-    if (wintype && *wintype == _NET_WM_WINDOW_TYPE_DIALOG)
-    {
-        c->flags |= F_DIALOG|F_FLOATING;
-    }
-    xfree(wintype);
-
-    /* The following properties are unused currently */
-    /* WM_ICON_NAME - window title when iconified */
-    /* WM_COLORMAP_WINDOWS - */
-}
 
 void client_shade(Client* c)
 {