create basics
This commit is contained in:
parent
cd189fd54c
commit
b6132f82fa
276
wm.c
Normal file
276
wm.c
Normal 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
69
wm.h
Normal 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();
|
Loading…
x
Reference in New Issue
Block a user