create basics

This commit is contained in:
Akos Horvath 2022-07-27 21:35:05 +02:00
parent cd189fd54c
commit b6132f82fa
2 changed files with 345 additions and 0 deletions

276
wm.c Normal file
View File

@ -0,0 +1,276 @@
#include "wm.h"
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xinerama.h>
Monitor wm_monitor_open(Display *d, XineramaScreenInfo info)
{
Monitor m = {
.display = d,
.info = info
};
return m;
}
void wm_monitors_open_all(Display *d)
{
int count;
XineramaScreenInfo *xsi = XineramaQueryScreens(d, &count);
if (!xsi) {
printf("wm: Could not open display. Exiting.\n");
exit(1);
}
wm_monitors = malloc(count * sizeof(Monitor));
for (int i = 0; i < count; i++) {
*(wm_monitors + i) = wm_monitor_open(d, *(xsi + i));
//cfg
wm_monitors[i].wscount = 9;
wm_monitors[i].wss = malloc(wm_smon->wscount*sizeof(int));
wm_monitors[i].selws = wm_monitors[i].wss[0];
for (int j = 0; j < wm_monitors[i].wscount; j++)
wm_monitors[i].wss[i] = j;
wm_monitors[i].clients = NULL;
}
wm_smon = &wm_monitors[0];
wm_smon->clients = &wm_root;
}
Display* wm_connect_display()
{
Display *d;
if (!(d = XOpenDisplay(NULL)))
{
printf("wm: Could not open display. Exiting.\n");
exit(1);
}
return d;
}
static int wm_xerror_handler(Display *displau, XErrorEvent *e)
{
if (e->error_code == BadAccess) {
wm_other_wm = true;
}
return 0;
}
static int wm_other_wm_handler(Display *displau, XErrorEvent *e)
{
printf("wm: Error occured. %d\n", e->error_code);
return 0;
}
void wm_create_handler(XCreateWindowEvent e)
{
Client *nc = malloc(sizeof(Client));
Client *c;
nc->wn = e.window;
nc->m = wm_smon;
nc->ws = nc->m->selws;
nc->hidden = true;
if (wm_smon->clients == NULL) {
wm_smon->clients = nc;
nc->prev = NULL;
} else {
LAST_WINDOW(c, wm_smon)
c->next = nc;
nc->prev = c;
nc->next = NULL;
}
}
// TODO
void wm_destroy_handler(XDestroyWindowEvent e)
{
Client *c;
// TODO: make function for linked list management
for (c = wm_smon->clients; c; c = c->next) {
if (e.window == c->wn) {
if (c == wm_smon->clients) {
if (c->next)
wm_smon->clients = c->next;
else
wm_smon->clients = NULL;
} else {
if (!c->next)
c->prev->next = NULL;
else {
c->prev->next = c->next;
c->next->prev = c->prev;
}
}
free(c);
}
}
}
void wm_reparent_handler(XReparentEvent e)
{
}
// TODO
void wm_configure_handler(XConfigureRequestEvent e)
{
Client *c;
XWindowChanges ch;
int cc_sws = 0;
for (c = wm_smon->clients; c; c = c->next) {
if (c->ws == wm_smon->selws) {
cc_sws++;
}
}
FIND_WINDOW(c, wm_smon, e.window)
// dynamic
if (cc_sws == 0) {
c->x = 0;
c->y = 0;
c->w = wm_smon->info.width;
c->h = wm_smon->info.height;
}
else {
// TODO
// c.x = m.h / cc_sws;
}
XConfigureWindow(wm_display, c->wn, e.value_mask, &ch);
}
void wm_map_handler(XMapRequestEvent e)
{
Client *c;
XMapWindow(wm_display, e.window);
FIND_WINDOW(c, wm_smon, e.window)
c->hidden = false;
}
// TODO
XWindowChanges wm_client_to_xwchanges(Client c)
{
XWindowChanges ch;
ch.x = c.x;
ch.y = c.y;
ch.width = c.w;
ch.height = c.h;
ch.border_width = 0;
ch.stack_mode = Above;
return ch;
}
void wm_create_client(Window w)
{
}
void wm_client_hide(Client *c)
{
if (c->hidden)
return;
c->hidden = true;
XUnmapWindow(wm_display, c->wn);
}
void wm_client_show(Client *c)
{
if (!c->hidden)
return;
c->hidden = false;
XMapWindow(wm_display, c->wn);
}
void wm_switch_ws(int ws)
{
if (ws > wm_smon->wscount)
return;
Client *c;
for (c = wm_smon->clients; c; c = c->next) {
if (c->ws == wm_smon->selws) {
wm_client_hide(c);
}
}
wm_smon->selws = ws;
for (c = wm_smon->clients; c; c = c->next) {
if (c->ws == wm_smon->selws) {
wm_client_show(c);
}
}
}
void wm_mainloop()
{
while (1) {
XEvent e;
XNextEvent(wm_display, &e);
switch (e.type) {
case CreateNotify:
wm_create_handler(e.xcreatewindow);
break;
case DestroyNotify:
wm_destroy_handler(e.xdestroywindow);
break;
case ReparentNotify:
wm_reparent_handler(e.xreparent);
break;
case ConfigureRequest:
wm_configure_handler(e.xconfigurerequest);
break;
}
}
}
void wm_init()
{
Display *d = wm_connect_display();
wm_display = d;
wm_monitors_open_all(d);
wm_root.wn = DefaultRootWindow(d);
wm_last_client = &wm_root;
XSetErrorHandler(&wm_other_wm_handler);
XSelectInput(d, wm_root.wn, SubstructureRedirectMask |
SubstructureNotifyMask);
XSync(d, false);
if (wm_other_wm) {
printf("wm: Detected other window manager. Exiting.\n");
exit(1);
}
XSetErrorHandler(&wm_xerror_handler);
wm_mainloop();
}

69
wm.h Normal file
View File

@ -0,0 +1,69 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xinerama.h>
#define LAST_WINDOW(c, smon) for (c = smon->clients; c; c = c->next) {}
#define FIND_WINDOW(c, smon, window) \
for (c = smon->clients; c; c = c->next) \
{ \
if (c->wn == window) { \
break; \
} \
}
typedef struct Client Client;
typedef struct Monitor Monitor;
struct Monitor {
Display *display;
XineramaScreenInfo info;
Client *clients;
int *wss;
int selws;
int wscount;
};
struct Client {
int x;
int y;
int w;
int h;
int ws;
bool hidden;
Monitor *m;
Window wn;
Client *prev;
Client *next;
// linked list is not sufficent for manual tiling.
// will propably need a tree.
};
static Display *wm_display;
static Monitor *wm_monitors;
static Monitor *wm_smon;
static int wm_mc;
static bool wm_other_wm;
static Client wm_root;
static Client *wm_last_client;
static int wm_xerror_handler(Display *display, XErrorEvent *e);
static int wm_other_wm_handler(Display *display, XErrorEvent *e);
void wm_create_handler(XCreateWindowEvent e);
void wm_destroy_handler(XDestroyWindowEvent e);
void wm_reparent_handler(XReparentEvent e);
void wm_configure_handler(XConfigureRequestEvent e);
void wm_map_handler(XMapRequestEvent e);
Monitor wm_monitor_open(Display *d, XineramaScreenInfo info);
void wm_monitors_open_all(Display *d);
Display* wm_connect_display();
XWindowChanges wm_client_to_xwchanges(Client c);
void wm_create_client(Window w);
void wm_client_hide(Client *c);
void wm_client_show(Client *c);
void wm_switch_ws(int ws);
void wm_mainloop();
void wm_init();