sorta works
This commit is contained in:
parent
59f81d9eb4
commit
61cecbd7ee
7 changed files with 187 additions and 36 deletions
|
|
@ -15,5 +15,5 @@ static int dumper(void* user, const char* section, const char* name, const char*
|
|||
}
|
||||
|
||||
void parse_config(void) {
|
||||
ini_parse(CONFDIR "/mdm/mdmrc", dumper, NULL);
|
||||
ini_parse(SYSCONFDIR "/mdm/mdmrc", dumper, NULL);
|
||||
}
|
||||
|
|
|
|||
30
milkwm/config.c
Normal file
30
milkwm/config.c
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#include "milkwm.h"
|
||||
|
||||
/* we prefix them for reasons */
|
||||
|
||||
config_t wm_config;
|
||||
|
||||
void wm_config_init(void) {
|
||||
config_init(&wm_config);
|
||||
}
|
||||
|
||||
static void read_config(const char* path) {
|
||||
if(!config_read_file(&wm_config, path)) {
|
||||
fprintf(stderr, "MilkWM config error: file %s at line %d: %s\n", path, config_error_line(&wm_config), config_error_text(&wm_config));
|
||||
}
|
||||
}
|
||||
|
||||
void wm_config_read(void) {
|
||||
char* conf = MDEDirectoryConfigPath();
|
||||
char* dir = MwDirectoryJoin(conf, "milkwm");
|
||||
char* path = MwDirectoryJoin(dir, "milkwmrc");
|
||||
|
||||
free(dir);
|
||||
free(conf);
|
||||
|
||||
config_clear(&wm_config);
|
||||
read_config(SYSCONFDIR "/milkwm/milkwmrc");
|
||||
read_config(path);
|
||||
|
||||
free(path);
|
||||
}
|
||||
|
|
@ -3,6 +3,9 @@
|
|||
int main() {
|
||||
int st;
|
||||
|
||||
wm_config_init();
|
||||
wm_config_read();
|
||||
|
||||
if((st = init_x()) != 0) return st;
|
||||
|
||||
loop_wm();
|
||||
|
|
|
|||
|
|
@ -8,11 +8,15 @@
|
|||
#include <Mw/Milsko.h>
|
||||
|
||||
/* External */
|
||||
#include <libconfig.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
/* Standard */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define TitleBarHeight 16
|
||||
|
|
@ -28,6 +32,13 @@ void loop_x(void);
|
|||
/* wm.c */
|
||||
void loop_wm(void);
|
||||
MwWidget wm_frame(int w, int h);
|
||||
void wm_destroy(MwWidget widget);
|
||||
void wm_set_name(MwWidget widget, const char* name);
|
||||
|
||||
/* config.c */
|
||||
extern config_t wm_config;
|
||||
|
||||
void wm_config_init(void);
|
||||
void wm_config_read(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# This file should be copied to .config/milkwm/milkwmrc
|
||||
|
||||
Window: {
|
||||
TitleBar: {
|
||||
Buttons: {
|
||||
|
|
@ -12,5 +14,19 @@ Window: {
|
|||
"Iconify"
|
||||
];
|
||||
};
|
||||
Background: {
|
||||
# Just don't write anything if you want default background
|
||||
#Inactive: "white";
|
||||
Active: "blue";
|
||||
};
|
||||
Foreground: {
|
||||
# Just don't write anything if you want default background
|
||||
#Inactive: "black";
|
||||
Active: "white";
|
||||
};
|
||||
|
||||
# Left, Right, or Center
|
||||
# Default is Center
|
||||
Align = "Left";
|
||||
};
|
||||
};
|
||||
|
|
|
|||
57
milkwm/wm.c
57
milkwm/wm.c
|
|
@ -5,6 +5,10 @@ static MwWidget root;
|
|||
|
||||
typedef struct wmframe {
|
||||
MwWidget titlebar;
|
||||
MwWidget title;
|
||||
|
||||
int left_space;
|
||||
int right_space;
|
||||
} wmframe_t;
|
||||
|
||||
void loop_wm(void) {
|
||||
|
|
@ -45,6 +49,36 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
MwNwidth, ww - MwDefaultBorderWidth(handle) * 2,
|
||||
MwNheight, TitleBarHeight + MwDefaultBorderWidth(handle) * 2,
|
||||
NULL);
|
||||
|
||||
MwVaApply(f->title,
|
||||
MwNx, MwDefaultBorderWidth(f->titlebar) + f->left_space + 8,
|
||||
MwNy, MwDefaultBorderWidth(f->titlebar),
|
||||
MwNwidth, MwGetInteger(f->titlebar, MwNwidth) - MwDefaultBorderWidth(f->titlebar) * 2 - f->left_space - f->right_space - 16,
|
||||
MwNheight, MwGetInteger(f->titlebar, MwNheight) - MwDefaultBorderWidth(f->titlebar) * 2,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int alignment(const char* str) {
|
||||
if(strcmp(str, "Left") == 0) return MwALIGNMENT_BEGINNING;
|
||||
if(strcmp(str, "Right") == 0) return MwALIGNMENT_END;
|
||||
if(strcmp(str, "Center") == 0) return MwALIGNMENT_CENTER;
|
||||
|
||||
return MwALIGNMENT_CENTER;
|
||||
}
|
||||
|
||||
static void apply_config(MwWidget wnd) {
|
||||
wmframe_t* f = wnd->opaque;
|
||||
const char* str;
|
||||
|
||||
if(config_lookup_string(&wm_config, "Window.TitleBar.Align", &str)) {
|
||||
MwVaApply(f->title,
|
||||
MwNalignment, alignment(str),
|
||||
NULL);
|
||||
} else {
|
||||
MwVaApply(f->title,
|
||||
MwNalignment, MwALIGNMENT_CENTER,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
MwWidget wm_frame(int w, int h) {
|
||||
|
|
@ -60,13 +94,20 @@ MwWidget wm_frame(int w, int h) {
|
|||
NULL);
|
||||
wnd->opaque = f;
|
||||
|
||||
f->left_space = TitleBarHeight;
|
||||
f->right_space = 0;
|
||||
|
||||
f->titlebar = MwVaCreateWidget(MwFrameClass, "titlebar", wnd, 0, 0, 0, 0,
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 1,
|
||||
NULL);
|
||||
|
||||
f->title = MwCreateWidget(MwLabelClass, "title", f->titlebar, 0, 0, 0, 0);
|
||||
|
||||
MwCreateWidget(MwButtonClass, "button", f->titlebar, MwDefaultBorderWidth(wnd), MwDefaultBorderWidth(wnd), TitleBarHeight, TitleBarHeight);
|
||||
|
||||
apply_config(wnd);
|
||||
|
||||
resize(wnd, NULL, NULL);
|
||||
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
|
|
@ -74,5 +115,19 @@ MwWidget wm_frame(int w, int h) {
|
|||
return wnd;
|
||||
}
|
||||
|
||||
void wm_set_name(MwWidget widget, const char* name) {
|
||||
void wm_destroy(MwWidget widget) {
|
||||
pthread_mutex_lock(&xmutex);
|
||||
free(widget->opaque);
|
||||
MwDestroyWidget(widget);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
}
|
||||
|
||||
void wm_set_name(MwWidget widget, const char* name) {
|
||||
wmframe_t* f = widget->opaque;
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
MwVaApply(f->title,
|
||||
MwNtext, name,
|
||||
NULL);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
}
|
||||
|
|
|
|||
106
milkwm/xserver.c
106
milkwm/xserver.c
|
|
@ -8,12 +8,21 @@ Display* xdisplay;
|
|||
pthread_t xthread;
|
||||
pthread_mutex_t xmutex;
|
||||
|
||||
static int wm_detected = 0;
|
||||
static int wm_detect(Display* disp, XErrorEvent* ev) {
|
||||
wm_detected = 1;
|
||||
static void* old_handler;
|
||||
static int error_happened = 0;
|
||||
static int ignore_error(Display* disp, XErrorEvent* ev) {
|
||||
error_happened = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ignore_error(Display* disp, XErrorEvent* ev) {
|
||||
static void begin_error(void) {
|
||||
old_handler = XSetErrorHandler(ignore_error);
|
||||
error_happened = 0;
|
||||
}
|
||||
|
||||
static void end_error(void) {
|
||||
XSync(xdisplay, False);
|
||||
XSetErrorHandler(old_handler);
|
||||
}
|
||||
|
||||
static void* x11_thread_routine(void* arg) {
|
||||
|
|
@ -40,12 +49,11 @@ int init_x(void) {
|
|||
|
||||
xdisplay = XOpenDisplay(NULL);
|
||||
|
||||
old = XSetErrorHandler(wm_detect);
|
||||
begin_error();
|
||||
XSelectInput(xdisplay, DefaultRootWindow(xdisplay), SubstructureRedirectMask);
|
||||
XSync(xdisplay, False);
|
||||
XSetErrorHandler(old);
|
||||
end_error();
|
||||
|
||||
if(wm_detected) return 1;
|
||||
if(error_happened) return 1;
|
||||
|
||||
nofocus = XCreateSimpleWindow(xdisplay, DefaultRootWindow(xdisplay), -10, -10, 1, 1, 0, 0, 0);
|
||||
XChangeWindowAttributes(xdisplay, nofocus, CWOverrideRedirect, &xswa);
|
||||
|
|
@ -75,7 +83,7 @@ static void save(Window w) {
|
|||
XAddToSaveSet(xdisplay, w);
|
||||
}
|
||||
|
||||
int parent_eq(Window wnd, Window might_be_parent) {
|
||||
static int parent_eq(Window wnd, Window might_be_parent) {
|
||||
Window root, parent;
|
||||
Window* children;
|
||||
unsigned int nchildren;
|
||||
|
|
@ -88,6 +96,24 @@ int parent_eq(Window wnd, Window might_be_parent) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void set_name(Window wnd) {
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitem, after;
|
||||
unsigned char* buf;
|
||||
Atom atom = XInternAtom(xdisplay, "WM_NAME", False);
|
||||
int i;
|
||||
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].client == wnd) {
|
||||
if(XGetWindowProperty(xdisplay, wnd, atom, 0, 1024, False, XA_STRING, &type, &format, &nitem, &after, &buf) == Success) {
|
||||
wm_set_name(windows[i].frame, buf);
|
||||
XFree(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop_x(void) {
|
||||
XEvent ev;
|
||||
Window root, parent;
|
||||
|
|
@ -95,23 +121,28 @@ void loop_x(void) {
|
|||
unsigned int nchildren;
|
||||
int i;
|
||||
|
||||
begin_error();
|
||||
|
||||
XQueryTree(xdisplay, DefaultRootWindow(xdisplay), &root, &parent, &children, &nchildren);
|
||||
if(children != NULL) {
|
||||
for(i = 0; i < nchildren; i++) {
|
||||
window_t w;
|
||||
XWindowAttributes xwa;
|
||||
|
||||
XGetWindowAttributes(xdisplay, children[i], &xwa);
|
||||
if(xwa.override_redirect || xwa.map_state != IsViewable) continue;
|
||||
if(XGetWindowAttributes(xdisplay, children[i], &xwa)) {
|
||||
if(xwa.override_redirect || xwa.map_state != IsViewable) continue;
|
||||
|
||||
w.frame = wm_frame(xwa.width, xwa.height);
|
||||
w.client = children[i];
|
||||
w.frame = wm_frame(xwa.width, xwa.height);
|
||||
w.client = children[i];
|
||||
|
||||
XUnmapWindow(xdisplay, children[i]);
|
||||
XUnmapWindow(xdisplay, children[i]);
|
||||
|
||||
save(w.client);
|
||||
save(w.client);
|
||||
|
||||
arrput(windows, w);
|
||||
arrput(windows, w);
|
||||
|
||||
set_name(w.client);
|
||||
}
|
||||
}
|
||||
XFree(children);
|
||||
}
|
||||
|
|
@ -181,11 +212,12 @@ void loop_x(void) {
|
|||
int ret = 0;
|
||||
XWindowAttributes xwa;
|
||||
|
||||
XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa);
|
||||
if(!XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa)) continue;
|
||||
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].frame->lowlevel->x11.window == ev.xmaprequest.window) break;
|
||||
if(windows[i].client == ev.xmaprequest.window) {
|
||||
/* what? */
|
||||
ret = 1;
|
||||
break;
|
||||
}
|
||||
|
|
@ -193,15 +225,28 @@ void loop_x(void) {
|
|||
if(ret) continue;
|
||||
if(i != arrlen(windows)) {
|
||||
XWindowAttributes xwa;
|
||||
XGetWindowAttributes(xdisplay, windows[i].client, &xwa);
|
||||
if(!XGetWindowAttributes(xdisplay, windows[i].client, &xwa)) {
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
XMoveWindow(xdisplay, windows[i].frame->lowlevel->x11.window, xwa.x, xwa.y);
|
||||
|
||||
XMapWindow(xdisplay, ev.xmaprequest.window);
|
||||
pthread_mutex_lock(&xmutex);
|
||||
XReparentWindow(xdisplay, windows[i].client, windows[i].frame->lowlevel->x11.window, MwDefaultBorderWidth(windows[i].frame), MwDefaultBorderWidth(windows[i].frame) * 3 + TitleBarHeight);
|
||||
if(!XReparentWindow(xdisplay, windows[i].client, windows[i].frame->lowlevel->x11.window, MwDefaultBorderWidth(windows[i].frame), MwDefaultBorderWidth(windows[i].frame) * 3 + TitleBarHeight)) {
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
continue;
|
||||
}
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
XMapWindow(xdisplay, windows[i].client);
|
||||
if(!XMapWindow(xdisplay, windows[i].client)) {
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
continue;
|
||||
}
|
||||
XFlush(xdisplay);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -211,6 +256,8 @@ void loop_x(void) {
|
|||
save(w.client);
|
||||
|
||||
arrput(windows, w);
|
||||
|
||||
set_name(w.client);
|
||||
} else if(ev.type == PropertyNotify) {
|
||||
int i;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
|
|
@ -221,15 +268,7 @@ void loop_x(void) {
|
|||
if(arrlen(windows) == i) continue;
|
||||
|
||||
if(ev.xproperty.atom == XInternAtom(xdisplay, "WM_NAME", False)) {
|
||||
Atom type;
|
||||
int format;
|
||||
unsigned long nitem, after;
|
||||
unsigned char* buf;
|
||||
|
||||
if(XGetWindowProperty(xdisplay, ev.xproperty.window, ev.xproperty.atom, 0, 1024, False, XA_STRING, &type, &format, &nitem, &after, &buf) == Success) {
|
||||
wm_set_name(windows[i].frame, buf);
|
||||
XFree(buf);
|
||||
}
|
||||
set_name(windows[i].client);
|
||||
}
|
||||
} else if(ev.type == MapNotify) {
|
||||
int i;
|
||||
|
|
@ -243,19 +282,15 @@ void loop_x(void) {
|
|||
int i;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].client == ev.xunmap.window) {
|
||||
void* old;
|
||||
XWindowAttributes xwa;
|
||||
|
||||
XGetWindowAttributes(xdisplay, windows[i].frame->lowlevel->x11.window, &xwa);
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
old = XSetErrorHandler(ignore_error);
|
||||
XReparentWindow(xdisplay, windows[i].client, DefaultRootWindow(xdisplay), xwa.x, xwa.y);
|
||||
XSync(xdisplay, False);
|
||||
XSetErrorHandler(old);
|
||||
|
||||
MwDestroyWidget(windows[i].frame);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
break;
|
||||
}
|
||||
|
|
@ -278,4 +313,5 @@ void loop_x(void) {
|
|||
}
|
||||
}
|
||||
}
|
||||
end_error();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue