can move window and stuff
This commit is contained in:
parent
9cb052fd7a
commit
c271de7e52
3 changed files with 144 additions and 29 deletions
|
|
@ -20,6 +20,7 @@
|
|||
#include <pthread.h>
|
||||
|
||||
#define TitleBarHeight 16
|
||||
#define Gap 1
|
||||
|
||||
/* xserver.c */
|
||||
extern pthread_t xthread;
|
||||
|
|
@ -28,6 +29,7 @@ extern Display* xdisplay;
|
|||
|
||||
int init_x(void);
|
||||
void loop_x(void);
|
||||
void set_focus_x(MwWidget widget);
|
||||
|
||||
/* wm.c */
|
||||
void loop_wm(void);
|
||||
|
|
@ -35,6 +37,13 @@ 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);
|
||||
MwWidget wm_get_inside(MwWidget widget); /* make client area child of this widget, at (wm_content_x(),wm_content_y) */
|
||||
int wm_entire_width(int content);
|
||||
int wm_entire_height(int content);
|
||||
int wm_content_width(int entire);
|
||||
int wm_content_height(int entire);
|
||||
int wm_content_x(void);
|
||||
int wm_content_y(void);
|
||||
|
||||
/* config.c */
|
||||
extern config_t wm_config;
|
||||
|
|
|
|||
74
milkwm/wm.c
74
milkwm/wm.c
|
|
@ -6,6 +6,7 @@
|
|||
static MwWidget root;
|
||||
|
||||
typedef struct wmframe {
|
||||
MwWidget inside;
|
||||
MwWidget titlebar;
|
||||
MwWidget title;
|
||||
|
||||
|
|
@ -53,14 +54,19 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
int x;
|
||||
int i;
|
||||
|
||||
MwVaApply(f->inside,
|
||||
MwNwidth, ww - MwDefaultBorderWidth(handle) * 2 - Gap * 2,
|
||||
MwNheight, wh - MwDefaultBorderWidth(handle) * 2 - Gap * 2,
|
||||
NULL);
|
||||
|
||||
MwVaApply(f->titlebar,
|
||||
MwNx, MwDefaultBorderWidth(handle),
|
||||
MwNy, MwDefaultBorderWidth(handle),
|
||||
MwNwidth, ww - MwDefaultBorderWidth(handle) * 2,
|
||||
MwNheight, TitleBarHeight + MwDefaultBorderWidth(handle) * 2,
|
||||
MwNwidth, ww - MwDefaultBorderWidth(handle) * 4 - Gap * 2,
|
||||
MwNheight, TitleBarHeight,
|
||||
NULL);
|
||||
|
||||
x = MwDefaultBorderWidth(handle);
|
||||
x = 0;
|
||||
for(i = 0; i < arrlen(f->left); i++) {
|
||||
MwVaApply(f->left[i],
|
||||
MwNx, x,
|
||||
|
|
@ -68,7 +74,7 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
x += TitleBarHeight;
|
||||
}
|
||||
|
||||
x = MwGetInteger(f->titlebar, MwNwidth) - MwDefaultBorderWidth(handle);
|
||||
x = MwGetInteger(f->titlebar, MwNwidth);
|
||||
for(i = 0; i < arrlen(f->right); i++) {
|
||||
x -= TitleBarHeight;
|
||||
MwVaApply(f->right[i],
|
||||
|
|
@ -77,10 +83,10 @@ static void resize(MwWidget handle, void* user, void* client) {
|
|||
}
|
||||
|
||||
MwVaApply(f->title,
|
||||
MwNx, MwDefaultBorderWidth(f->titlebar) + arrlen(f->left) * TitleBarHeight,
|
||||
MwNy, MwDefaultBorderWidth(f->titlebar),
|
||||
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,
|
||||
MwNx, arrlen(f->left) * TitleBarHeight,
|
||||
MwNy, 0,
|
||||
MwNwidth, MwGetInteger(f->titlebar, MwNwidth) - arrlen(f->left) * TitleBarHeight - arrlen(f->right) * TitleBarHeight,
|
||||
MwNheight, MwGetInteger(f->titlebar, MwNheight),
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
@ -148,6 +154,8 @@ static void drag_down(MwWidget handle, void* user, void* client) {
|
|||
f->dragging = 1;
|
||||
f->drag_point.x = c.x - x;
|
||||
f->drag_point.y = c.y - y;
|
||||
|
||||
set_focus_x(w);
|
||||
}
|
||||
|
||||
static void drag_up(MwWidget handle, void* user, void* client) {
|
||||
|
|
@ -192,7 +200,7 @@ MwWidget wm_frame(int w, int h) {
|
|||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
|
||||
wnd = MwVaCreateWidget(MwWindowClass, "frame", root, MwDEFAULT, MwDEFAULT, w + MwDefaultBorderWidth(root) * 2, h + MwDefaultBorderWidth(root) * 4 + TitleBarHeight,
|
||||
wnd = MwVaCreateWidget(MwWindowClass, "frame", root, MwDEFAULT, MwDEFAULT, wm_entire_width(w), wm_entire_height(h),
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 0,
|
||||
NULL);
|
||||
|
|
@ -224,10 +232,12 @@ MwWidget wm_frame(int w, int h) {
|
|||
f->left = NULL;
|
||||
f->right = NULL;
|
||||
|
||||
f->titlebar = MwVaCreateWidget(MwFrameClass, "titlebar", wnd, 0, 0, 0, 0,
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 1,
|
||||
NULL);
|
||||
f->inside = MwVaCreateWidget(MwFrameClass, "inside", wnd, MwDefaultBorderWidth(wnd) + Gap, MwDefaultBorderWidth(wnd) + Gap, 0, 0,
|
||||
MwNhasBorder, 1,
|
||||
MwNinverted, 1,
|
||||
NULL);
|
||||
|
||||
f->titlebar = MwCreateWidget(MwFrameClass, "titlebar", f->inside, 0, 0, 0, 0);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseUpHandler, drag_up, NULL);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseMoveHandler, drag, NULL);
|
||||
MwAddUserHandler(f->titlebar, MwNmouseDownHandler, drag_down, NULL);
|
||||
|
|
@ -239,7 +249,7 @@ MwWidget wm_frame(int w, int h) {
|
|||
|
||||
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,
|
||||
MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, 0, TitleBarHeight, TitleBarHeight,
|
||||
MwNborderWidth, 1,
|
||||
NULL);
|
||||
|
||||
|
|
@ -250,7 +260,7 @@ MwWidget wm_frame(int w, int h) {
|
|||
|
||||
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,
|
||||
MwWidget w = MwVaCreateWidget(MwButtonClass, "button", f->titlebar, 0, 0, TitleBarHeight, TitleBarHeight,
|
||||
MwNborderWidth, 1,
|
||||
NULL);
|
||||
|
||||
|
|
@ -316,3 +326,37 @@ void wm_focus(MwWidget widget, int focus) {
|
|||
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
}
|
||||
|
||||
MwWidget wm_get_inside(MwWidget widget) {
|
||||
MwWidget ret;
|
||||
|
||||
pthread_mutex_lock(&xmutex);
|
||||
ret = ((wmframe_t*)widget->opaque)->inside;
|
||||
pthread_mutex_unlock(&xmutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wm_entire_width(int content) {
|
||||
return content + MwDefaultBorderWidth(root) * 4 + Gap * 2;
|
||||
}
|
||||
|
||||
int wm_entire_height(int content) {
|
||||
return content + MwDefaultBorderWidth(root) * 4 + Gap * 2 + TitleBarHeight;
|
||||
}
|
||||
|
||||
int wm_content_width(int entire) {
|
||||
return entire - wm_entire_width(0);
|
||||
}
|
||||
|
||||
int wm_content_height(int entire) {
|
||||
return entire - wm_entire_height(0);
|
||||
}
|
||||
|
||||
int wm_content_x(void) {
|
||||
return MwDefaultBorderWidth(root);
|
||||
}
|
||||
|
||||
int wm_content_y(void) {
|
||||
return MwDefaultBorderWidth(root) + TitleBarHeight;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ Display* xdisplay;
|
|||
pthread_t xthread;
|
||||
pthread_mutex_t xmutex;
|
||||
|
||||
static pthread_mutex_t focusmutex;
|
||||
|
||||
static Atom milkwm_set_focus;
|
||||
|
||||
typedef struct window {
|
||||
MwWidget frame;
|
||||
Window client;
|
||||
|
|
@ -42,19 +46,26 @@ static Window focus = None, nofocus;
|
|||
static void set_focus(Window w) {
|
||||
int i;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
pthread_mutex_lock(&focusmutex);
|
||||
if(windows[i].client == w) {
|
||||
pthread_mutex_unlock(&focusmutex);
|
||||
wm_focus(windows[i].frame, 1);
|
||||
} else if(focus == windows[i].client) {
|
||||
} else if(focus != w && focus == windows[i].client) {
|
||||
pthread_mutex_unlock(&focusmutex);
|
||||
wm_focus(windows[i].frame, 0);
|
||||
} else {
|
||||
pthread_mutex_unlock(&focusmutex);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&focusmutex);
|
||||
focus = w;
|
||||
if(w == None) {
|
||||
XSetInputFocus(xdisplay, nofocus, RevertToParent, CurrentTime);
|
||||
} else {
|
||||
XSetInputFocus(xdisplay, w, RevertToParent, CurrentTime);
|
||||
}
|
||||
focus = w;
|
||||
pthread_mutex_unlock(&focusmutex);
|
||||
}
|
||||
|
||||
int init_x(void) {
|
||||
|
|
@ -80,7 +91,10 @@ int init_x(void) {
|
|||
XChangeProperty(xdisplay, nofocus, XInternAtom(xdisplay, "_NET_SUPPORTING_WM_CHECK", False), XA_WINDOW, 32, PropModeReplace, (unsigned char*)&nofocus, 1);
|
||||
XChangeProperty(xdisplay, nofocus, XInternAtom(xdisplay, "_NET_WM_NAME", False), XInternAtom(xdisplay, "UTF8_STRING", False), 8, PropModeReplace, (unsigned char*)"milkwm", 6);
|
||||
|
||||
milkwm_set_focus = XInternAtom(xdisplay, "MILKWM_SET_FOCUS", False);
|
||||
|
||||
pthread_mutex_init(&xmutex, NULL);
|
||||
pthread_mutex_init(&focusmutex, NULL);
|
||||
|
||||
pthread_create(&xthread, NULL, x11_thread_routine, NULL);
|
||||
|
||||
|
|
@ -88,6 +102,7 @@ int init_x(void) {
|
|||
}
|
||||
|
||||
static void save(Window w) {
|
||||
XGrabButton(xdisplay, 1, 0, w, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None);
|
||||
XSelectInput(xdisplay, w, StructureNotifyMask | FocusChangeMask | PropertyChangeMask);
|
||||
XSetWindowBorderWidth(xdisplay, w, 0);
|
||||
XAddToSaveSet(xdisplay, w);
|
||||
|
|
@ -159,17 +174,37 @@ void loop_x(void) {
|
|||
|
||||
while(1) {
|
||||
XNextEvent(xdisplay, &ev);
|
||||
if(ev.type == ButtonPress) {
|
||||
if((ev.type == ButtonPress || ev.type == ButtonRelease) && ev.xbutton.subwindow != None && ev.xbutton.button == Button1) {
|
||||
Window w = None;
|
||||
if(ev.type == ButtonPress) {
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].frame->lowlevel->x11.window == ev.xbutton.window || parent_eq(ev.xbutton.window, windows[i].frame->lowlevel->x11.window)) {
|
||||
if(windows[i].frame->lowlevel->x11.window == ev.xbutton.subwindow || parent_eq(ev.xbutton.subwindow, windows[i].frame->lowlevel->x11.window)) {
|
||||
set_focus(windows[i].client);
|
||||
w = windows[i].frame->lowlevel->x11.window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i != arrlen(windows)) continue;
|
||||
set_focus(ev.xbutton.window);
|
||||
}
|
||||
|
||||
ev.xbutton.window = ev.xbutton.subwindow;
|
||||
ev.xbutton.subwindow = None;
|
||||
XSendEvent(xdisplay, ev.xbutton.window, False, 0, &ev);
|
||||
|
||||
if(w != None) XRaiseWindow(xdisplay, w);
|
||||
} else if(ev.type == MotionNotify && ev.xmotion.subwindow != None) {
|
||||
Window w = None;
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].frame->lowlevel->x11.window == ev.xbutton.subwindow || parent_eq(ev.xbutton.subwindow, windows[i].frame->lowlevel->x11.window)) {
|
||||
w = windows[i].frame->lowlevel->x11.window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ev.xmotion.window = ev.xmotion.subwindow;
|
||||
ev.xmotion.subwindow = None;
|
||||
XSendEvent(xdisplay, ev.xmotion.window, False, 0, &ev);
|
||||
|
||||
if(w != None) XRaiseWindow(xdisplay, w);
|
||||
} else if(ev.type == FocusIn && ev.xfocus.window != focus) {
|
||||
set_focus(focus);
|
||||
} else if(ev.type == FocusOut && focus != None) {
|
||||
|
|
@ -182,8 +217,8 @@ void loop_x(void) {
|
|||
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;
|
||||
xwc.width = wm_content_width(ev.xconfigurerequest.width);
|
||||
xwc.height = wm_content_height(ev.xconfigurerequest.height);
|
||||
|
||||
XConfigureWindow(xdisplay, windows[i].client, CWX | CWY | CWWidth | CWHeight, &xwc);
|
||||
break;
|
||||
|
|
@ -205,16 +240,16 @@ void loop_x(void) {
|
|||
|
||||
xwc.x = ev.xconfigure.x;
|
||||
xwc.y = ev.xconfigure.y;
|
||||
xwc.width = MwDefaultBorderWidth(windows[i].frame) * 2 + ev.xconfigure.width;
|
||||
xwc.height = MwDefaultBorderWidth(windows[i].frame) * 4 + TitleBarHeight + ev.xconfigure.height;
|
||||
xwc.width = wm_entire_width(ev.xconfigure.width);
|
||||
xwc.height = wm_entire_height(ev.xconfigure.height);
|
||||
|
||||
XGetWindowAttributes(xdisplay, windows[i].frame->lowlevel->x11.window, &xwa);
|
||||
|
||||
if(xwc.x != MwDefaultBorderWidth(windows[i].frame) || xwc.y != (MwDefaultBorderWidth(windows[i].frame) * 3 + TitleBarHeight)) {
|
||||
if(xwc.x != wm_content_x() || xwc.y != wm_content_y()) {
|
||||
XConfigureWindow(xdisplay, windows[i].frame->lowlevel->x11.window, CWX | CWY | CWWidth | CWHeight, &xwc);
|
||||
|
||||
xwc.x = MwDefaultBorderWidth(windows[i].frame);
|
||||
xwc.y = MwDefaultBorderWidth(windows[i].frame) * 3 + TitleBarHeight;
|
||||
xwc.x = wm_content_x();
|
||||
xwc.y = wm_content_y();
|
||||
XConfigureWindow(xdisplay, windows[i].client, CWX | CWY, &xwc);
|
||||
} else if(xwa.width != xwc.width || xwa.height != xwc.height) {
|
||||
XConfigureWindow(xdisplay, windows[i].frame->lowlevel->x11.window, CWWidth | CWHeight, &xwc);
|
||||
|
|
@ -251,7 +286,7 @@ void loop_x(void) {
|
|||
XMoveWindow(xdisplay, windows[i].frame->lowlevel->x11.window, xwa.x, xwa.y);
|
||||
|
||||
XMapWindow(xdisplay, ev.xmaprequest.window);
|
||||
if(!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, wm_get_inside(windows[i].frame)->lowlevel->x11.window, wm_content_x(), wm_content_y())) {
|
||||
wm_destroy(windows[i].frame);
|
||||
arrdel(windows, i);
|
||||
continue;
|
||||
|
|
@ -323,7 +358,34 @@ void loop_x(void) {
|
|||
|
||||
set_focus(w);
|
||||
}
|
||||
} else if(ev.type == ClientMessage) {
|
||||
if(ev.xclient.message_type == milkwm_set_focus && ev.xclient.data.l[0] == milkwm_set_focus) {
|
||||
set_focus(ev.xclient.data.l[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
end_error();
|
||||
}
|
||||
|
||||
void set_focus_x(MwWidget widget) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < arrlen(windows); i++) {
|
||||
if(windows[i].frame == widget) {
|
||||
XEvent ev;
|
||||
|
||||
ev.type = ClientMessage;
|
||||
ev.xclient.window = nofocus;
|
||||
ev.xclient.message_type = milkwm_set_focus;
|
||||
ev.xclient.format = 32;
|
||||
ev.xclient.data.l[0] = ev.xclient.message_type;
|
||||
ev.xclient.data.l[1] = windows[i].client;
|
||||
|
||||
XSendEvent(xdisplay, nofocus, False, 0, &ev);
|
||||
|
||||
XRaiseWindow(xdisplay, windows[i].frame->lowlevel->x11.window);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue