summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBossCode45 <human.cyborg42@gmail.com>2024-12-19 15:00:45 +1300
committerBossCode45 <human.cyborg42@gmail.com>2024-12-24 15:56:39 +1300
commitd1d4a63d4473cd4910b678cf5b385f622186fbd3 (patch)
treee6a4a478ad63e29ab12479d88a700238b970ec26 /src
parentc3791254bfb127d64b329098bc792acaa9c30832 (diff)
downloadYATwm-d1d4a63d4473cd4910b678cf5b385f622186fbd3.tar.gz
YATwm-d1d4a63d4473cd4910b678cf5b385f622186fbd3.zip
feat: Added IPC client side to main binary
Updated command line arguments to use `getopt_long' Made it so both -v and --version work Made it so that if you give it non recognised arguments they are sent through the socket to the running window manager if possible.
Diffstat (limited to 'src')
-rw-r--r--src/IPC.cpp79
-rw-r--r--src/IPC.h25
-rw-r--r--src/main.cpp204
3 files changed, 234 insertions, 74 deletions
diff --git a/src/IPC.cpp b/src/IPC.cpp
index 709cc5c..3ed1bb6 100644
--- a/src/IPC.cpp
+++ b/src/IPC.cpp
@@ -1,6 +1,7 @@
#include "IPC.h"
#include "ewmh.h"
+#include <X11/Xlib.h>
#include <cstring>
#include <string>
#include <sys/socket.h>
@@ -11,14 +12,14 @@ using std::cout, std::endl;
static const char* path = "/tmp/YATwm.sock";
-IPCModule::IPCModule(CommandsModule& commandsModule, Config& cfg, Globals& globals)
+IPCServerModule::IPCServerModule(CommandsModule& commandsModule, Config& cfg, Globals& globals)
:commandsModule(commandsModule),
cfg(cfg),
globals(globals)
{
}
-void IPCModule::init()
+void IPCServerModule::init()
{
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
address.sun_family = AF_UNIX;
@@ -35,7 +36,7 @@ void IPCModule::init()
ready = true;
}
-void IPCModule::doListen()
+void IPCServerModule::doListen()
{
if(!ready)
return;
@@ -73,7 +74,7 @@ void IPCModule::doListen()
close(newsock);
}
-void IPCModule::quitIPC()
+void IPCServerModule::quitIPC()
{
if(!ready)
return;
@@ -81,7 +82,7 @@ void IPCModule::quitIPC()
ready = false;
}
-int IPCModule::getFD()
+int IPCServerModule::getFD()
{
if(!ready)
return -1;
@@ -89,3 +90,71 @@ int IPCModule::getFD()
return sockfd;
return -1;
}
+
+IPCClientModule::IPCClientModule()
+{
+ ready = false;
+}
+
+int IPCClientModule::init()
+{
+ Display* dpy = XOpenDisplay(nullptr);
+ Window root = Window(DefaultRootWindow(dpy));
+ Atom propName = XInternAtom(dpy, "YATWM_SOCKET_PATH", false);
+ Atom propType = XInternAtom(dpy, "STRING", false);
+ int format;
+ unsigned long length;
+ unsigned long after;
+ Atom type;
+ unsigned char* sockPath;
+
+ if(XGetWindowProperty(dpy, root, propName, 0L, 32L, False, propType, &type, &format, &length, &after, &sockPath) != Success || type == None)
+ {
+ cout << "Failed to get path" << endl;
+ XFree(sockPath);
+ return 1;
+ }
+
+ sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(sockfd == -1)
+ {
+ cout << "Failed to create socket" << endl;
+ XFree(sockPath);
+ return -1;
+ }
+ sockaddr_un address;
+ address.sun_family = AF_UNIX;
+ strcpy(address.sun_path, (const char*)sockPath);
+ if(connect(sockfd, (sockaddr*) &address, sizeof(address)) == -1)
+ {
+ cout << "Failed connect" << endl;
+ XFree(sockPath);
+ return -1;
+ }
+ XFree(sockPath);
+ XCloseDisplay(dpy);
+
+ ready = true;
+ return 0;
+}
+
+int IPCClientModule::sendMessage(const char* message, int length)
+{
+ if(!ready)
+ return 1;
+ return write(sockfd, message, length);
+}
+
+int IPCClientModule::getMessage(char* buff, int buffsize)
+{
+ if(!ready)
+ return 1;
+ return read(sockfd, buff, buffsize);
+}
+
+void IPCClientModule::quit()
+{
+ if(!ready)
+ return;
+ close(sockfd);
+}
diff --git a/src/IPC.h b/src/IPC.h
index 97716bb..e0bbcee 100644
--- a/src/IPC.h
+++ b/src/IPC.h
@@ -7,10 +7,10 @@
#include "config.h"
#include "util.h"
-class IPCModule
+class IPCServerModule
{
public:
- IPCModule(CommandsModule& commandsModule, Config& cfg, Globals& globals);
+ IPCServerModule(CommandsModule& commandsModule, Config& cfg, Globals& globals);
void init();
void doListen();
void quitIPC();
@@ -25,3 +25,24 @@ private:
bool ready = false;
sockaddr_un address;
};
+
+class IPCClientModule
+{
+public:
+ IPCClientModule();
+
+ // Returns 0 for success, 1 for X error, -1 for socket error
+ int init();
+
+ // Returns 0 for success, 1 for not ready, -1 for socket error
+ int sendMessage(const char* message, int length);
+
+ // Returns 0 for success, 1 for not ready, -1 for socket error
+ int getMessage(char* buff, int buffsize);
+
+
+ void quit();
+private:
+ bool ready;
+ int sockfd;
+};
diff --git a/src/main.cpp b/src/main.cpp
index a11b203..da1ae9b 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,6 +5,7 @@
#include <X11/Xutil.h>
#include <X11/extensions/Xrandr.h>
+#include <bits/getopt_core.h>
#include <libnotify/notification.h>
#include <libnotify/notify.h>
@@ -26,6 +27,7 @@
#include <algorithm>
#include <fcntl.h>
#include <poll.h>
+#include <getopt.h>
#include "IPC.h"
#include "commands.h"
@@ -48,8 +50,8 @@ std::time_t timeNow;
std::tm *now;
char nowString[80];
-#define log(x) \
- updateTime(); \
+#define log(x) \
+ updateTime(); \
yatlog << nowString << x << std::endl
Display* dpy;
@@ -62,7 +64,7 @@ void updateMousePos();
CommandsModule commandsModule;
Config cfg(commandsModule);
KeybindsModule keybindsModule(commandsModule, cfg, globals, &updateMousePos);
-IPCModule ipc(commandsModule, cfg, globals);
+IPCServerModule ipc(commandsModule, cfg, globals);
int sW, sH;
int bH;
@@ -193,8 +195,8 @@ void handleConfigErrs(vector<Err> cfgErrs)
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);
+ body.c_str(),
+ 0);
notify_notification_set_timeout(n, 10000);
if(!notify_notification_show(n, 0))
{
@@ -207,8 +209,8 @@ void handleConfigErrs(vector<Err> cfgErrs)
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);
+ body.c_str(),
+ 0);
notify_notification_set_timeout(n, 10000);
if(!notify_notification_show(n, 0))
{
@@ -317,30 +319,30 @@ const void kill(const CommandArg* argv)
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);
- }
+ 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);
+ }
}
const void changeWS(const CommandArg* argv)
{
@@ -418,20 +420,20 @@ int dirFind(int fID, MoveDir dir)
{
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;
+ 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;
+ 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)
@@ -677,19 +679,19 @@ void mapRequest(XMapRequestEvent e)
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;
- }
+ 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;
+ }
*/
}
@@ -876,7 +878,7 @@ void clientMessage(XClientMessageEvent e)
currWS = nextWS;
if(prevWS == currWS)
- return;
+ return;
untile(prevWS);
tile(currWS, outerGaps, outerGaps, sW - outerGaps*2, sH - outerGaps*2 - bH);
@@ -928,9 +930,9 @@ void tileRoots()
Client c = getClient(fullscreenClientID);
XMapWindow(dpy, c.w);
XMoveWindow(dpy, c.w,
- screens[i].x, screens[i].y);
+ screens[i].x, screens[i].y);
XResizeWindow(dpy, c.w,
- screens[i].w, screens[i].h);
+ screens[i].w, screens[i].h);
}
}
}
@@ -983,9 +985,9 @@ int tile(int frameID, int x, int y, int w, int h)
wH -= cfg.gaps * 2;
XMapWindow(dpy, c.w);
XMoveWindow(dpy, c.w,
- wX, wY);
+ wX, wY);
XResizeWindow(dpy, c.w,
- wW, wH);
+ wW, wH);
}
return noID;
}
@@ -1015,24 +1017,92 @@ void untile(int frameID)
}
}
+void printVersion()
+{
+ const char* version =
+ "YATwm for X\n"
+ "version 0.0.1";
+ cout << version << endl;
+}
+
int main(int argc, char** argv)
{
- if(argc > 1)
+ int versionFlag = 0;
+ bool immediateExit = false;
+ while(1)
{
- if(strcmp(argv[1], "--version") == 0)
+ static option long_options[] = {{"version", no_argument, &versionFlag, 1},
+ {0, 0, 0, 0}};
+
+ int optionIndex;
+ char c = getopt_long(argc, argv, "v", long_options, &optionIndex);
+
+ if(c == -1)
+ break;
+
+ switch(c)
{
- const char* version =
- "YATwm for X\n"
- "version 0.1.0";
- cout << version << endl;
- return 0;
+ case 0:
+ if(long_options[optionIndex].flag != 0)
+ break;
+ //Option had arg
+ break;
+ case 'v':
+ versionFlag = 1;
+ case '?':
+ //Error??
+ break;
+ default:
+ //Big error???
+ cout << "BIG ERROR WITH OPTIONS" << endl;
}
}
-
+
+ if(versionFlag == 1)
+ {
+ printVersion();
+ immediateExit = true;
+ }
+
+ if(optind < argc)
+ {
+ //Extra options - probably meant to be a command sent on IPC
+ std::string message;
+ while(optind < argc)
+ {
+ message += argv[optind++];
+ if(optind != argc)
+ message += " ";
+ }
+
+ cout << message << endl;
+
+ IPCClientModule IPCClient;
+ switch(IPCClient.init())
+ {
+ case 1:
+ cout << "X error: is YATwm running?" << endl;
+ exit(1);
+ case -1:
+ cout << "Socket error" << endl;
+ exit(1);
+ }
+ IPCClient.sendMessage(message.c_str(), message.length());
+ char buff[256];
+ IPCClient.getMessage(buff, 256);
+ cout << buff << endl;
+ IPCClient.quit();
+
+ immediateExit = true;
+ }
+
+ if(immediateExit)
+ exit(0);
+
//Important init stuff
mX = mY = 0;
- dpy = XOpenDisplay(nullptr);
- root = Window(DefaultRootWindow(dpy));
+ dpy = XOpenDisplay(nullptr);
+ root = Window(DefaultRootWindow(dpy));
// Adding commands
commandsModule.addCommand("exit", exit, 0, {});
commandsModule.addCommand("spawn", spawn, 1, {STR_REST});