respect _MOTIF_WM_HINTS
This commit is contained in:
parent
803344663e
commit
281b3bfd9b
1 changed files with 107 additions and 37 deletions
142
milkwm/xserver.c
142
milkwm/xserver.c
|
|
@ -5,6 +5,33 @@
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
#include <stb_image.h>
|
#include <stb_image.h>
|
||||||
|
|
||||||
|
typedef struct mwm_hints {
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned long functions;
|
||||||
|
unsigned long decorations;
|
||||||
|
long input_mode;
|
||||||
|
unsigned long status;
|
||||||
|
} mwm_hints_t;
|
||||||
|
enum mwm_hints_enum {
|
||||||
|
MWM_HINTS_FUNCTIONS = (1L << 0),
|
||||||
|
MWM_HINTS_DECORATIONS = (1L << 1),
|
||||||
|
|
||||||
|
MWM_FUNC_ALL = (1L << 0),
|
||||||
|
MWM_FUNC_RESIZE = (1L << 1),
|
||||||
|
MWM_FUNC_MOVE = (1L << 2),
|
||||||
|
MWM_FUNC_MINIMIZE = (1L << 3),
|
||||||
|
MWM_FUNC_MAXIMIZE = (1L << 4),
|
||||||
|
MWM_FUNC_CLOSE = (1L << 5),
|
||||||
|
|
||||||
|
MWM_DECOR_ALL = (1L << 0),
|
||||||
|
MWM_DECOR_BORDER = (1L << 1),
|
||||||
|
MWM_DECOR_RESIZEH = (1L << 2),
|
||||||
|
MWM_DECOR_TITLE = (1L << 3),
|
||||||
|
MWM_DECOR_MENU = (1L << 4),
|
||||||
|
MWM_DECOR_MINIMIZE = (1L << 5),
|
||||||
|
MWM_DECOR_MAXIMIZE = (1L << 6)
|
||||||
|
};
|
||||||
|
|
||||||
Display* xdisplay;
|
Display* xdisplay;
|
||||||
pthread_t xthread;
|
pthread_t xthread;
|
||||||
pthread_mutex_t xmutex;
|
pthread_mutex_t xmutex;
|
||||||
|
|
@ -57,29 +84,30 @@ static void* x11_thread_routine(void* arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static Window focus = None, nofocus;
|
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 != w && focus == windows[i].client) {
|
|
||||||
pthread_mutex_unlock(&focusmutex);
|
|
||||||
wm_focus(windows[i].frame, 0);
|
|
||||||
} else {
|
|
||||||
pthread_mutex_unlock(&focusmutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_mutex_lock(&focusmutex);
|
static void set_focus(Window w) {
|
||||||
focus = w;
|
int i;
|
||||||
if(w == None) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
XSetInputFocus(xdisplay, nofocus, RevertToParent, CurrentTime);
|
pthread_mutex_lock(&focusmutex);
|
||||||
} else {
|
if(windows[i].frame != NULL && windows[i].client == w) {
|
||||||
XSetInputFocus(xdisplay, w, RevertToParent, CurrentTime);
|
pthread_mutex_unlock(&focusmutex);
|
||||||
}
|
wm_focus(windows[i].frame, 1);
|
||||||
pthread_mutex_unlock(&focusmutex);
|
} else if(windows[i].frame != NULL && 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);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&focusmutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long generate_color(int r, int g, int b) {
|
static unsigned long generate_color(int r, int g, int b) {
|
||||||
|
|
@ -304,6 +332,36 @@ static void set_name(Window wnd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_no_border(Window window) {
|
||||||
|
Atom atom = XInternAtom(xdisplay, "_MOTIF_WM_HINTS", False);
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long nitem, after;
|
||||||
|
unsigned char* buf = NULL;
|
||||||
|
mwm_hints_t* mwm;
|
||||||
|
|
||||||
|
if(XGetWindowProperty(xdisplay, window, atom, 0, sizeof(*mwm) / sizeof(long), False, AnyPropertyType, &type, &format, &nitem, &after, &buf) == Success && buf != NULL) {
|
||||||
|
if(type == atom && nitem == (sizeof(*mwm) / sizeof(long))) {
|
||||||
|
mwm = (mwm_hints_t*)buf;
|
||||||
|
|
||||||
|
if(mwm->flags & MWM_HINTS_DECORATIONS) {
|
||||||
|
if(mwm->decorations == 0) {
|
||||||
|
XFree(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XFree(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void loop_x(void) {
|
void loop_x(void) {
|
||||||
XEvent ev;
|
XEvent ev;
|
||||||
Window root, parent;
|
Window root, parent;
|
||||||
|
|
@ -320,7 +378,7 @@ void loop_x(void) {
|
||||||
XWindowAttributes xwa;
|
XWindowAttributes xwa;
|
||||||
|
|
||||||
if(XGetWindowAttributes(xdisplay, children[i], &xwa)) {
|
if(XGetWindowAttributes(xdisplay, children[i], &xwa)) {
|
||||||
if(xwa.override_redirect || xwa.map_state != IsViewable) continue;
|
if(xwa.override_redirect || xwa.map_state != IsViewable || is_no_border(children[i])) continue;
|
||||||
|
|
||||||
w.frame = wm_frame(xwa.width, xwa.height);
|
w.frame = wm_frame(xwa.width, xwa.height);
|
||||||
w.client = children[i];
|
w.client = children[i];
|
||||||
|
|
@ -344,7 +402,7 @@ void loop_x(void) {
|
||||||
if(ev.xbutton.subwindow != None) t = ev.xbutton.subwindow;
|
if(ev.xbutton.subwindow != None) t = ev.xbutton.subwindow;
|
||||||
if(ev.type == ButtonPress) {
|
if(ev.type == ButtonPress) {
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].frame->lowlevel->x11.window == t || parent_eq(t, windows[i].frame->lowlevel->x11.window)) {
|
if(windows[i].frame != NULL && (windows[i].frame->lowlevel->x11.window == t || parent_eq(t, windows[i].frame->lowlevel->x11.window))) {
|
||||||
set_focus(windows[i].client);
|
set_focus(windows[i].client);
|
||||||
w = windows[i].frame->lowlevel->x11.window;
|
w = windows[i].frame->lowlevel->x11.window;
|
||||||
break;
|
break;
|
||||||
|
|
@ -377,7 +435,7 @@ void loop_x(void) {
|
||||||
int i;
|
int i;
|
||||||
Window w = ev.xconfigurerequest.window;
|
Window w = ev.xconfigurerequest.window;
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].frame->lowlevel->x11.window == w) {
|
if(windows[i].frame != NULL && windows[i].frame->lowlevel->x11.window == w) {
|
||||||
XConfigureEvent ev2;
|
XConfigureEvent ev2;
|
||||||
|
|
||||||
xwc.x = wm_content_x();
|
xwc.x = wm_content_x();
|
||||||
|
|
@ -408,7 +466,7 @@ void loop_x(void) {
|
||||||
} else if(ev.type == ConfigureNotify) {
|
} else if(ev.type == ConfigureNotify) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].client == ev.xconfigure.window) {
|
if(windows[i].frame != NULL && windows[i].client == ev.xconfigure.window) {
|
||||||
XWindowChanges xwc;
|
XWindowChanges xwc;
|
||||||
XWindowAttributes xwa;
|
XWindowAttributes xwa;
|
||||||
|
|
||||||
|
|
@ -435,12 +493,14 @@ void loop_x(void) {
|
||||||
} else if(ev.type == CreateNotify) {
|
} else if(ev.type == CreateNotify) {
|
||||||
XWindowAttributes xwa;
|
XWindowAttributes xwa;
|
||||||
|
|
||||||
XGetWindowAttributes(xdisplay, DefaultRootWindow(xdisplay), &xwa);
|
if(!ev.xcreatewindow.override_redirect) {
|
||||||
|
XGetWindowAttributes(xdisplay, DefaultRootWindow(xdisplay), &xwa);
|
||||||
|
|
||||||
XMoveWindow(xdisplay, ev.xcreatewindow.window, rand() % (xwa.width - wm_entire_width(ev.xcreatewindow.width)), rand() % (xwa.height - wm_entire_height(ev.xcreatewindow.height)));
|
XMoveWindow(xdisplay, ev.xcreatewindow.window, rand() % (xwa.width - wm_entire_width(ev.xcreatewindow.width)), rand() % (xwa.height - wm_entire_height(ev.xcreatewindow.height)));
|
||||||
|
}
|
||||||
} else if(ev.type == DestroyNotify) {
|
} else if(ev.type == DestroyNotify) {
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].client == ev.xdestroywindow.window) {
|
if(windows[i].frame != NULL && windows[i].client == ev.xdestroywindow.window) {
|
||||||
wm_destroy(windows[i].frame);
|
wm_destroy(windows[i].frame);
|
||||||
arrdel(windows, i);
|
arrdel(windows, i);
|
||||||
break;
|
break;
|
||||||
|
|
@ -455,13 +515,18 @@ void loop_x(void) {
|
||||||
|
|
||||||
if(!XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa)) continue;
|
if(!XGetWindowAttributes(xdisplay, ev.xmaprequest.window, &xwa)) continue;
|
||||||
/* ?? ? ? ???? ?? ? ? */
|
/* ?? ? ? ???? ?? ? ? */
|
||||||
if(xwa.override_redirect) {
|
if(xwa.override_redirect || is_no_border(ev.xmaprequest.window)) {
|
||||||
|
w.frame = NULL;
|
||||||
|
w.client = ev.xmaprequest.window;
|
||||||
|
w.working = 1;
|
||||||
|
arrput(windows, w);
|
||||||
|
|
||||||
XMapWindow(xdisplay, ev.xmaprequest.window);
|
XMapWindow(xdisplay, ev.xmaprequest.window);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].frame->lowlevel->x11.window == ev.xmaprequest.window) break;
|
if(windows[i].frame != NULL && windows[i].frame->lowlevel->x11.window == ev.xmaprequest.window) break;
|
||||||
if(windows[i].client == ev.xmaprequest.window) {
|
if(windows[i].client == ev.xmaprequest.window) {
|
||||||
/* what? */
|
/* what? */
|
||||||
ret = 1;
|
ret = 1;
|
||||||
|
|
@ -509,6 +574,7 @@ void loop_x(void) {
|
||||||
w.frame = wm_frame(xwa.width, xwa.height);
|
w.frame = wm_frame(xwa.width, xwa.height);
|
||||||
w.client = ev.xmaprequest.window;
|
w.client = ev.xmaprequest.window;
|
||||||
w.working = 1;
|
w.working = 1;
|
||||||
|
|
||||||
save(w.client);
|
save(w.client);
|
||||||
|
|
||||||
if(ret) {
|
if(ret) {
|
||||||
|
|
@ -537,8 +603,9 @@ void loop_x(void) {
|
||||||
for(i = 0; i < arrlen(windows); i++) {
|
for(i = 0; i < arrlen(windows); i++) {
|
||||||
if(windows[i].client == ev.xmap.window) {
|
if(windows[i].client == ev.xmap.window) {
|
||||||
windows[i].working = 0;
|
windows[i].working = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} else if(windows[i].frame->lowlevel->x11.window == ev.xmap.window || nofocus == ev.xmap.window) {
|
} else if(windows[i].frame != NULL && (windows[i].frame->lowlevel->x11.window == ev.xmap.window || nofocus == ev.xmap.window)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -575,11 +642,14 @@ void loop_x(void) {
|
||||||
|
|
||||||
x = xwa.x;
|
x = xwa.x;
|
||||||
y = xwa.y;
|
y = xwa.y;
|
||||||
if(XGetWindowAttributes(xdisplay, windows[i].frame->lowlevel->x11.window, &xwa)) {
|
|
||||||
XReparentWindow(xdisplay, windows[i].client, DefaultRootWindow(xdisplay), xwa.x + x, xwa.y + y);
|
|
||||||
}
|
|
||||||
|
|
||||||
wm_destroy(windows[i].frame);
|
if(windows[i].frame != NULL) {
|
||||||
|
if(XGetWindowAttributes(xdisplay, windows[i].frame->lowlevel->x11.window, &xwa)) {
|
||||||
|
XReparentWindow(xdisplay, windows[i].client, DefaultRootWindow(xdisplay), xwa.x + x, xwa.y + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
wm_destroy(windows[i].frame);
|
||||||
|
}
|
||||||
arrdel(windows, i);
|
arrdel(windows, i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue