/* initialize all the things */
Atoms_Init();
+ EWMH_Init();
InitCursors();
InitFont();
Client_InitAll();
#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)
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;
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
WM_COLORMAP_WINDOWS
WM_CLIENT_MACHINE
WM_DELETE_WINDOW
+_NET_WM_NAME
_NET_ACTIVE_WINDOW
_NET_WM_WINDOW_TYPE
_NET_WM_WINDOW_TYPE_DESKTOP
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;
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);
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;
#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);
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;
/* 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;
}
if (Focused == c)
{
Focused = NULL;
+ EWMH_SetActiveWindow(None);
}
AllClients = ListDelete(AllClients, c);
xfree(c->name);
{
Client* prev = Focused;
Focused = client;
+ EWMH_SetActiveWindow(Focused->win);
XSetInputFocus(X.disp, client->win, RevertToPointerRoot, CurrentTime);
Redraw(client);
if (prev)
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);
// 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)
--- /dev/null
+#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;
+}
#include "anvil.h"
-int GetActiveMonitor(void)
+int Monitors_GetActiveMonitor(void)
{
int monitor = 0;
Mouse_GetLocation(&PtrX, &PtrY);
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)