Added support for unmanaged windows, see #65 and #4

This commit is contained in:
Jarcode
2018-10-04 20:14:37 -07:00
parent e4b16cdbb6
commit 353c3bd62f
3 changed files with 46 additions and 22 deletions

View File

@@ -175,6 +175,7 @@ struct glxwin {
GLXContext context; GLXContext context;
double time; double time;
bool should_close, clickthrough; bool should_close, clickthrough;
char override_state;
}; };
static Atom ATOM__MOTIF_WM_HINTS, ATOM_WM_DELETE_WINDOW, ATOM_WM_PROTOCOLS, ATOM__NET_ACTIVE_WINDOW; static Atom ATOM__MOTIF_WM_HINTS, ATOM_WM_DELETE_WINDOW, ATOM_WM_PROTOCOLS, ATOM__NET_ACTIVE_WINDOW;
@@ -271,12 +272,13 @@ static void* create_and_bind(const char* name, const char* class,
int version_major, int version_minor, int version_major, int version_minor,
bool clickthrough) { bool clickthrough) {
struct glxwin* w = malloc(sizeof(struct glxwin)); struct glxwin* w = malloc(sizeof(struct glxwin));
w->override_state = '\0';
w->time = 0.0D; w->time = 0.0D;
w->should_close = false; w->should_close = false;
w->clickthrough = false; w->clickthrough = false;
XVisualInfo* vi; XVisualInfo* vi;
XSetWindowAttributes attr; XSetWindowAttributes attr = {};
GLXFBConfig* fbc; GLXFBConfig* fbc;
int fb_sz, best = -1, samp = -1; int fb_sz, best = -1, samp = -1;
@@ -339,12 +341,18 @@ static void* create_and_bind(const char* name, const char* class,
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | PropertyChangeMask; attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | PropertyChangeMask;
attr.background_pixmap = None; attr.background_pixmap = None;
attr.border_pixel = 0; attr.border_pixel = 0;
unsigned long vmask = CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel;
if (type[0] == '!') {
vmask |= CWOverrideRedirect;
attr.override_redirect = true;
w->override_state = type[1];
}
if (!(w->w = XCreateWindow(display, DefaultRootWindow(display)/**xwin_get_desktop_layer(&wcb_glx)*/, if (!(w->w = XCreateWindow(display, DefaultRootWindow(display)/**xwin_get_desktop_layer(&wcb_glx)*/,
x, y, d, h, 0, x, y, d, h, 0,
vi->depth, InputOutput, vi->visual, vi->depth, InputOutput, vi->visual,
CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel, vmask, &attr))) {
&attr))) {
fprintf(stderr, "XCreateWindow(): failed\n"); fprintf(stderr, "XCreateWindow(): failed\n");
abort(); abort();
} }
@@ -409,23 +417,25 @@ static void* create_and_bind(const char* name, const char* class,
} }
static void raise(struct glxwin* w) { static void raise(struct glxwin* w) {
XClientMessageEvent ev = { if (w->override_state == '\0') {
.type = ClientMessage, XClientMessageEvent ev = {
.serial = 0, .type = ClientMessage,
.send_event = true, .serial = 0,
.display = display, .send_event = true,
.window = w->w, .display = display,
.message_type = ATOM__NET_ACTIVE_WINDOW, .window = w->w,
.format = 32, .message_type = ATOM__NET_ACTIVE_WINDOW,
.data = { .l = { .format = 32,
[0] = 1, /* source indication -- `1` when coming from an application */ .data = { .l = {
[1] = 0, /* timestamp -- `0` to (attempt to) ignore */ [0] = 1, /* source indication -- `1` when coming from an application */
[2] = w->w /* requestor's currently active window -- `0` for none */ [1] = 0, /* timestamp -- `0` to (attempt to) ignore */
[2] = w->w /* requestor's currently active window -- `0` for none */
}
} }
} };
}; /* Send the client message as defined by EWMH standards (usually works) */
/* Send the client message as defined by EWMH standards (usually works) */ XSendEvent(display, DefaultRootWindow(display), false, StructureNotifyMask, (XEvent*) &ev);
XSendEvent(display, DefaultRootWindow(display), false, StructureNotifyMask, (XEvent*) &ev); }
/* Raise the client in the X11 stacking order (sometimes works, can be blocked by the WM) */ /* Raise the client in the X11 stacking order (sometimes works, can be blocked by the WM) */
XRaiseWindow(display, w->w); XRaiseWindow(display, w->w);
XFlush(display); XFlush(display);
@@ -446,6 +456,12 @@ static void set_visible(struct glxwin* w, bool visible) {
if (visible) { if (visible) {
XMapWindow(display, w->w); XMapWindow(display, w->w);
apply_clickthrough(w); apply_clickthrough(w);
switch (w->override_state) {
case '+': XRaiseWindow(display, w->w); break;
case '-': XLowerWindow(display, w->w); break;
default: break;
}
XFlush(display);
} }
else XUnmapWindow(display, w->w); else XUnmapWindow(display, w->w);
} }

View File

@@ -61,7 +61,13 @@
This will set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_(TYPE), This will set _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_(TYPE),
where (TYPE) is the one of the window types listed (after being where (TYPE) is the one of the window types listed (after being
converted to uppercase). */ converted to uppercase).
Alternatively, you can set this value to "!", which will cause
the window to be unmanaged. If this is set, then `addxwinstate`
will do nothing, but you can use "!+" and "!-" to stack on top
or below other windows.
*/
#request setxwintype "normal" #request setxwintype "normal"
/* (X11 only) EWMH Window state atoms (multiple can be specified). /* (X11 only) EWMH Window state atoms (multiple can be specified).

6
xwin.c
View File

@@ -221,8 +221,10 @@ static void xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
-> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */ -> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* rtype) { bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* rtype) {
S_UPPER(rtype, type); S_UPPER(rtype, type);
xwin_changeatom(wcb, impl, type, "_NET_WM_WINDOW_TYPE", if (type[0] != '!') {
"_NET_WM_WINDOW_TYPE_%s", PropModeReplace); xwin_changeatom(wcb, impl, type, "_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_%s", PropModeReplace);
}
return !strcmp(type, "DESKTOP"); return !strcmp(type, "DESKTOP");
} }