kind of works
This commit is contained in:
parent
5317e24c93
commit
9cb052fd7a
4 changed files with 236 additions and 41 deletions
|
|
@ -34,6 +34,7 @@ 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);
|
||||
void wm_focus(MwWidget widget, int focus);
|
||||
|
||||
/* config.c */
|
||||
extern config_t wm_config;
|
||||
|
|
|
|||
|
|
@ -14,15 +14,12 @@ Window: {
|
|||
"Iconify"
|
||||
];
|
||||
};
|
||||
Background: {
|
||||
# Just don't write anything if you want default background
|
||||
#Inactive: "white";
|
||||
Active: "blue";
|
||||
Active: {
|
||||
Background = "dark blue";
|
||||
Foreground = "white";
|
||||
};
|
||||
Foreground: {
|
||||
# Just don't write anything if you want default background
|
||||
#Inactive: "black";
|
||||
Active: "white";
|
||||
Inactive: {
|
||||
# Just don't write anything if you want default background/foreground
|
||||
};
|
||||
|
||||
# Left, Right, or Center
|
||||
|
|
|
|||
207
milkwm/wm.c
207
milkwm/wm.c
|
|
@ -1,14 +1,22 @@
|
|||
#define _MILSKO
|
||||
#include "milkwm.h"
|
||||
|
||||
#include <stb_ds.h>
|
||||
|
||||
static MwWidget root;
|
||||
|
||||
typedef struct wmframe {
|
||||
MwWidget titlebar;
|
||||
MwWidget title;
|
||||
|
||||
int left_space;
|
||||
int right_space;
|
||||
MwWidget* left;
|
||||
MwWidget* right;
|
||||
|
||||
MwLLPixmap maximize;
|
||||
MwLLPixmap iconify;
|
||||
|
||||
int dragging;
|
||||
MwPoint drag_point;
|
||||
} wmframe_t;
|
||||
|
||||
void loop_wm(void) {
|
||||
|
|
@ -42,6 +50,8 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
wmframe_t* f = handle->opaque;
|
||||
int ww = MwGetInteger(handle, MwNwidth);
|
||||
int wh = MwGetInteger(handle, MwNheight);
|
||||
int x;
|
||||
int i;
|
||||
|
||||
MwVaApply(f->titlebar,
|
||||
MwNx, MwDefaultBorderWidth(handle),
|
||||
|
|
@ -50,10 +60,26 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
MwNheight, TitleBarHeight + MwDefaultBorderWidth(handle) * 2,
|
||||
NULL);
|
||||
|
||||
x = MwDefaultBorderWidth(handle);
|
||||
for(i = 0; i < arrlen(f->left); i++) {
|
||||
MwVaApply(f->left[i],
|
||||
MwNx, x,
|
||||
NULL);
|
||||
x += TitleBarHeight;
|
||||
}
|
||||
|
||||
x = MwGetInteger(f->titlebar, MwNwidth) - MwDefaultBorderWidth(handle);
|
||||
for(i = 0; i < arrlen(f->right); i++) {
|
||||
x -= TitleBarHeight;
|
||||
MwVaApply(f->right[i],
|
||||
MwNx, x,
|
||||
NULL);
|
||||
}
|
||||
|
||||
MwVaApply(f->title,
|
||||
MwNx, MwDefaultBorderWidth(f->titlebar) + f->left_space + 8,
|
||||
MwNx, MwDefaultBorderWidth(f->titlebar) + arrlen(f->left) * TitleBarHeight,
|
||||
MwNy, MwDefaultBorderWidth(f->titlebar),
|
||||
MwNwidth, MwGetInteger(f->titlebar, MwNwidth) - MwDefaultBorderWidth(f->titlebar) * 2 - f->left_space - f->right_space - 16,
|
||||
MwNwidth, MwGetInteger(f->titlebar, MwNwidth) - MwDefaultBorderWidth(f->titlebar) * 2 - arrlen(f->left) * TitleBarHeight - arrlen(f->right) * TitleBarHeight,
|
||||
MwNheight, MwGetInteger(f->titlebar, MwNheight) - MwDefaultBorderWidth(f->titlebar) * 2,
|
||||
NULL);
|
||||
}
|
||||
|
|
@ -81,10 +107,88 @@ static void apply_config(MwWidget wnd) {
|
|||
}
|
||||
}
|
||||
|
||||
static void apply_button(MwWidget widget, const char* str) {
|
||||
MwWidget w = widget;
|
||||
wmframe_t* f;
|
||||
MwLLPixmap px = NULL;
|
||||
|
||||
while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w);
|
||||
|
||||
f = w->opaque;
|
||||
|
||||
if(strcmp(str, "Maximize") == 0) {
|
||||
px = f->maximize;
|
||||
} else if(strcmp(str, "Iconify") == 0) {
|
||||
px = f->iconify;
|
||||
}
|
||||
|
||||
if(px != NULL) {
|
||||
int p = (MwGetInteger(widget, MwNwidth) - MwDefaultBorderWidth(widget) * 2 - px->common.width) / 2;
|
||||
MwVaApply(widget,
|
||||
MwNpixmap, px,
|
||||
MwNpadding, p,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
static void drag_down(MwWidget handle, void* user, void* client) {
|
||||
MwWidget w = handle;
|
||||
wmframe_t* f;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
MwPoint c;
|
||||
|
||||
while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w);
|
||||
x += MwGetInteger(w, MwNx);
|
||||
y += MwGetInteger(w, MwNy);
|
||||
|
||||
f = w->opaque;
|
||||
|
||||
MwGetCursorCoord(w, &c);
|
||||
|
||||
f->dragging = 1;
|
||||
f->drag_point.x = c.x - x;
|
||||
f->drag_point.y = c.y - y;
|
||||
}
|
||||
|
||||
static void drag_up(MwWidget handle, void* user, void* client) {
|
||||
MwWidget w = handle;
|
||||
wmframe_t* f;
|
||||
|
||||
while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w);
|
||||
|
||||
f = w->opaque;
|
||||
|
||||
f->dragging = 0;
|
||||
}
|
||||
|
||||
static void drag(MwWidget handle, void* user, void* client) {
|
||||
MwWidget w = handle;
|
||||
wmframe_t* f;
|
||||
|
||||
while(w != NULL && strcmp(MwGetName(w), "frame") != 0) w = MwGetParent(w);
|
||||
|
||||
f = w->opaque;
|
||||
|
||||
if(f->dragging) {
|
||||
MwPoint c;
|
||||
|
||||
MwGetCursorCoord(w, &c);
|
||||
|
||||
MwVaApply(w,
|
||||
MwNx, c.x - f->drag_point.x,
|
||||
MwNy, c.y - f->drag_point.y,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
MwWidget wm_frame(int w, int h) {
|
||||
MwWidget wnd, titlebar;
|
||||
int i;
|
||||
wmframe_t* f = malloc(sizeof(*f));
|
||||
MwWidget wnd, titlebar;
|
||||
int i;
|
||||
config_setting_t* s;
|
||||
const char* str;
|
||||
wmframe_t* f = malloc(sizeof(*f));
|
||||
unsigned char* icon;
|
||||
int y, x;
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
|
||||
|
|
@ -94,17 +198,66 @@ MwWidget wm_frame(int w, int h) {
|
|||
NULL);
|
||||
wnd->opaque = f;
|
||||
|
||||
f->left_space = TitleBarHeight;
|
||||
f->right_space = 0;
|
||||
MwAddUserHandler(wnd, MwNresizeHandler, resize, NULL);
|
||||
|
||||
f->dragging = 0;
|
||||
|
||||
icon = malloc(6 * 6 * 4);
|
||||
|
||||
memset(icon, 0, 6 * 6 * 4);
|
||||
for(y = 0; y < 6; y++) {
|
||||
for(x = 0; x < 6; x++) {
|
||||
if((y == 0 || y == 5 || x == 0 || x == 5) && !(2 <= y && y <= 3) && !(2 <= x && x <= 3)) icon[(y * 6 + x) * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
f->iconify = MwLoadRaw(wnd, icon, 6, 6);
|
||||
|
||||
memset(icon, 0, 6 * 6 * 4);
|
||||
for(y = 0; y < 6; y++) {
|
||||
for(x = 0; x < 6; x++) {
|
||||
if(y == 0 || y == 5 || x == 0 || x == 5) icon[(y * 6 + x) * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
f->maximize = MwLoadRaw(wnd, icon, 6, 6);
|
||||
free(icon);
|
||||
|
||||
f->left = NULL;
|
||||
f->right = NULL;
|
||||
|
||||
f->titlebar = MwVaCreateWidget(MwFrameClass, "titlebar", wnd, 0, 0, 0, 0,
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 1,
|
||||
NULL);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseUpHandler, drag_up, NULL);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseMoveHandler, drag, NULL);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseDownHandler, drag_down, NULL);
|
||||
|
||||
f->title = MwCreateWidget(MwLabelClass, "title", f->titlebar, 0, 0, 0, 0);
|
||||
MwAddUserHandler(f->title, MwNmouseUpHandler, drag_up, NULL);
|
||||
MwAddUserHandler(f->title, MwNmouseMoveHandler, drag, NULL);
|
||||
MwAddUserHandler(f->title, MwNmouseDownHandler, drag_down, NULL);
|
||||
|
||||
MwCreateWidget(MwButtonClass, "button", f->titlebar, MwDefaultBorderWidth(wnd), MwDefaultBorderWidth(wnd), TitleBarHeight, TitleBarHeight);
|
||||
s = config_lookup(&wm_config, "Window.TitleBar.Buttons.Left");
|
||||
for(i = 0; (str = config_setting_get_string_elem(s, i)) != NULL; i++) {
|
||||
MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, MwDefaultBorderWidth(wnd), TitleBarHeight, TitleBarHeight,
|
||||
MwNborderWidth, 1,
|
||||
NULL);
|
||||
|
||||
apply_button(w, str);
|
||||
|
||||
arrput(f->left, w);
|
||||
}
|
||||
|
||||
s = config_lookup(&wm_config, "Window.TitleBar.Buttons.Right");
|
||||
for(i = 0; (str = config_setting_get_string_elem(s, i)) != NULL; i++) {
|
||||
MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, MwDefaultBorderWidth(wnd), TitleBarHeight, TitleBarHeight,
|
||||
MwNborderWidth, 1,
|
||||
NULL);
|
||||
|
||||
apply_button(w, str);
|
||||
|
||||
arrput(f->right, w);
|
||||
}
|
||||
|
||||
apply_config(wnd);
|
||||
|
||||
|
|
@ -116,7 +269,14 @@ MwWidget wm_frame(int w, int h) {
|
|||
}
|
||||
|
||||
void wm_destroy(MwWidget widget) {
|
||||
wmframe_t* f = widget->opaque;
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
arrfree(f->left);
|
||||
arrfree(f->right);
|
||||
|
||||
MwLLDestroyPixmap(f->maximize);
|
||||
MwLLDestroyPixmap(f->iconify);
|
||||
free(widget->opaque);
|
||||
MwDestroyWidget(widget);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
|
|
@ -124,10 +284,35 @@ void wm_destroy(MwWidget widget) {
|
|||
|
||||
void wm_set_name(MwWidget widget, const char* name) {
|
||||
wmframe_t* f = widget->opaque;
|
||||
char* s = MDEStringConcatenate(" ", name);
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
MwVaApply(f->title,
|
||||
MwNtext, name,
|
||||
MwNtext, s,
|
||||
NULL);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
void wm_focus(MwWidget widget, int focus) {
|
||||
wmframe_t* f = widget->opaque;
|
||||
const char* bg = NULL;
|
||||
const char* fg = NULL;
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
if(focus) {
|
||||
config_lookup_string(&wm_config, "Window.TitleBar.Active.Background", &bg);
|
||||
config_lookup_string(&wm_config, "Window.TitleBar.Active.Foreground", &fg);
|
||||
} else {
|
||||
config_lookup_string(&wm_config, "Window.TitleBar.Inactive.Background", &bg);
|
||||
config_lookup_string(&wm_config, "Window.TitleBar.Inactive.Foreground", &fg);
|
||||
}
|
||||
|
||||
MwVaApply(f->title,
|
||||
MwNbackground, bg,
|
||||
MwNforeground, fg,
|
||||
NULL);
|
||||
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@ Display* xdisplay;
|
|||
pthread_t xthread;
|
||||
pthread_mutex_t xmutex;
|
||||
|
||||
typedef struct window {
|
||||
MwWidget frame;
|
||||
Window client;
|
||||
} window_t;
|
||||
static window_t* windows = NULL;
|
||||
|
||||
static void* old_handler;
|
||||
static int error_happened = 0;
|
||||
static int ignore_error(Display* disp, XErrorEvent* ev) {
|
||||
|
|
@ -32,13 +38,23 @@ static void* x11_thread_routine(void* arg) {
|
|||
}
|
||||
|
||||
static Window focus = None, nofocus;
|
||||
static void set_focus(Window w) {
|
||||
if(w == None) {
|
||||
XSetInputFocus(xdisplay, nofocus, RevertToParent, CurrentTime);
|
||||
} else {
|
||||
XSetInputFocus(xdisplay, w, RevertToParent, CurrentTime);
|
||||
}
|
||||
focus = w;
|
||||
|
||||
static void set_focus(Window w) {
|
||||
int i;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].client == w) {
|
||||
wm_focus(windows[i].frame, 1);
|
||||
} else if(focus == windows[i].client) {
|
||||
wm_focus(windows[i].frame, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(w == None) {
|
||||
XSetInputFocus(xdisplay, nofocus, RevertToParent, CurrentTime);
|
||||
} else {
|
||||
XSetInputFocus(xdisplay, w, RevertToParent, CurrentTime);
|
||||
}
|
||||
focus = w;
|
||||
}
|
||||
|
||||
int init_x(void) {
|
||||
|
|
@ -71,12 +87,6 @@ int init_x(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef struct window {
|
||||
MwWidget frame;
|
||||
Window client;
|
||||
} window_t;
|
||||
static window_t* windows = NULL;
|
||||
|
||||
static void save(Window w) {
|
||||
XSelectInput(xdisplay, w, StructureNotifyMask | FocusChangeMask | PropertyChangeMask);
|
||||
XSetWindowBorderWidth(xdisplay, w, 0);
|
||||
|
|
@ -100,13 +110,13 @@ static void set_name(Window wnd) {
|
|||
Atom type;
|
||||
int format;
|
||||
unsigned long nitem, after;
|
||||
unsigned char* buf;
|
||||
unsigned char* buf = NULL;
|
||||
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) {
|
||||
if(XGetWindowProperty(xdisplay, wnd, atom, 0, 1024, False, XA_STRING, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
|
||||
wm_set_name(windows[i].frame, buf);
|
||||
XFree(buf);
|
||||
}
|
||||
|
|
@ -169,8 +179,13 @@ void loop_x(void) {
|
|||
int i;
|
||||
Window w = ev.xconfigurerequest.window;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].client == w) {
|
||||
w = windows[i].frame->lowlevel->x11.window;
|
||||
if(windows[i].frame->lowlevel->x11.window == w) {
|
||||
xwc.x = ev.xconfigurerequest.x;
|
||||
xwc.y = ev.xconfigurerequest.y;
|
||||
xwc.width = ev.xconfigurerequest.width - MwDefaultBorderWidth(windows[i].frame) * 2;
|
||||
xwc.height = ev.xconfigurerequest.height - MwDefaultBorderWidth(windows[i].frame) * 4 - TitleBarHeight;
|
||||
|
||||
XConfigureWindow(xdisplay, windows[i].client, CWX | CWY | CWWidth | CWHeight, &xwc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +202,7 @@ void loop_x(void) {
|
|||
if(windows[i].client == ev.xconfigure.window) {
|
||||
XWindowChanges xwc;
|
||||
XWindowAttributes xwa;
|
||||
|
||||
xwc.x = ev.xconfigure.x;
|
||||
xwc.y = ev.xconfigure.y;
|
||||
xwc.width = MwDefaultBorderWidth(windows[i].frame) * 2 + ev.xconfigure.width;
|
||||
|
|
@ -203,6 +219,7 @@ void loop_x(void) {
|
|||
} else if(xwa.width != xwc.width || xwa.height != xwc.height) {
|
||||
XConfigureWindow(xdisplay, windows[i].frame->lowlevel->x11.window, CWWidth | CWHeight, &xwc);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -234,14 +251,11 @@ void loop_x(void) {
|
|||
XMoveWindow(xdisplay, windows[i].frame->lowlevel->x11.window, xwa.x, xwa.y);
|
||||
|
||||
XMapWindow(xdisplay, ev.xmaprequest.window);
|
||||
pthread_mutex_lock(&xmutex);
|
||||
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);
|
||||
if(!XMapWindow(xdisplay, windows[i].client)) {
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
|
|
@ -285,9 +299,7 @@ void loop_x(void) {
|
|||
XWindowAttributes xwa;
|
||||
|
||||
if(XGetWindowAttributes(xdisplay, windows[i].frame->lowlevel->x11.window, &xwa)) {
|
||||
pthread_mutex_lock(&xmutex);
|
||||
XReparentWindow(xdisplay, windows[i].client, DefaultRootWindow(xdisplay), xwa.x, xwa.y);
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
}
|
||||
|
||||
wm_destroy(windows[i].frame);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue