Handle window map_state and VisibilityNotify events, closes #68

This commit is contained in:
Jarcode
2018-10-08 11:18:45 -07:00
parent acdbb8f3b5
commit 83a94e3eb4
7 changed files with 54 additions and 21 deletions

View File

@@ -128,6 +128,7 @@ static void swap_buffers(GLFWwindow* w) {
static Display* get_x11_display(void) { return glfwGetX11Display(); }
static Window get_x11_window (GLFWwindow* w) { return glfwGetX11Window(w); }
static bool should_close (GLFWwindow* w) { return glfwWindowShouldClose(w); }
static bool should_render (GLFWwindow* w) { return true; }
static void get_fbsize (GLFWwindow* w, int* d, int* h) { glfwGetFramebufferSize(w, d, h); }
static void get_pos (GLFWwindow* w, int* x, int* y) { glfwGetWindowPos(w, x, y); }
static double get_time (GLFWwindow* w) { return glfwGetTime(); }

View File

@@ -175,7 +175,7 @@ struct glxwin {
Window w;
GLXContext context;
double time;
bool should_close, clickthrough;
bool should_close, should_render, clickthrough;
char override_state;
};
@@ -274,10 +274,13 @@ static void* create_and_bind(const char* name, const char* class,
int version_major, int version_minor,
bool clickthrough) {
struct glxwin* w = malloc(sizeof(struct glxwin));
w->override_state = '\0';
w->time = 0.0D;
w->should_close = false;
w->clickthrough = false;
*w = (struct glxwin) {
.override_state = '\0',
.time = 0.0D,
.should_close = false,
.should_render = true,
.clickthrough = false
};
XVisualInfo* vi;
XSetWindowAttributes attr = {};
@@ -355,10 +358,11 @@ static void* create_and_bind(const char* name, const char* class,
vi = glXGetVisualFromFBConfig(display, config);
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vi->visual, AllocNone);
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | PropertyChangeMask;
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask;
attr.event_mask |= PropertyChangeMask | VisibilityChangeMask;
attr.background_pixmap = None;
attr.border_pixel = 0;
unsigned long vmask = CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel;
if (type[0] == '!') {
vmask |= CWOverrideRedirect;
@@ -483,8 +487,14 @@ static void set_visible(struct glxwin* w, bool visible) {
else XUnmapWindow(display, w->w);
}
static bool should_close(struct glxwin* w) {
return w->should_close;
static bool should_close (struct glxwin* w) { return w->should_close; }
static bool should_render(struct glxwin* w) {
/* For nearly all window managers, windows are 'minimized' by unmapping parent windows.
VisibilityNotify events are not sent in these instances, so we have to read window
attributes to see if our window isn't viewable. */
XWindowAttributes attrs;
XGetWindowAttributes(display, w->w, &attrs);
return w->should_render && attrs.map_state == IsViewable;
}
static void swap_buffers(struct glxwin* w) {
@@ -500,6 +510,19 @@ static void swap_buffers(struct glxwin* w) {
w->should_close = true;
}
break;
case VisibilityNotify:
switch (ev.xvisibility.state) {
case VisibilityFullyObscured:
w->should_render = false;
break;
case VisibilityUnobscured:
case VisibilityPartiallyObscured:
w->should_render = true;
break;
default:
fprintf(stderr, "Invalid VisibilityNotify event state (%d)\n", ev.xvisibility.state);
break;
}
default: break;
}
}

View File

@@ -724,7 +724,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
.sm_prog = 0,
.copy_desktop = true,
.premultiply_alpha = true,
.check_fullscreen = true,
.check_fullscreen = false,
.smooth_pass = true,
.fft_scale = 10.2F,
.fft_cutoff = 0.3F,
@@ -1329,7 +1329,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
overlay(&gl->overlay);
glClearColor(gl->clear_color.r, gl->clear_color.g, gl->clear_color.b, gl->clear_color.a);
gl->wcb->set_visible(gl->w, true);
return r;
@@ -1349,9 +1349,13 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
r->alive = false;
return true;
}
/* Stop rendering if the backend has some reason not to render (minimized, obscured) */
if (!gl->wcb->should_render(gl->w))
return false;
/* Stop rendering when fullscreen windows are focused */
if (gl->check_fullscreen && !xwin_should_render(r))
if (gl->check_fullscreen && !xwin_should_render(gl->wcb, gl->w))
return false;
/* Force disable interpolation if the update rate is close to or higher than the frame rate */

View File

@@ -33,6 +33,7 @@ struct gl_wcb {
int version_major, int version_minor,
bool clickthrough);
bool (*should_close) (void* ptr);
bool (*should_render) (void* ptr);
void (*swap_buffers) (void* ptr);
void (*raise) (void* ptr);
void (*destroy) (void* ptr);
@@ -68,6 +69,7 @@ struct gl_wcb {
WCB_FUNC(init), \
WCB_FUNC(create_and_bind), \
WCB_FUNC(should_close), \
WCB_FUNC(should_render), \
WCB_FUNC(swap_buffers), \
WCB_FUNC(raise), \
WCB_FUNC(destroy), \

View File

@@ -128,11 +128,14 @@
simply set to zero (or lower) to disable the frame limiter. */
#request setframerate 0
/* Enable/disable fullscreen checks. This looks at the currently
focused window and halts GLava's rendering if it is
fullscreen. This prevents rendering from interfering with
other graphically intensive tasks. */
#request setfullscreencheck true
/* Suspends rendering if a fullscreen window is focused while
GLava is still visible (ie. on another monitor). This prevents
rendering from interfering with other graphically intensive
tasks.
If GLava is minimized or completely obscured, it will not
render regardless of this option. */
#request setfullscreencheck false
/* Enable/disable printing framerate every second. 'FPS' stands
for 'Frames Per Second', and 'UPS' stands for 'Updates Per

6
xwin.c
View File

@@ -140,14 +140,14 @@ const char* xwin_detect_wm(struct gl_wcb* wcb) {
}
bool xwin_should_render(struct renderer* rd) {
bool xwin_should_render(struct gl_wcb* wcb, void* impl) {
bool ret = true, should_close = false;
Display* d = rd_get_wcb(rd)->get_x11_display();
Display* d = wcb->get_x11_display();
if (!d) {
d = XOpenDisplay(0);
should_close = true;
}
Atom prop = XInternAtom(d, "_NET_ACTIVE_WINDOW", true);
Atom fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", true);

2
xwin.h
View File

@@ -6,7 +6,7 @@
typedef unsigned long int Window;
bool xwin_should_render(struct renderer* rd);
bool xwin_should_render(struct gl_wcb* wcb, void* impl);
void xwin_wait_for_wm(void);
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* type);
void xwin_setdesktop(struct gl_wcb* wcb, void* impl, unsigned long desktop);