summaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp1159
1 files changed, 0 insertions, 1159 deletions
diff --git a/main.cpp b/main.cpp
deleted file mode 100644
index 1f3edc2..0000000
--- a/main.cpp
+++ /dev/null
@@ -1,1159 +0,0 @@
-#include <X11/X.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#include <X11/cursorfont.h>
-#include <X11/Xutil.h>
-#include <X11/extensions/Xrandr.h>
-
-#include <libnotify/notification.h>
-#include <libnotify/notify.h>
-
-#include <chrono>
-#include <cstdio>
-#include <cstdlib>
-#include <ctime>
-#include <fstream>
-#include <ios>
-#include <iostream>
-#include <map>
-#include <ostream>
-#include <string>
-#include <sys/poll.h>
-#include <sys/select.h>
-#include <vector>
-#include <unistd.h>
-#include <cstring>
-#include <algorithm>
-#include <fcntl.h>
-#include <poll.h>
-
-#include "IPC.h"
-#include "commands.h"
-#include "keybinds.h"
-#include "structs.h"
-#include "config.h"
-#include "util.h"
-#include "ewmh.h"
-#include "error.h"
-
-using std::cout;
-using std::string;
-using std::endl;
-using std::map;
-using std::pair;
-using std::vector;
-
-std::ofstream yatlog;
-std::time_t timeNow;
-std::tm *now;
-char nowString[80];
-
-#define log(x) \
- updateTime(); \
- yatlog << nowString << x << std::endl
-
-Display* dpy;
-Window root;
-
-Globals globals = {dpy, root};
-
-void updateMousePos();
-
-CommandsModule commandsModule;
-Config cfg(commandsModule);
-KeybindsModule keybindsModule(commandsModule, cfg, globals, &updateMousePos);
-IPCModule ipc(commandsModule, cfg, globals);
-
-int sW, sH;
-int bH;
-TileDir nextDir = horizontal;
-
-bool keepGoing = true;
-
-map<int, Client> clients;
-int currClientID = 0;
-map<int, Frame> frames;
-int currFrameID = 1;
-map<Window, int> frameIDS;
-
-ScreenInfo* screens;
-int* focusedWorkspaces;
-int focusedScreen = 0;
-int nscreens;
-int mX, mY;
-
-#define getClient(c) clients.find(c)->second
-#define getFrame(f) frames.find(f)->second
-#define getFrameID(w) frameIDS.find(w)->second
-
-Window bar;
-
-int currWS = 1;
-
-
-// Usefull functions
-int FFCF(int sID);
-void detectScreens();
-void focusRoot(int root);
-void handleConfigErrs(vector<Err> cfgErrs);
-void updateTime();
-
-void configureRequest(XConfigureRequestEvent e);
-void mapRequest(XMapRequestEvent e);
-void destroyNotify(XDestroyWindowEvent e);
-void enterNotify(XEnterWindowEvent e);
-void clientMessage(XClientMessageEvent e);
-
-static int OnXError(Display* display, XErrorEvent* e);
-
-// Tiling
-// Call this one to tile everything (it does all the fancy stuff trust me just call this one)
-void tileRoots();
-// Call this one to until everything (it handles multiple monitors)
-void untileRoots();
-// This is to be called by tileRoots, it takes in the x, y, w, and h of where it's allowed to tile windows to, and returns the ID of a fullscreen client if one is found, or noID (-1) if none are found
-int tile(int frameID, int x, int y, int w, int h);
-// This is to be called by tileRoots, it takes in a frameID and recursively unmaps all its children
-void untile(int frameID);
-
-// Usefull functions
-int FFCF(int sID)
-{
- if(frames.find(sID)->second.isClient)
- return sID;
- return FFCF(frames.find(sID)->second.subFrameIDs[0]);
-}
-void detectScreens()
-{
- delete[] screens;
- delete[] focusedWorkspaces;
- log("Detecting screens: ");
- XRRMonitorInfo* monitors = XRRGetMonitors(dpy, root, true, &nscreens);
- log("\t" << nscreens << " monitors");
- screens = new ScreenInfo[nscreens];
- focusedWorkspaces = new int[nscreens];
- for(int i = 0; i < nscreens; i++)
- {
- focusedWorkspaces[i] = i * 5 + 1;
- char* name = XGetAtomName(dpy, monitors[i].name);
- screens[i] = {name, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height};
- log("\tMonitor " << i + 1 << " - " << screens[i].name);
- log("\t\tx: " << screens[i].x << ", y: " << screens[i].y);
- log("\t\tw: " << screens[i].w << ", h: " << screens[i].h);
- XFree(name);
- }
- for(int i = 0; i < cfg.workspaces.size(); i++)
- {
- if(cfg.workspaces[i].screenPreferences[0] < nscreens && focusedWorkspaces[cfg.workspaces[i].screenPreferences[0]] == 0)
- {
- //focusedWorkspaces[screenPreferences[i][0]] = i+1;
- }
- }
- XFree(monitors);
-}
-void updateMousePos()
-{
- Window rootRet, childRet;
- int rX, rY, cX, cY;
- unsigned int maskRet;
- XQueryPointer(dpy, root, &rootRet, &childRet, &rX, &rY, &cX, &cY, &maskRet);
- mX = rX;
- mY = rY;
-}
-int getClientChild(int fID)
-{
- if(getFrame(fID).isClient)
- return fID;
- else
- return getClientChild(getFrame(fID).subFrameIDs[0]);
-}
-void focusRoot(int root)
-{
- //log("Focusing root: " << root);
- if(getFrame(root).subFrameIDs.size() == 0)
- {
- //log("\tRoot has no children");
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
- return;
- }
- int client = getFrame(getClientChild(root)).cID;
- Window w = getClient(client).w;
- //log("\tFocusing window: " << w);
- XSetInputFocus(dpy, w, RevertToPointerRoot, CurrentTime);
-}
-void handleConfigErrs(vector<Err> cfgErrs)
-{
- for(Err cfgErr : cfgErrs)
- {
- if(cfgErr.code == CFG_ERR_FATAL)
- {
- log("YATwm fatal error (Code " << cfgErr.code << ")\n" << cfgErr.message);
- std::string title = "YATwm fatal config error (Code " + std::to_string(cfgErr.code) + ")";
- std::string body = cfgErr.message;
- NotifyNotification* n = notify_notification_new(title.c_str(),
- body.c_str(),
- 0);
- notify_notification_set_timeout(n, 10000);
- if(!notify_notification_show(n, 0))
- {
- log("notification failed");
- }
- }
- else
- {
- log("YATwm non fatal error (Code " << cfgErr.code << ")\n" << cfgErr.message);
- std::string title = "YATwm non fatal config error (Code " + std::to_string(cfgErr.code) + ")";
- std::string body = "Check logs for more information";
- NotifyNotification* n = notify_notification_new(title.c_str(),
- body.c_str(),
- 0);
- notify_notification_set_timeout(n, 10000);
- if(!notify_notification_show(n, 0))
- {
- log("notification failed");
- }
- }
- }
-}
-void updateTime()
-{
- timeNow = std::time(0);
- now = std::localtime(&timeNow);
- strftime(nowString, sizeof(nowString), "[%H:%M:%S] ", now);
-}
-
-//Keybind commands
-const void exit(const CommandArg* argv)
-{
- keepGoing = false;
-}
-const void spawn(const CommandArg* argv)
-{
- if(fork() == 0)
- {
- const std::string argsStr = argv[0].str;
- vector<std::string> args = split(argsStr, ' ');
- char** execvpArgs = new char*[args.size()];
- for(int i = 0; i < args.size(); i++)
- {
- execvpArgs[i] = strdup(args[i].c_str());
- }
- int null = open("/dev/null", O_WRONLY);
- dup2(null, 0);
- dup2(null, 1);
- dup2(null, 2);
- execvp(execvpArgs[0], execvpArgs);
- exit(0);
- }
-}
-const void spawnOnce(const CommandArg* argv)
-{
- if(cfg.loaded)
- return;
- else spawn(argv);
-}
-const void toggle(const CommandArg* argv)
-{
- nextDir = nextDir = (nextDir==horizontal)? vertical : horizontal;
-}
-const void kill(const CommandArg* argv)
-{
- Window w;
- int revertToReturn;
- XGetInputFocus(dpy, &w, &revertToReturn);
- Atom* supported_protocols;
- int num_supported_protocols;
- if (XGetWMProtocols(dpy,
- w,
- &supported_protocols,
- &num_supported_protocols) &&
- (std::find(supported_protocols,
- supported_protocols + num_supported_protocols,
- XInternAtom(dpy, "WM_DELETE_WINDOW", false)) !=
- supported_protocols + num_supported_protocols)) {
- // 1. Construct message.
- XEvent msg;
- memset(&msg, 0, sizeof(msg));
- msg.xclient.type = ClientMessage;
- msg.xclient.message_type = XInternAtom(dpy, "WM_PROTOCOLS", false);
- msg.xclient.window = w;
- msg.xclient.format = 32;
- msg.xclient.data.l[0] = XInternAtom(dpy, "WM_DELETE_WINDOW", false);
- // 2. Send message to window to be closed.
- cout << "Nice kill\n";
- XSendEvent(dpy, w, false, 0, &msg);
- } else {
- cout << "Mean kill\n";
- XKillClient(dpy, w);
- }
-}
-// Took this out as it is used commonly
-void cWS(int newWS)
-{
- int prevWS = currWS;
-
- currWS = newWS;
- if(prevWS == currWS)
- return;
- untileRoots();
-
- //log("Changing WS with keybind");
-
- for(int i = 0; i < cfg.workspaces[newWS - 1].screenPreferencesc; i++)
- {
- if(nscreens > cfg.workspaces[newWS - 1].screenPreferences[i])
- {
- int screen = cfg.workspaces[newWS - 1].screenPreferences[i];
- //log("Found screen (screen " << screenPreferences[arg.num - 1][i] << ")");
- prevWS = focusedWorkspaces[screen];
- //log("Changed prevWS");
- focusedWorkspaces[screen] = newWS;
- //log("Changed focusedWorkspaces");
- if(focusedScreen != screen)
- {
- focusedScreen = screen;
- XWarpPointer(dpy, root, root, 0, 0, 0, 0, screens[screen].x + screens[screen].w/2, screens[screen].y + screens[screen].h/2);
- }
- //log("Changed focusedScreen");
- break;
- }
- }
-
- //log("Finished changes");
-
- //log(prevWS);
- // LOOK: what is this for?????
- if(prevWS < 1 || prevWS > cfg.workspaces.size())
- {
- //untile(prevWS);
- }
- //log("Untiled");
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- tileRoots();
- //log("Roots tiled");
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-
- cout << focusedWorkspaces[0] << endl;
-
- //EWMH
- setCurrentDesktop(currWS);
-}
-const void changeWS(const CommandArg* argv)
-{
- cWS(argv[0].num);
-}
-const void wToWS(const CommandArg* argv)
-{
- Window focusedWindow;
- int revertToReturn;
- XGetInputFocus(dpy, &focusedWindow, &revertToReturn);
- if(focusedWindow == root)
- return;
-
- int fID = frameIDS.find(focusedWindow)->second;
- //TODO: make floating windows move WS
- if(clients.find(frames.find(fID)->second.cID)->second.floating)
- return;
- vector<int>& pSF = frames.find(frames.find(fID)->second.pID)->second.subFrameIDs;
- for(int i = 0; i < pSF.size(); i++)
- {
- if(pSF[i] == fID)
- {
- //Frame disolve
- pSF.erase(pSF.begin() + i);
- int pID = frames.find(fID)->second.pID;
- if(pSF.size() < 2 && !frames.find(pID)->second.isRoot)
- {
- //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;
- }
- }
- frames.find(fID)->second.pID = argv[0].num;
- frames.find(argv[0].num)->second.subFrameIDs.push_back(fID);
-
- //EWMH
- setWindowDesktop(focusedWindow, argv[0].num);
-
- XUnmapWindow(dpy, focusedWindow);
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- untileRoots();
- tileRoots();
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-}
-int dirFind(int fID, MoveDir dir)
-{
- vector<int>& pSF = frames.find(frames.find(fID)->second.pID)->second.subFrameIDs;
- TileDir pDir = frames.find(frames.find(fID)->second.pID)->second.dir;
-
- int i = 0;
- for(int f : pSF)
- {
- if(f == fID)
- {
- break;
- }
- i++;
- }
-
- if(pDir == vertical)
- {
- switch(dir)
- {
- case UP: i--; break;
- case DOWN: i++; break;
- case LEFT: return (frames.find(fID)->second.pID > cfg.numWS)? dirFind(frames.find(fID)->second.pID, dir) : fID;
- case RIGHT: return (frames.find(fID)->second.pID > cfg.numWS)? dirFind(frames.find(fID)->second.pID, dir) : fID;
- }
- }
- else if(pDir == horizontal)
- {
- switch(dir)
- {
- case LEFT: i--; break;
- case RIGHT: i++; break;
- case UP: return (frames.find(fID)->second.pID > cfg.numWS)? dirFind(frames.find(fID)->second.pID, dir) : fID;
- case DOWN: return (frames.find(fID)->second.pID > cfg.numWS)? dirFind(frames.find(fID)->second.pID, dir) : fID;
- }
- }
- if(i < 0)
- i = pSF.size() - 1;
- if(i == pSF.size())
- i = 0;
-
- return pSF[i];
-}
-const void focChange(const CommandArg* argv)
-{
- Window focusedWindow;
- int revertToReturn;
- XGetInputFocus(dpy, &focusedWindow, &revertToReturn);
- if(focusedWindow == root)
- return;
-
- int fID = frameIDS.find(focusedWindow)->second;
- int nID = dirFind(fID, argv[0].dir);
- int fNID = FFCF(nID);
- Window w = clients.find(frames.find(fNID)->second.cID)->second.w;
- XSetInputFocus(dpy, w, RevertToPointerRoot, CurrentTime);
-}
-const void wMove(const CommandArg* argv)
-{
- Window focusedWindow;
- int revertToReturn;
- XGetInputFocus(dpy, &focusedWindow, &revertToReturn);
- if(focusedWindow == root)
- return;
-
- int fID = frameIDS.find(focusedWindow)->second;
- if(clients.find(frames.find(fID)->second.cID)->second.floating)
- return;
- int nID = dirFind(fID, argv[0].dir);
- int fNID = FFCF(nID);
- int pID = frames.find(fNID)->second.pID;
- int oPID = frames.find(fID)->second.pID;
-
- vector<int>& pSF = frames.find(pID)->second.subFrameIDs;
- vector<int>& oPSF = frames.find(oPID)->second.subFrameIDs;
-
- for(int i = 0; i < frames.find(oPID)->second.subFrameIDs.size(); i++)
- {
- if(oPSF[i] != fID)
- continue;
-
- if(pID!=oPID)
- {
- //Frame dissolve
- oPSF.erase(oPSF.begin() + i);
- if(oPSF.size() < 2 && !frames.find(oPID)->second.isRoot)
- {
- //Erase parent frame
- int lastChildID = frames.find(frames.find(oPID)->second.subFrameIDs[0])->second.ID;
- int parentParentID = frames.find(oPID)->second.pID;
- vector<int>& parentParentSubFrameIDs = frames.find(parentParentID)->second.subFrameIDs;
- for(int j = 0; j < parentParentSubFrameIDs.size(); j++)
- {
- if(parentParentSubFrameIDs[j] == oPID)
- {
- parentParentSubFrameIDs[j] = lastChildID;
- frames.find(lastChildID)->second.pID = parentParentID;
- frames.erase(oPID);
- break;
- }
- }
- }
-
- frames.find(fID)->second.pID = pID;
- pSF.push_back(fID);
- }
- else
- {
- if(frames.find(pID)->second.dir == vertical)
- {
- if(argv[0].dir == LEFT || argv[0].dir == RIGHT)
- return;
- }
- else
- {
- if(argv[0].dir == UP || argv[0].dir == DOWN)
- return;
- }
-
- int offset;
- if(argv[0].dir == UP || argv[0].dir == LEFT)
- offset = -1;
- else
- offset = 1;
-
- int swapPos = i + offset;
-
- if(swapPos == pSF.size())
- swapPos = 0;
- else if(swapPos == -1)
- swapPos = pSF.size() - 1;
-
- std::swap(pSF[i], pSF[swapPos]);
- }
- untileRoots();
- tileRoots();
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- XSetInputFocus(dpy, focusedWindow, RevertToPointerRoot, CurrentTime);
- return;
- }
- XSetInputFocus(dpy, focusedWindow, RevertToPointerRoot, CurrentTime);
-}
-const void bashSpawn(const CommandArg* argv)
-{
- if(fork() == 0)
- {
- int null = open("/dev/null", O_WRONLY);
- dup2(null, 0);
- dup2(null, 1);
- dup2(null, 2);
- system(argv[0].str);
- exit(0);
- }
-}
-const void bashSpawnOnce(const CommandArg* argv)
-{
- if(cfg.loaded)
- return;
- else bashSpawn(argv);
-}
-const void reload(const CommandArg* argv)
-{
- detectScreens();
-
- //Clear keybinds
- keybindsModule.clearKeybinds();
-
- //Load config again
- vector<Err> cfgErr = cfg.reloadFile();
- //Error check
- handleConfigErrs(cfgErr);
-
- //Re tile
- untileRoots();
- tileRoots();
-}
-const void wsDump(const CommandArg* argv)
-{
- log("Workspace dump:");
- for(int i = 1; i < currFrameID; i++)
- {
- if(getFrame(i).isClient)
- {
- int id = i;
- while(!getFrame(id).isRoot)
- {
- id=getFrame(id).pID;
- }
- log("\tClient with ID: " << getClient(getFrame(i).cID).w << ", on worskapce " << id);
- }
- }
-}
-const void nextMonitor(const CommandArg* argv)
-{
- focusedScreen++;
- if(focusedScreen >= nscreens)
- focusedScreen = 0;
-
- XWarpPointer(dpy, root, root, 0, 0, 0, 0, screens[focusedScreen].x + screens[focusedScreen].w/2, screens[focusedScreen].y + screens[focusedScreen].h/2);
- focusRoot(focusedWorkspaces[focusedScreen]);
-}
-const void fullscreen(const CommandArg* arg)
-{
- Window focusedWindow;
- int focusedRevert;
- XGetInputFocus(dpy, &focusedWindow, &focusedRevert);
-
- int fID = getFrameID(focusedWindow);
- int cID = getFrame(fID).cID;
- getClient(cID).fullscreen ^= true;
- tileRoots();
- setFullscreen(focusedWindow, getClient(cID).fullscreen);
-}
-
-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, (unsigned int) e.value_mask, &changes);
- log("Configure request: " << e.window);
- //XSetInputFocus(dpy, e.window, RevertToNone, CurrentTime);
- //tileRoots();
-}
-
-void mapRequest(XMapRequestEvent e)
-{
- XMapWindow(dpy, e.window);
-
- XTextProperty name;
- bool gotName = XGetWMName(dpy, e.window, &name);
- XWindowAttributes attr;
- XGetWindowAttributes(dpy, e.window, &attr);
- if(gotName)
- {
- log("Mapping window: " << name.value);
- }
- else
- {
- log("Mapping window with unknown name (its probably mpv, mpv is annoying)");
- }
- log("\tWindow ID: " << e.window);
-
- Window focusedWindow;
- int revertToReturn;
- int pID;
- XGetInputFocus(dpy, &focusedWindow, &revertToReturn);
- if(focusedWindow && focusedWindow != root && frameIDS.count(focusedWindow)>0)
- {
- //Use focused to determine parent
- pID = frames.find(frameIDS.find(focusedWindow)->second)->second.pID;
- }
- else
- {
- Window rootRet, childRet;
- int rX, rY, cX, cY;
- unsigned int maskRet;
- XQueryPointer(dpy, root, &rootRet, &childRet, &rX, &rY, &cX, &cY, &maskRet);
- mX = rX;
- mY = rY;
- int monitor = 0;
- for(int i = 0; i < nscreens; i++)
- {
- if(screens[i].x <= mX && mX < screens[i].x + screens[i].w)
- {
- if(screens[i].y <= mY && mY < screens[i].y + screens[i].h)
- {
- monitor = i;
- }
- }
- }
- pID = focusedWorkspaces[monitor];
- focusedScreen = monitor;
- /*
- if(mX == rX && mY == rY)
- {
- //Use focused screen
- log("\tFocused screen is: " << focusedScreen);
- }
- else
- {
- //Use mouse
- //TODO: Make this find the monitor
- log("\tMouse is at x: " << rX << ", y: " << rY);
- mX = rX;
- mY = rY;
- }
- */
- }
-
- unsigned char* data;
- Atom type;
- int status = getProp(e.window, "_NET_WM_WINDOW_TYPE", &type, &data);
- if (status == Success && type != None && ((Atom*)data)[0] == XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", false))
- {
- log("\tWindow was bar");
- bH = attr.height;
- bar = e.window;
- XFree(data);
- return;
- }
- XFree(data);
-
-
-
-
- XSelectInput(dpy, e.window, EnterWindowMask);
-
- //Make client
- Client c = {currClientID, e.window, false, false};
- currClientID++;
-
- //Add to clients map
- clients.insert(pair<int, Client>(c.ID, c));
-
- //Make frame
- //pID = (frameIDS.count(focusedWindow)>0)? frames.find(frameIDS.find(focusedWindow)->second)->second.pID : currWS;
- vector<int> v;
- vector<int> floating;
- Frame f = {currFrameID, pID, true, c.ID, noDir, v, false, floating};
- currFrameID++;
-
-
- //Add ID to frameIDS map
- frameIDS.insert(pair<Window, int>(e.window, f.ID));
-
- status = getProp(e.window, "_NET_WM_STATE", &type, &data);
- if(status == Success && type!=None && (((Atom*)data)[0] == XInternAtom(dpy, "_NET_WM_STATE_MODAL", false) || ((Atom*)data)[0] == XInternAtom(dpy, "_NET_WM_STATE_ABOVE", false)))
- {
- cout << "Floating" << endl;
- clients.find(c.ID)->second.floating = true;
- frames.find(pID)->second.floatingFrameIDs.push_back(f.ID);
- frames.insert(pair<int, Frame>(f.ID, f));
- setWindowDesktop(e.window, currWS);
- updateClientList(clients);
- XFree(data);
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- tileRoots();
- return;
- }
- XFree(data);
-
- //Check how to add
- if(nextDir == frames.find(pID)->second.dir || frameIDS.count(focusedWindow)==0)
- {
- //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, false, floating};
-
- //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));
-
- setWindowDesktop(e.window, currWS);
- updateClientList(clients);
-
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- XSetInputFocus(dpy, e.window, RevertToNone, CurrentTime);
- tileRoots();
-}
-
-void destroyNotify(XDestroyWindowEvent e)
-{
- if(frameIDS.count(e.window)<1)
- return;
- log("Destroy notif");
- log("\tWindow ID: " << e.window);
- int fID = frameIDS.find(e.window)->second;
- int pID = frames.find(fID)->second.pID;
- vector<int>& pS = frames.find(pID)->second.subFrameIDs;
- if(clients.find(frames.find(fID)->second.cID)->second.floating)
- {
- pS = frames.find(pID)->second.floatingFrameIDs;
- }
- 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 && !frames.find(pID)->second.isRoot)
- {
- //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;
- }
- }
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
- //tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- tileRoots();
-
- updateClientList(clients);
-}
-void enterNotify(XEnterWindowEvent e)
-{
- //log(e.xcrossing.x);
- //Cancel if crossing into root
- if(e.window == root)
- return;
-
- XWindowAttributes attr;
- XGetWindowAttributes(dpy, e.window, &attr);
- int monitor = 0;
- for(int i = 0; i < nscreens; i++)
- {
- if(screens[i].x <= attr.x && attr.x < screens[i].x + screens[i].w)
- {
- if(screens[i].y <= attr.y && attr.y < screens[i].y + screens[i].h)
- {
- monitor = i;
- }
- }
- }
- focusedScreen = monitor;
- XSetInputFocus(dpy, e.window, RevertToNone, CurrentTime);
-}
-void clientMessage(XClientMessageEvent e)
-{
- char* name = XGetAtomName(dpy, e.message_type);
- log("Client message: " << name);
- if(e.message_type == XInternAtom(dpy, "_NET_CURRENT_DESKTOP", false))
- {
- cWS(e.data.l[0] + 1);
- /*
- //Change desktop
- int nextWS = (long)e.data.l[0] + 1;
- int prevWS = currWS;
- currWS = nextWS;
-
- if(prevWS == currWS)
- return;
-
- untile(prevWS);
- tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-
- //EWMH
- setCurrentDesktop(currWS);
- */
- }
- else if(e.message_type == XInternAtom(dpy, "_NET_WM_STATE", false))
- {
- if((Atom)e.data.l[0] == 0)
- log("\tremove");
- if((Atom)e.data.l[0] == 1)
- log("\ttoggle");
- if((Atom)e.data.l[0] == 2)
- log("\tadd");
- char* prop1 = XGetAtomName(dpy, (Atom)e.data.l[1]);
- if((Atom)e.data.l[1] == XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", false))
- {
- int fID = getFrameID(e.window);
- int cID = getFrame(fID).cID;
- getClient(cID).fullscreen = (Atom) e.data.l[0] > 0;
- setFullscreen(e.window, (Atom) e.data.l[0] > 0);
- tileRoots();
- }
- XFree(prop1);
- }
- XFree(name);
-}
-
-static int OnXError(Display* display, XErrorEvent* e)
-{
- char* error = new char[50];
- XGetErrorText(dpy, e->type, error, 50);
- log("XError " << error);
- delete[] error;
- return 0;
-}
-
-void tileRoots()
-{
- for(int i = 0; i < nscreens; i++)
- {
- int fullscreenClientID = tile(focusedWorkspaces[i], screens[i].x + cfg.outerGaps, screens[i].y + cfg.outerGaps, screens[i].w - cfg.outerGaps*2, screens[i].h - cfg.outerGaps*2 - bH);
- if(fullscreenClientID!=noID)
- {
- untile(focusedWorkspaces[i]);
- Client c = getClient(fullscreenClientID);
- XMapWindow(dpy, c.w);
- XMoveWindow(dpy, c.w,
- screens[i].x, screens[i].y);
- XResizeWindow(dpy, c.w,
- screens[i].w, screens[i].h);
- }
- }
-}
-void untileRoots()
-{
- for(int i = 0; i < nscreens; i++)
- {
- untile(focusedWorkspaces[i]);
- }
-}
-int tile(int frameID, int x, int y, int w, int h)
-{
- for(int fID : frames.find(frameID)->second.floatingFrameIDs)
- {
- Window w = clients.find(frames.find(fID)->second.cID)->second.w;
- XMapWindow(dpy, w);
- }
- TileDir dir = frames.find(frameID)->second.dir;
- int i = 0;
- vector<int>& subFrameIDs = frames.find(frameID)->second.subFrameIDs;
- 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(i==subFrameIDs.size())
- {
- wW = (dir==horizontal) ? w - (wX - x) : w;
- wH = (dir==vertical) ? h - (wY - y) : h;
- }
- if(!f.isClient)
- {
- int fullscreenClientID = tile(fID, wX, wY, wW, wH);
- if(fullscreenClientID == noID)
- return fullscreenClientID;
- continue;
- }
- Client c = clients.find(f.cID)->second;
- if(c.fullscreen)
- return c.ID;
- wX += cfg.gaps;
- wY += cfg.gaps;
- wW -= cfg.gaps * 2;
- wH -= cfg.gaps * 2;
- XMapWindow(dpy, c.w);
- XMoveWindow(dpy, c.w,
- wX, wY);
- XResizeWindow(dpy, c.w,
- wW, wH);
- }
- return noID;
-}
-
-void untile(int frameID)
-{
- for(int fID : frames.find(frameID)->second.floatingFrameIDs)
- {
- Window w = clients.find(frames.find(fID)->second.cID)->second.w;
- XUnmapWindow(dpy, w);
- }
- 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;
- if(!f.isClient)
- {
- untile(fID);
- continue;
- }
- Client c = clients.find(f.cID)->second;
- XUnmapWindow(dpy, c.w);
- }
-}
-
-int main(int argc, char** argv)
-{
- if(argc > 1)
- {
- if(strcmp(argv[1], "--version") == 0)
- {
- const char* version =
- "YATwm for X\n"
- "version 0.1.0";
- cout << version << endl;
- return 0;
- }
- }
- //Important init stuff
- mX = mY = 0;
- dpy = XOpenDisplay(nullptr);
- root = Window(DefaultRootWindow(dpy));
-
- // Adding commands
- commandsModule.addCommand("exit", exit, 0, {});
- commandsModule.addCommand("spawn", spawn, 1, {STR_REST});
- commandsModule.addCommand("spawnOnce", spawnOnce, 1, {STR_REST});
- commandsModule.addCommand("toggle", toggle, 0, {});
- commandsModule.addCommand("kill", kill, 0, {});
- commandsModule.addCommand("changeWS", changeWS, 1, {NUM});
- commandsModule.addCommand("wToWS", wToWS, 1, {NUM});
- commandsModule.addCommand("focChange", focChange, 1, {MOVDIR});
- commandsModule.addCommand("bashSpawn", bashSpawn, 1, {STR_REST});
- commandsModule.addCommand("bashSpawnOnce", bashSpawnOnce, 1, {STR_REST});
- commandsModule.addCommand("reload", reload, 0, {});
- commandsModule.addCommand("wsDump", wsDump, 0, {});
- commandsModule.addCommand("nextMonitor", nextMonitor, 0, {});
- commandsModule.addCommand("fullscreen", fullscreen, 0, {});
-
- //Config
- std::vector<Err> cfgErr;
-
- char* confDir = getenv("XDG_CONFIG_HOME");
- if(confDir != NULL)
- {
- cfgErr = cfg.loadFromFile(string(confDir) + "/YATwm/config");
- }
- else
- {
- string home = getenv("HOME");
- cfgErr = cfg.loadFromFile(home + "/.config/YATwm/config");
- }
-
- //Log
- yatlog.open(cfg.logFile, std::ios_base::app);
- yatlog << "\n" << endl;
-
- //Print starting message
- log("-------- YATWM STARTING --------");
-
- //Notifications
- notify_init("YATwm");
-
- //Error check config
- handleConfigErrs(cfgErr);
-
- screens = new ScreenInfo[1];
- focusedWorkspaces = new int[1];
- detectScreens();
-
- int screenNum = DefaultScreen(dpy);
- sW = DisplayWidth(dpy, screenNum);
- sH = DisplayHeight(dpy, screenNum);
-
- //XSetErrorHandler(OnXError);
- XSelectInput(dpy, root, SubstructureRedirectMask | SubstructureNotifyMask | KeyPressMask | EnterWindowMask);
-
- XDefineCursor(dpy, root, XCreateFontCursor(dpy, XC_top_left_arrow));
- //EWMH
- initEWMH(&dpy, &root, cfg.workspaces.size(), cfg.workspaces);
- setCurrentDesktop(1);
-
- ipc.init();
-
- for(int i = 1; i < cfg.numWS + 1; i++)
- {
- vector<int> v;
- Frame rootFrame = {i, noID, false, noID, horizontal, v, true};
- frames.insert(pair<int, Frame>(i, rootFrame));
- currFrameID++;
- }
-
- XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
- XWarpPointer(dpy, root, root, 0, 0, 0, 0, 960, 540);
-
- fd_set fdset;
- int x11fd = ConnectionNumber(dpy);
- FD_ZERO(&fdset);
- FD_SET(x11fd, &fdset);
- FD_SET(ipc.getFD(), &fdset);
-
- log("Begin mainloop");
- while(keepGoing)
- {
- FD_ZERO(&fdset);
- FD_SET(x11fd, &fdset);
- FD_SET(ipc.getFD(), &fdset);
- int ready = select(x11fd + 1, &fdset, NULL, NULL, NULL);
- if(FD_ISSET(ipc.getFD(), &fdset))
- {
- ipc.doListen();
- }
- if(FD_ISSET(x11fd, &fdset))
- {
- XEvent e;
- while(XPending(dpy))
- {
- XNextEvent(dpy, &e);
-
- switch(e.type)
- {
- case KeyPress:
- keybindsModule.handleKeypress(e.xkey);
- break;
- case ConfigureRequest:
- configureRequest(e.xconfigurerequest);
- break;
- case MapRequest:
- mapRequest(e.xmaprequest);
- break;
- case DestroyNotify:
- destroyNotify(e.xdestroywindow);
- break;
- case EnterNotify:
- enterNotify(e.xcrossing);
- break;
- case ClientMessage:
- clientMessage(e.xclient);
- break;
- default:
- // cout << "Unhandled event: " << getEventName(e.type) << endl;
- break;
- }
- }
- }
- if(ready == -1)
- {
- cout << "E" << endl;
- log("ERROR");
- }
- }
-
- //Kill children
- ipc.quitIPC();
- XCloseDisplay(dpy);
-}