Handle window map_state and VisibilityNotify events, closes #68
This commit is contained in:
@@ -128,6 +128,7 @@ static void swap_buffers(GLFWwindow* w) {
|
|||||||
static Display* get_x11_display(void) { return glfwGetX11Display(); }
|
static Display* get_x11_display(void) { return glfwGetX11Display(); }
|
||||||
static Window get_x11_window (GLFWwindow* w) { return glfwGetX11Window(w); }
|
static Window get_x11_window (GLFWwindow* w) { return glfwGetX11Window(w); }
|
||||||
static bool should_close (GLFWwindow* w) { return glfwWindowShouldClose(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_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 void get_pos (GLFWwindow* w, int* x, int* y) { glfwGetWindowPos(w, x, y); }
|
||||||
static double get_time (GLFWwindow* w) { return glfwGetTime(); }
|
static double get_time (GLFWwindow* w) { return glfwGetTime(); }
|
||||||
|
|||||||
41
glx_wcb.c
41
glx_wcb.c
@@ -175,7 +175,7 @@ struct glxwin {
|
|||||||
Window w;
|
Window w;
|
||||||
GLXContext context;
|
GLXContext context;
|
||||||
double time;
|
double time;
|
||||||
bool should_close, clickthrough;
|
bool should_close, should_render, clickthrough;
|
||||||
char override_state;
|
char override_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -274,10 +274,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 = (struct glxwin) {
|
||||||
w->time = 0.0D;
|
.override_state = '\0',
|
||||||
w->should_close = false;
|
.time = 0.0D,
|
||||||
w->clickthrough = false;
|
.should_close = false,
|
||||||
|
.should_render = true,
|
||||||
|
.clickthrough = false
|
||||||
|
};
|
||||||
|
|
||||||
XVisualInfo* vi;
|
XVisualInfo* vi;
|
||||||
XSetWindowAttributes attr = {};
|
XSetWindowAttributes attr = {};
|
||||||
@@ -355,10 +358,11 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
vi = glXGetVisualFromFBConfig(display, config);
|
vi = glXGetVisualFromFBConfig(display, config);
|
||||||
|
|
||||||
attr.colormap = XCreateColormap(display, DefaultRootWindow(display), vi->visual, AllocNone);
|
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.background_pixmap = None;
|
||||||
attr.border_pixel = 0;
|
attr.border_pixel = 0;
|
||||||
|
|
||||||
unsigned long vmask = CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel;
|
unsigned long vmask = CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel;
|
||||||
if (type[0] == '!') {
|
if (type[0] == '!') {
|
||||||
vmask |= CWOverrideRedirect;
|
vmask |= CWOverrideRedirect;
|
||||||
@@ -483,8 +487,14 @@ static void set_visible(struct glxwin* w, bool visible) {
|
|||||||
else XUnmapWindow(display, w->w);
|
else XUnmapWindow(display, w->w);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool should_close(struct glxwin* w) {
|
static bool should_close (struct glxwin* w) { return w->should_close; }
|
||||||
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) {
|
static void swap_buffers(struct glxwin* w) {
|
||||||
@@ -500,6 +510,19 @@ static void swap_buffers(struct glxwin* w) {
|
|||||||
w->should_close = true;
|
w->should_close = true;
|
||||||
}
|
}
|
||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
render.c
10
render.c
@@ -724,7 +724,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
.sm_prog = 0,
|
.sm_prog = 0,
|
||||||
.copy_desktop = true,
|
.copy_desktop = true,
|
||||||
.premultiply_alpha = true,
|
.premultiply_alpha = true,
|
||||||
.check_fullscreen = true,
|
.check_fullscreen = false,
|
||||||
.smooth_pass = true,
|
.smooth_pass = true,
|
||||||
.fft_scale = 10.2F,
|
.fft_scale = 10.2F,
|
||||||
.fft_cutoff = 0.3F,
|
.fft_cutoff = 0.3F,
|
||||||
@@ -1329,7 +1329,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
overlay(&gl->overlay);
|
overlay(&gl->overlay);
|
||||||
|
|
||||||
glClearColor(gl->clear_color.r, gl->clear_color.g, gl->clear_color.b, gl->clear_color.a);
|
glClearColor(gl->clear_color.r, gl->clear_color.g, gl->clear_color.b, gl->clear_color.a);
|
||||||
|
|
||||||
gl->wcb->set_visible(gl->w, true);
|
gl->wcb->set_visible(gl->w, true);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -1349,9 +1349,13 @@ bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
r->alive = false;
|
r->alive = false;
|
||||||
return true;
|
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 */
|
/* 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;
|
return false;
|
||||||
|
|
||||||
/* Force disable interpolation if the update rate is close to or higher than the frame rate */
|
/* Force disable interpolation if the update rate is close to or higher than the frame rate */
|
||||||
|
|||||||
2
render.h
2
render.h
@@ -33,6 +33,7 @@ struct gl_wcb {
|
|||||||
int version_major, int version_minor,
|
int version_major, int version_minor,
|
||||||
bool clickthrough);
|
bool clickthrough);
|
||||||
bool (*should_close) (void* ptr);
|
bool (*should_close) (void* ptr);
|
||||||
|
bool (*should_render) (void* ptr);
|
||||||
void (*swap_buffers) (void* ptr);
|
void (*swap_buffers) (void* ptr);
|
||||||
void (*raise) (void* ptr);
|
void (*raise) (void* ptr);
|
||||||
void (*destroy) (void* ptr);
|
void (*destroy) (void* ptr);
|
||||||
@@ -68,6 +69,7 @@ struct gl_wcb {
|
|||||||
WCB_FUNC(init), \
|
WCB_FUNC(init), \
|
||||||
WCB_FUNC(create_and_bind), \
|
WCB_FUNC(create_and_bind), \
|
||||||
WCB_FUNC(should_close), \
|
WCB_FUNC(should_close), \
|
||||||
|
WCB_FUNC(should_render), \
|
||||||
WCB_FUNC(swap_buffers), \
|
WCB_FUNC(swap_buffers), \
|
||||||
WCB_FUNC(raise), \
|
WCB_FUNC(raise), \
|
||||||
WCB_FUNC(destroy), \
|
WCB_FUNC(destroy), \
|
||||||
|
|||||||
@@ -128,11 +128,14 @@
|
|||||||
simply set to zero (or lower) to disable the frame limiter. */
|
simply set to zero (or lower) to disable the frame limiter. */
|
||||||
#request setframerate 0
|
#request setframerate 0
|
||||||
|
|
||||||
/* Enable/disable fullscreen checks. This looks at the currently
|
/* Suspends rendering if a fullscreen window is focused while
|
||||||
focused window and halts GLava's rendering if it is
|
GLava is still visible (ie. on another monitor). This prevents
|
||||||
fullscreen. This prevents rendering from interfering with
|
rendering from interfering with other graphically intensive
|
||||||
other graphically intensive tasks. */
|
tasks.
|
||||||
#request setfullscreencheck true
|
|
||||||
|
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
|
/* Enable/disable printing framerate every second. 'FPS' stands
|
||||||
for 'Frames Per Second', and 'UPS' stands for 'Updates Per
|
for 'Frames Per Second', and 'UPS' stands for 'Updates Per
|
||||||
|
|||||||
6
xwin.c
6
xwin.c
@@ -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;
|
bool ret = true, should_close = false;
|
||||||
Display* d = rd_get_wcb(rd)->get_x11_display();
|
Display* d = wcb->get_x11_display();
|
||||||
if (!d) {
|
if (!d) {
|
||||||
d = XOpenDisplay(0);
|
d = XOpenDisplay(0);
|
||||||
should_close = true;
|
should_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Atom prop = XInternAtom(d, "_NET_ACTIVE_WINDOW", true);
|
Atom prop = XInternAtom(d, "_NET_ACTIVE_WINDOW", true);
|
||||||
Atom fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", true);
|
Atom fullscreen = XInternAtom(d, "_NET_WM_STATE_FULLSCREEN", true);
|
||||||
|
|
||||||
|
|||||||
2
xwin.h
2
xwin.h
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
typedef unsigned long int Window;
|
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);
|
void xwin_wait_for_wm(void);
|
||||||
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* type);
|
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* type);
|
||||||
void xwin_setdesktop(struct gl_wcb* wcb, void* impl, unsigned long desktop);
|
void xwin_setdesktop(struct gl_wcb* wcb, void* impl, unsigned long desktop);
|
||||||
|
|||||||
Reference in New Issue
Block a user