summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBossCode45 <human.cyborg42@gmail.com>2022-08-19 22:33:25 +1200
committerBossCode45 <human.cyborg42@gmail.com>2022-08-19 22:33:25 +1200
commit4895e9d1fa3fd4c51dfdf3e3fdac13a13cf10bd7 (patch)
tree1322197292b9aac0ecc292e8321ddc839a5e0122
parentc15c2df9b2512c7cfeb0eaa8301b12b96cb8c590 (diff)
downloadYATwm-4895e9d1fa3fd4c51dfdf3e3fdac13a13cf10bd7.tar.gz
YATwm-4895e9d1fa3fd4c51dfdf3e3fdac13a13cf10bd7.zip
Initial commit
-rw-r--r--.gitignore3
-rw-r--r--config.h15
-rw-r--r--main.cpp272
-rw-r--r--makefile18
-rw-r--r--run11
-rw-r--r--structs.h33
6 files changed, 352 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 259148f..40d73b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,3 +30,6 @@
*.exe
*.out
*.app
+
+# The executable on linux
+YATwm
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..18d0a93
--- /dev/null
+++ b/config.h
@@ -0,0 +1,15 @@
+#include <X11/keysym.h>
+
+struct Key
+{
+ KeySym keysym;
+ unsigned int modifiers;
+};
+
+Key keyBinds[] = {
+ {XK_E, Mod1Mask},
+ {XK_Return, Mod1Mask},
+ {XK_D, Mod1Mask},
+ {XK_T, Mod1Mask}
+};
+
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..0d33cd6
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,272 @@
+#include <X11/Xlib.h>
+
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <vector>
+
+#include "structs.h"
+#include "config.h"
+
+using std::cout;
+using std::map;
+using std::pair;
+using std::vector;
+
+Display* dpy;
+Window root;
+int sW, sH;
+TileDir nextDir = horizontal;
+
+
+bool keepGoing = true;
+
+map<int, Client> clients;
+int currClientID = 0;
+map<int, Frame> frames;
+int currFrameID = 0;
+map<Window, int> frameIDS;
+
+void keyPress(XKeyEvent e);
+void configureRequest(XConfigureRequestEvent e);
+void mapRequest(XMapRequestEvent e);
+void destroyNotify(XDestroyWindowEvent e);
+
+static int OnXError(Display* display, XErrorEvent* e);
+
+void tile(int frameID, int x, int y, int w, int h);
+
+void keyPress(XKeyEvent e)
+{
+ if(e.same_screen!=1) return;
+ //TODO: Make this into a for loop
+ switch(XLookupKeysym(&e, 1))
+ {
+ case XK_E: keepGoing = false; break;
+ case XK_Return: std::system("alacritty &"); break;
+ case XK_D: std::system("rofi -i -show drun &"); break;
+ case XK_T: nextDir = (nextDir==horizontal)? vertical : horizontal; break;
+ }
+}
+
+void configureRequest(XConfigureRequestEvent e)
+{
+ XWindowChanges changes;
+ changes.x = e.x;
+ changes.y = e.y;
+ changes.width = e.width;
+ changes.height = e.height;
+ changes.border_width = e.border_width;
+ changes.sibling = e.above;
+ changes.stack_mode = e.detail;
+ XConfigureWindow(dpy, e.window, e.value_mask, &changes);
+}
+
+void mapRequest(XMapRequestEvent e)
+{
+ XMapWindow(dpy, e.window);
+ Window focusedWindow;
+ int revertToReturn;
+ XGetInputFocus(dpy, &focusedWindow, &revertToReturn);
+ XSetInputFocus(dpy, e.window, RevertToNone, CurrentTime);
+ XSelectInput(dpy, e.window, EnterWindowMask);
+
+ //Make client
+ Client c = {currClientID, e.window};
+ currClientID++;
+
+ //Add to clients map
+ clients.insert(pair<int, Client>(c.ID, c));
+
+ //Make frame
+ int pID = (frameIDS.count(focusedWindow)>0)? frames.find(frameIDS.find(focusedWindow)->second)->second.pID : 0;
+ vector<int> v;
+ Frame f = {currFrameID, pID, true, c.ID, noDir, v};
+ currFrameID++;
+
+
+ //Add ID to frameIDS map
+ frameIDS.insert(pair<Window, int>(e.window, f.ID));
+
+ //Check how to add
+ if(nextDir == frames.find(pID)->second.dir)
+ {
+ //Add to focused parent
+ frames.find(pID)->second.subFrameIDs.push_back(f.ID);
+ }
+ else
+ {
+ //Get parent sub frames for later use
+ vector<int>& pS = frames.find(pID)->second.subFrameIDs;
+
+ //Get index of focused frame in parent sub frames
+ int index;
+ for(index = 0; index < pS.size(); index++)
+ {
+ if(pS[index] == frames.find(frameIDS.find(focusedWindow)->second)->second.ID)
+ break;
+ }
+
+ //Make new frame
+ vector<int> v;
+ v.push_back(frames.find(frameIDS.find(focusedWindow)->second)->second.ID);
+ v.push_back(f.ID);
+ Frame pF = {currFrameID, pID, false, noID, nextDir, v};
+
+ //Update the IDS
+ f.pID = currFrameID;
+ frames.find(frames.find(frameIDS.find(focusedWindow)->second)->second.ID)->second.pID = currFrameID;
+ pS[index] = currFrameID;
+
+ currFrameID++;
+
+ //Insert the new frame into the frames map
+ frames.insert(pair<int, Frame>(pF.ID, pF));
+ }
+
+ //Add to frames map
+ frames.insert(pair<int, Frame>(f.ID, f));
+
+ tile(0, 0, 0, sW, sH);
+}
+
+void destroyNotify(XDestroyWindowEvent e)
+{
+ if(frameIDS.count(e.window)<1)
+ return;
+ cout << "Destroy notif\n";
+ int fID = frameIDS.find(e.window)->second;
+ int pID = frames.find(fID)->second.pID;
+ vector<int>& pS = frames.find(pID)->second.subFrameIDs;
+ for(int i = 0; i < pS.size(); i++)
+ {
+ if(frames.find(pS[i])->second.ID == fID)
+ {
+ pS.erase(pS.begin() + i);
+ clients.erase(frames.find(fID)->second.cID);
+ frames.erase(fID);
+ frameIDS.erase(e.window);
+
+ if(pS.size() < 2 && pID != 0)
+ {
+ //Erase parent frame
+ int lastChildID = frames.find(frames.find(pID)->second.subFrameIDs[0])->second.ID;
+ int parentParentID = frames.find(pID)->second.pID;
+ vector<int>& parentParentSubFrameIDs = frames.find(parentParentID)->second.subFrameIDs;
+ for(int j = 0; j < parentParentSubFrameIDs.size(); j++)
+ {
+ if(parentParentSubFrameIDs[j] == pID)
+ {
+ parentParentSubFrameIDs[j] = lastChildID;
+ frames.find(lastChildID)->second.pID = parentParentID;
+ frames.erase(pID);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+ tile(0, 0, 0, sW, sH);
+}
+
+static int OnXError(Display* display, XErrorEvent* e)
+{
+ cout << "XError\n";
+ return 0;
+}
+
+void tile(int frameID, int x, int y, int w, int h)
+{
+ if(frameID == 0)
+ {
+ printf("\nTILING ROOT:\n");
+ }
+ printf("Tiling frame - ID: %i\n\tx: %i, y: %i, w: %i, h: %i\n", frameID, x, y, w, h);
+ int i = 0;
+ vector<int>& subFrameIDs = frames.find(frameID)->second.subFrameIDs;
+ TileDir dir = frames.find(frameID)->second.dir;
+ for(int fID : subFrameIDs)
+ {
+ Frame f = frames.find(fID)->second;
+ int wX = (dir==horizontal) ? x + i * (w/subFrameIDs.size()) : x;
+ int wY = (dir==vertical) ? y + i * (h/subFrameIDs.size()) : y;
+ int wW = (dir==horizontal) ? w/subFrameIDs.size() : w;
+ int wH = (dir==vertical) ? h/subFrameIDs.size() : h;
+ i++;
+ if(!f.isClient)
+ {
+ tile(fID, wX, wY, wW, wH);
+ continue;
+ }
+ Client c = clients.find(f.cID)->second;
+ printf("Arranging client with frame ID %i, client ID %i:\n\tx: %i, y: %i, w: %i, h: %i\n", fID, c.ID, wX, wY, wW, wH);
+ XMoveWindow(dpy, c.w,
+ wX, wY);
+ XResizeWindow(dpy, c.w,
+ wW, wH);
+ }
+ if(frameID == 0)
+ {
+ printf("DONE TILING ROOT\n\n");
+ }
+}
+
+int main(int argc, char** argv)
+{
+ dpy = XOpenDisplay(nullptr);
+ root = Window(DefaultRootWindow(dpy));
+
+ int screenNum = DefaultScreen(dpy);
+ sW = DisplayWidth(dpy, screenNum);
+ sH = DisplayHeight(dpy, screenNum);
+
+ XSetErrorHandler(OnXError);
+ XSelectInput(dpy, root, SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask);
+
+ for(int i = 0; i < sizeof(keyBinds)/sizeof(keyBinds[0]); i++)
+ {
+ XGrabKey(dpy, XKeysymToKeycode(dpy, keyBinds[i].keysym), keyBinds[i].modifiers, root, false, GrabModeAsync, GrabModeAsync);
+ }
+
+
+ vector<int> v;
+ Frame rootFrame = {0, noID, false, noID, horizontal, v};
+ currFrameID++;
+ frames.insert(pair<int, Frame>(0, rootFrame));
+
+ cout << "Begin mainloop\n";
+
+ while(keepGoing)
+ {
+ XEvent e;
+ XNextEvent(dpy, &e);
+
+ switch(e.type)
+ {
+ case KeyPress:
+ keyPress(e.xkey);
+ break;
+ case ConfigureRequest:
+ configureRequest(e.xconfigurerequest);
+ break;
+ case MapRequest:
+ mapRequest(e.xmaprequest);
+ break;
+ case DestroyNotify:
+ destroyNotify(e.xdestroywindow);
+ case EnterNotify:
+ //cout << e.xcrossing.window << "\n";
+ if(e.xcrossing.window == 1326)
+ break;
+ XSetInputFocus(dpy, e.xcrossing.window, RevertToNone, CurrentTime);
+
+ break;
+ default:
+ //cout << "Unhandled event, code: " << e.type << "!\n";
+ break;
+ }
+ }
+
+ XCloseDisplay(dpy);
+}
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..ee98188
--- /dev/null
+++ b/makefile
@@ -0,0 +1,18 @@
+CXXFLAGS := -g `pkg-config --cflags x11`
+LDFLAGS := `pkg-config --libs x11`
+
+all: YATwm
+
+HEADERS = \
+ config.h \
+ structs.h
+SOURCES = \
+ main.cpp
+OBJECTS = $(SOURCES:.cpp=.o)
+
+newwm: $(HEADERS) $(OBJECTS)
+ $(CXX) -o $@ $(OBJECTS) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+ rm -f YATwm $(OBJECTS)
diff --git a/run b/run
new file mode 100644
index 0000000..5427e8e
--- /dev/null
+++ b/run
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+make
+
+Xephyr :100 -screen 1600x900 &
+
+sleep 0.1
+
+DISPLAY=:100 ./YATwm
+
+pkill Xephyr
diff --git a/structs.h b/structs.h
new file mode 100644
index 0000000..f4287bb
--- /dev/null
+++ b/structs.h
@@ -0,0 +1,33 @@
+#include <X11/Xlib.h>
+
+#include <vector>
+
+int noID = -1;
+
+struct Client
+{
+ int ID;
+ Window w;
+};
+
+enum TileDir
+{
+ horizontal,
+ vertical,
+ noDir
+};
+
+struct Frame
+{
+ int ID;
+ int pID;
+
+ bool isClient;
+
+ //If its a client (window)
+ int cID;
+
+ //If it isn't a client
+ TileDir dir;
+ std::vector<int> subFrameIDs;
+};