]> git.mdlowis.com Git - proto/anvil.git/commitdiff
added ewmh.c file and added some handling of those hints
authorMike Lowis <mike.lowis@gentex.com>
Fri, 9 Aug 2024 20:13:00 +0000 (16:13 -0400)
committerMike Lowis <mike.lowis@gentex.com>
Fri, 9 Aug 2024 20:13:00 +0000 (16:13 -0400)
anvil.c
anvil.h
atoms
atoms.c
atoms.h
client.c
ewmh.c [new file with mode: 0644]
monitors.c

diff --git a/anvil.c b/anvil.c
index f3653de0b4a9e6b42e165007fec5c7a5e4f83bcd..6f11a302480cc976e925eae2feb4d94f5efda2b1 100644 (file)
--- a/anvil.c
+++ b/anvil.c
@@ -318,6 +318,7 @@ int main(void)
 
     /* initialize all the things */
     Atoms_Init();
+    EWMH_Init();
     InitCursors();
     InitFont();
     Client_InitAll();
diff --git a/anvil.h b/anvil.h
index d417cb36fe73ce825c9b761a4a827ef6f9ceecb4..71e3f0855c4df438f708ebfe7127968da630ff01 100644 (file)
--- a/anvil.h
+++ b/anvil.h
@@ -19,6 +19,7 @@
 
 #define min(a,b) (a < b ? a : b)
 #define max(a,b) (a > b ? a : b)
+#define nelem(a) (sizeof(a)/sizeof(a[0]))
 
 #define BORDER_WIDTH      5
 #define TITLE_HEIGHT      (X.font_ext->max_logical_extent.height)
@@ -96,6 +97,9 @@ typedef struct Client {
     struct Client* col_prev;
     char* name;
     Window frame, win, transient_for;
+    int wm_types;
+    int wm_state;
+
     int state, flags, wspace, x, y, w, h, rel_x, rel_y;
     long hint_flags, wm_flags;
     XWMHints hints;
@@ -176,5 +180,18 @@ void Mouse_GetLocation(int* ptrx, int* ptry);
 void Monitors_Init(void);
 void Monitors_SetWorkspace(int id);
 void Monitors_SendToWorkspace(Client* c, int id);
+int Monitors_GetActiveMonitor(void);
+
+/* ewmh.c */
+void EWMH_Init(void);
+void EWMH_SetClientList(void);
+void EWMH_SetActiveWindow(Window w);
+char* EWMH_GetName(Window w);
+int EWMH_GetWindowTypeFlags(Window w);
+int EWMH_GetWindowStateFlags(Window w);
+void EWMH_SetWindowStateFlags(Window w, int flags);
+//void EWMH_GetWindowStrut(Strut* strut);
+int EWMH_GetWindowPid(Window w);
+void EWMH_SetWindowFrameExtents(Window w, int left, int right, int top, int bottom);
 
 #endif
diff --git a/atoms b/atoms
index bddebae706bf0f0596f1c0b45b4acdb59bc1b36d..3db2a50df88d39270b3a77456dd305a6c7545e5b 100644 (file)
--- a/atoms
+++ b/atoms
@@ -9,6 +9,7 @@ WM_PROTOCOLS
 WM_COLORMAP_WINDOWS
 WM_CLIENT_MACHINE
 WM_DELETE_WINDOW
+_NET_WM_NAME
 _NET_ACTIVE_WINDOW
 _NET_WM_WINDOW_TYPE
 _NET_WM_WINDOW_TYPE_DESKTOP
diff --git a/atoms.c b/atoms.c
index 7f9a684636a85c3fbf19dd99bae0b6e2a27bd7cb..2e9e98f3fd6e75e0b4e16be91d6bc2cbed1a3780 100644 (file)
--- a/atoms.c
+++ b/atoms.c
@@ -10,6 +10,7 @@ Atom WM_PROTOCOLS;
 Atom WM_COLORMAP_WINDOWS;
 Atom WM_CLIENT_MACHINE;
 Atom WM_DELETE_WINDOW;
+Atom _NET_WM_NAME;
 Atom _NET_ACTIVE_WINDOW;
 Atom _NET_WM_WINDOW_TYPE;
 Atom _NET_WM_WINDOW_TYPE_DESKTOP;
@@ -46,6 +47,7 @@ void Atoms_Init(void) {
     WM_COLORMAP_WINDOWS = XInternAtom(X.disp, "WM_COLORMAP_WINDOWS", False);
     WM_CLIENT_MACHINE = XInternAtom(X.disp, "WM_CLIENT_MACHINE", False);
     WM_DELETE_WINDOW = XInternAtom(X.disp, "WM_DELETE_WINDOW", False);
+    _NET_WM_NAME = XInternAtom(X.disp, "_NET_WM_NAME", False);
     _NET_ACTIVE_WINDOW = XInternAtom(X.disp, "_NET_ACTIVE_WINDOW", False);
     _NET_WM_WINDOW_TYPE = XInternAtom(X.disp, "_NET_WM_WINDOW_TYPE", False);
     _NET_WM_WINDOW_TYPE_DESKTOP = XInternAtom(X.disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
diff --git a/atoms.h b/atoms.h
index e71cdf52de7f36eabb59606d004498a02647c652..bf83d0b69de1f47521c211856896ec217d1a9838 100644 (file)
--- a/atoms.h
+++ b/atoms.h
@@ -10,6 +10,7 @@ extern Atom WM_PROTOCOLS;
 extern Atom WM_COLORMAP_WINDOWS;
 extern Atom WM_CLIENT_MACHINE;
 extern Atom WM_DELETE_WINDOW;
+extern Atom _NET_WM_NAME;
 extern Atom _NET_ACTIVE_WINDOW;
 extern Atom _NET_WM_WINDOW_TYPE;
 extern Atom _NET_WM_WINDOW_TYPE_DESKTOP;
index 539ceb71607a22633bb3d4d48eddd4c28e8f3ad6..58bf2299164b09bfb876f5e75e081689cc086177 100644 (file)
--- a/client.c
+++ b/client.c
@@ -5,8 +5,6 @@
 #define LIST_FOR_EACH(val,list) \
     for (val = list; (val != NULL); val = val->next)
 
-static void ReadWindowTypes(Client* c);
-static void ReadWindowState(Client* c);
 static void ReadProps(Client* c);
 static void Redraw(Client* c);
 static void LayerWindows(void);
@@ -17,38 +15,6 @@ static void SendMessage(Window win, Atom proto, Atom type);
 static void SetWMState(Client *c, int state);
 static void* ListDelete(void* list, void* node);
 
-typedef struct {
-    Atom* atom;
-    int flags;
-} AtomMap;
-
-static AtomMap WindowTypes[] = {
-    { .atom = &_NET_WM_WINDOW_TYPE,         .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_DESKTOP, .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_DOCK,    .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_TOOLBAR, .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_MENU,    .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_UTILITY, .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_SPLASH,  .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_DIALOG,  .flags = 0 },
-    { .atom = &_NET_WM_WINDOW_TYPE_NORMAL,  .flags = 0 },
-};
-
-static AtomMap WindowStates[] = {
-    { .atom = &_NET_WM_STATE_MODAL,             .flags = 0 },
-    { .atom = &_NET_WM_STATE_STICKY,            .flags = 0 },
-    { .atom = &_NET_WM_STATE_MAXIMIZED_VERT,    .flags = 0 },
-    { .atom = &_NET_WM_STATE_MAXIMIZED_HORZ,    .flags = 0 },
-    { .atom = &_NET_WM_STATE_SHADED,            .flags = 0 },
-    { .atom = &_NET_WM_STATE_SKIP_TASKBAR,      .flags = 0 },
-    { .atom = &_NET_WM_STATE_SKIP_PAGER,        .flags = 0 },
-    { .atom = &_NET_WM_STATE_HIDDEN,            .flags = 0 },
-    { .atom = &_NET_WM_STATE_FULLSCREEN,        .flags = 0 },
-    { .atom = &_NET_WM_STATE_ABOVE,             .flags = 0 },
-    { .atom = &_NET_WM_STATE_BELOW,             .flags = 0 },
-    { .atom = &_NET_WM_STATE_DEMANDS_ATTENTION, .flags = 0 },
-};
-
 Client* Client_Find(Window win)
 {
     Client* curr = AllClients;
@@ -124,6 +90,11 @@ void Client_Show(Client* c)
     /* set mouse to titlebar if mapping for first time */
     if (!(c->wm_flags & F_MAPPED_ONCE))
     {
+        int mon = Monitors_GetActiveMonitor();
+        c->wspace = Monitors[mon].wspace;
+        c->x = Monitors[mon].midx - c->w/2;
+        c->y = Monitors[mon].midy - c->h/2;
+        Client_MoveResize(c);
         Mouse_ToTitle(c);
         c->wm_flags |= F_MAPPED_ONCE;
     }
@@ -148,6 +119,7 @@ void Client_Destroy(Client* c)
     if (Focused == c)
     {
         Focused = NULL;
+        EWMH_SetActiveWindow(None);
     }
     AllClients = ListDelete(AllClients, c);
     xfree(c->name);
@@ -214,6 +186,7 @@ void Client_Focus(Client* client)
 {
     Client* prev = Focused;
     Focused = client;
+    EWMH_SetActiveWindow(Focused->win);
     XSetInputFocus(X.disp, client->win, RevertToPointerRoot, CurrentTime);
     Redraw(client);
     if (prev)
@@ -327,15 +300,12 @@ void Client_UpdateAll(void)
 
 static void ReadProps(Client* c)
 {
-    Atom actual_type, *protos = NULL;
-    int format, nprotos = 0;
-    unsigned long n, extra;
+    Atom *protos = NULL;
+    int nprotos = 0;
 
     /* 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);
+    c->name = EWMH_GetName(c->win);
 
     /* WM_HINTS - other non-dimensional attributes of the window */
     XWMHints* hints = XGetWMHints(X.disp, c->win);
@@ -374,86 +344,18 @@ static void ReadProps(Client* c)
     // TODO: read client machine property
 
     /* check if the window is a dialog */
-    ReadWindowTypes(c);
+    c->wm_types = EWMH_GetWindowTypeFlags(c->win);
+    c->wm_state = EWMH_GetWindowStateFlags(c->win);
 
-    ReadWindowState(c);
+//    ReadWindowTypes(c);
+//
+//    ReadWindowState(c);
 
     /* The following properties are unused currently */
     /* WM_ICON_NAME - window title when iconified */
     /* WM_COLORMAP_WINDOWS - */
 }
 
-static void ReadFlagHint(Client* c, Atom hint, AtomMap* known, unsigned long nknown, int* flags)
-{
-    Atom actual_type, *atoms;
-    int format;
-    unsigned long natoms, extra;
-
-    XGetWindowProperty(
-        X.disp, c->win, hint, 0L, -1, False, XA_ATOM, &actual_type, &format, &natoms, &extra, (unsigned char **)&atoms);
-
-    for (unsigned long i = 0; i < natoms; i++)
-    {
-        for (unsigned long x = 0; x < nknown; x++)
-        {
-            if (*known[x].atom == atoms[i])
-            {
-                *flags |= known[x].flags;
-            }
-        }
-    }
-    xfree(atoms);
-}
-
-static void ReadWindowTypes(Client* c)
-{
-    ReadFlagHint(c, _NET_WM_WINDOW_TYPE, WindowTypes, sizeof(WindowTypes)/sizeof(WindowTypes[0]), &(c->flags));
-
-//    for (unsigned long i = 0; i < ntypes; i++)
-//    {
-//        if (types[i] == _NET_WM_WINDOW_TYPE_DIALOG)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_DESKTOP)
-//        {
-//            c->flags |= F_FLOATING|F_NO_FRAME;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_DOCK)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING|F_NO_FRAME;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_TOOLBAR)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_MENU)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING|F_NO_FRAME;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_UTILITY)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_SPLASH)
-//        {
-//            c->flags |= F_DIALOG|F_FLOATING|F_NO_FRAME;
-//        }
-//        if (types[i] == _NET_WM_WINDOW_TYPE_NORMAL)
-//        {
-//            c->flags |= 0;
-//        }
-//    }
-//    xfree(atoms);
-}
-
-static void ReadWindowState(Client* c)
-{
-    ReadFlagHint(c, _NET_WM_STATE, WindowStates, sizeof(WindowStates)/sizeof(WindowStates[0]), &(c->flags));
-
-}
-
-
 static void Redraw(Client* c)
 {
     if (c->frame)
diff --git a/ewmh.c b/ewmh.c
new file mode 100644 (file)
index 0000000..acd4bad
--- /dev/null
+++ b/ewmh.c
@@ -0,0 +1,201 @@
+#include "anvil.h"
+
+//DWM supports only these:
+//    NetSupported,
+//    NetWMName,
+//    NetWMState,
+//    NetWMCheck,
+//    NetWMFullscreen,
+//    NetActiveWindow,
+//    NetWMWindowType,
+//    NetWMWindowTypeDialog,
+//    NetClientList,
+
+static Atom* WindowTypes[] = {
+    &_NET_WM_WINDOW_TYPE,
+    &_NET_WM_WINDOW_TYPE_DESKTOP,
+    &_NET_WM_WINDOW_TYPE_DOCK,
+    &_NET_WM_WINDOW_TYPE_TOOLBAR,
+    &_NET_WM_WINDOW_TYPE_MENU,
+    &_NET_WM_WINDOW_TYPE_UTILITY,
+    &_NET_WM_WINDOW_TYPE_SPLASH,
+    &_NET_WM_WINDOW_TYPE_DIALOG,
+    &_NET_WM_WINDOW_TYPE_NORMAL,
+};
+
+static Atom* WindowStates[] = {
+    &_NET_WM_STATE_MODAL,
+    &_NET_WM_STATE_STICKY,
+    &_NET_WM_STATE_MAXIMIZED_VERT,
+    &_NET_WM_STATE_MAXIMIZED_HORZ,
+    &_NET_WM_STATE_SHADED,
+    &_NET_WM_STATE_SKIP_TASKBAR,
+    &_NET_WM_STATE_SKIP_PAGER,
+    &_NET_WM_STATE_HIDDEN,
+    &_NET_WM_STATE_FULLSCREEN,
+    &_NET_WM_STATE_ABOVE,
+    &_NET_WM_STATE_BELOW,
+    &_NET_WM_STATE_DEMANDS_ATTENTION,
+};
+
+static void ReplaceProp(Window w, Atom prop, Atom type, void* elems, int nelems, int format)
+{
+    XChangeProperty(
+        X.disp,
+        w,
+        prop,
+        type,
+        format,
+        PropModeReplace,
+        (unsigned char *) elems,
+        nelems);
+}
+
+static int ReadFlagHint(Window w, Atom hint, Atom** known, unsigned long nknown)
+{
+    Atom actual_type, *atoms;
+    int format, flags = 0;
+    unsigned long natoms, extra;
+
+    XGetWindowProperty(
+        X.disp, w, hint, 0L, -1, False, XA_ATOM, &actual_type, &format, &natoms, &extra, (unsigned char **)&atoms);
+
+    for (unsigned long i = 0; i < natoms; i++)
+    {
+        for (unsigned long x = 0; x < nknown; x++)
+        {
+            if (*known[x] == atoms[i])
+            {
+                flags |= (1 << x);
+            }
+        }
+    }
+    if (atoms)
+    {
+        XFree(atoms);
+    }
+    return flags;
+}
+
+
+static void WriteFlagHint(Window w, Atom hint, Atom** known, unsigned long nknown, int flags)
+{
+    Atom* to_write = calloc(sizeof(Atom), nknown);
+    int n_to_write = 0;
+    if (to_write)
+    {
+        for (unsigned long i = 0; i < nknown; i++)
+        {
+            if (flags & (1 << i))
+            {
+                to_write[n_to_write++] = *known[i];
+            }
+        }
+        ReplaceProp(w, hint, XA_ATOM, to_write, n_to_write, 32);
+        free(to_write);
+    }
+}
+
+/*
+    We might not use these properties?
+
+    _NET_VIRTUAL_ROOTS
+    _NET_DESKTOP_LAYOUT
+    _NET_SHOWING_DESKTOP
+*/
+
+/*
+    Client messages to root we may need to listen for
+
+    _NET_WM_STATE
+
+*/
+
+/*
+    Protocols we do not intend to support...
+
+    _NET_WM_PING
+    _NET_WM_SYNC_REQUEST
+*/
+
+
+void EWMH_Init(void)
+{
+    // Write _NET_SUPPORTED - array of all hints we support...
+    // Write _NET_NUMBER_OF_DESKTOPS - total number of workspaces (10)
+    // Write _NET_DESKTOP_NAMES - names of workspaces...
+    // Write _NET_DESKTOP_VIEWPORT - always 0,0. write it here
+
+    // _NET_SUPPORTING_WM_CHECK
+        // Set this to the id of a window we create and own
+        // Set _NET_WM_NAME on said window to name of WM
+        // Tells clients we are alive and kicking...
+}
+
+void EWMH_SetClientList(void)
+{
+    // Write _NET_CLIENT_LIST - initial mapping order
+    // Write _NET_CLIENT_LIST_Stacking - bottom-to-top order
+}
+
+void EWMH_SetActiveWindow(Window w)
+{
+    // Write _NET_ACTIVE_WINDOW
+    ReplaceProp(X.root, _NET_ACTIVE_WINDOW, XA_WINDOW, &w, 1, 32);
+}
+
+char* EWMH_GetName(Window w)
+{
+    // Read _NET_WM_NAME
+    // else read WM_NAME
+
+    Atom actual_type;
+    int format;
+    unsigned long n, extra;
+    char* name = NULL;
+    XGetWindowProperty(
+        X.disp, w, _NET_WM_NAME, 0, -1, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **)&name);
+    if (!name)
+    {
+        XGetWindowProperty(
+            X.disp, w, XA_WM_NAME, 0, -1, False, AnyPropertyType, &actual_type, &format, &n, &extra, (unsigned char **)&name);
+    }
+    return name;
+}
+
+int EWMH_GetWindowTypeFlags(Window w)
+{
+    // Read _NET_WM_WINDOW_TYPE
+    return ReadFlagHint(w, _NET_WM_WINDOW_TYPE, WindowTypes, nelem(WindowTypes));
+}
+
+int EWMH_GetWindowStateFlags(Window w)
+{
+    // Read _NET_WM_STATE
+    return ReadFlagHint(w, _NET_WM_STATE, WindowStates, nelem(WindowStates));
+}
+
+void EWMH_SetWindowStateFlags(Window w, int flags)
+{
+    // Write _NET_WM_STATE
+    WriteFlagHint(w, _NET_WM_STATE, WindowStates, nelem(WindowStates), flags);
+}
+
+//void EWMH_GetWindowStrut(Strut* strut)
+//{
+//    // Read _NET_WM_STRUT_PARTIAL
+//    // Else read _NET_WM_STRUT
+//}
+
+int EWMH_GetWindowPid(Window w)
+{
+    // Read _NET_WM_PID
+    (void)w;
+    return 0;
+}
+
+void EWMH_SetWindowFrameExtents(Window w, int left, int right, int top, int bottom)
+{
+    // Write _NET_FRAME_EXTENTS
+    (void)w, (void)left, (void)right, (void)top, (void)bottom;
+}
index 478b1366cd7a4a8ff3b2ea9d08e55bad9d5bc5b7..4bdda8da65af320f237e1de210b4207f5155c772 100644 (file)
@@ -1,6 +1,6 @@
 #include "anvil.h"
 
-int GetActiveMonitor(void)
+int Monitors_GetActiveMonitor(void)
 {
     int monitor = 0;
     Mouse_GetLocation(&PtrX, &PtrY);
@@ -59,7 +59,7 @@ void Monitors_SetWorkspace(int ws_id)
     printf("WORKSPACE %d\n", ws_id);
 
     XGrabServer(X.disp);
-    int mon_id = GetActiveMonitor();
+    int mon_id = Monitors_GetActiveMonitor();
     int other_mon_id = Workspaces[ws_id].monitor;
     printf("MONITORS %d %d\n", mon_id, other_mon_id);
     if (mon_id != other_mon_id)