11 Commits

Author SHA1 Message Date
Jarcode
dfd16f9e22 Properly compare desktop window types, closes #37 2018-03-19 21:45:19 -07:00
Jarcode
b446ac99c9 Fixed resource leak associated with xlib usage, see #33 2018-03-18 22:01:03 -07:00
Jarcode
8024e308d8 fixed some code style issues 2018-03-18 17:27:36 -07:00
Jarcode
dd5586a76e cleaning up comment formatting & spelling 2018-03-18 17:23:45 -07:00
Jarcode
20e755fbcb Switched to using git tags for versioning 2018-03-18 17:00:14 -07:00
Jarcode
ccf3c7b169 updated version 2018-03-18 16:26:52 -07:00
Jarcode
4be89c3337 force GLX backend even on XWayland sessions 2018-03-18 16:22:23 -07:00
Jarcode
2220946a2f Updated readme with compatibility information 2018-03-18 16:19:25 -07:00
Jarcode
9fb80be00f Merge branch 'unstable' 2018-03-18 12:26:31 -07:00
Jarcode
283afaaaca Cleanup & implementation of #32 2018-03-18 12:20:20 -07:00
Jarcode
5ac2cc4a94 Removed changelog in favour of GitHub releases 2018-03-04 13:39:39 -08:00
11 changed files with 88 additions and 95 deletions

View File

@@ -1,33 +0,0 @@
## 1.4
* Added window creation backends. GLava automatically uses the appropriate backend, currently `"glx"` and `"glfw"` are available. The GLX window creation code nicely supports transparent windows so that users do not need to use GLFW 3.3 for native transparency, which remains unstable and unreleased.
* Added a `--backend` (or `-b`) flag that can be used to manually select window creation backends.
* Fixed alpha blending with `"native"` transparency. GLava now correctly uses premultiplied alpha to provide alpha blending with other X windows, where a compositor is available.
* Fixed a segmentation fault that occurs with uncommon window managers, see #19
* Fixed various other issues with alpha blending in shader code.
## 1.3
* Added RGBA color parsing for GLSL code and directives (does not work within `#request` directives). The behaviour converts `#3ef708ff` -> `vec4(0.243, 0.967, 0.031, 1.0)`. If the alpha component is omitted, it is assumed to be `1.0`. The parsing occurs during compile time, so it does not incurr any performance penalty.
* Fixed stray `[DEBUG]` messages that were errornously being printed
* _Actually_ added support for GLFW 3.1, see issue #13
* Fixed issue with some WMs not responding to GLava's window types and hints, see #17
* Fixed alpha blending not working, `radial` and `circle` image quality should be drastically improved on `xroot` and `none` opacity settings.
* Added `--version` command line flag
## 1.2
* Attempted to add support for GLFW 3.1, see issue #13
* Added configurable solid background color, see #16
* Fixed issue with excessive file reads from `~/.Xauthority` see #15
## 1.1
* Added `circle` module
* Added anti-aliasing to the `radial` module, written into the shader itself
* Default configuration values should create more appealing visualizers now
* Massive performance improvements, see issue #10
## 1.0
* All versions of GLava with `1.0` version numbers are older development releases.

View File

@@ -57,10 +57,15 @@ LDFLAGS += $(ASAN) -lpulse -lpulse-simple -pthread $(LDFLAGS_GLFW) -ldl -lm -lX1
PYTHON = python
GLAVA_VERSION = \"$(shell git describe --tags 2>/dev/null)\"
ifeq ($(GLAVA_VERSION),\"\")
GLAVA_VERSION = \"unknown\"
endif
GLAD_INSTALL_DIR = glad
GLAD_SRCFILE = ./glad/src/glad.c
GLAD_ARGS = --generator=$(GLAD_GEN) --extensions=GL_EXT_framebuffer_multisample,GL_EXT_texture_filter_anisotropic
CFLAGS_COMMON = -I glad/include
CFLAGS_COMMON = -I glad/include -DGLAVA_VERSION="$(GLAVA_VERSION)"
CFLAGS_USE = $(CFLAGS_COMMON) $(CFLAGS_GLX) $(CFLAGS_GLFW) $(CFLAGS_BUILD) $(CFLAGS_INSTALL) $(CFLAGS)
all: glava

View File

@@ -51,10 +51,11 @@ GLava aims to be compatible with _most_ EWMH compliant window managers. Below is
| WM | ! | Details
| :---: | --- | --- |
| Mutter (GNOME, Budgie) | ![-](https://placehold.it/15/118932/000000?text=+) | `"native"` (default) opacity should be used
| Openbox (LXDE or standalone) | ![-](https://placehold.it/15/118932/000000?text=+) | [Some tweaks may be required](https://www.reddit.com/r/unixporn/comments/7vcgi4/oc_after_receiving_positive_feedback_here_i/dtrkvja/)
| Openbox (LXDE or standalone) | ![-](https://placehold.it/15/118932/000000?text=+) | No issues
| Xfwm (XFCE) | ![-](https://placehold.it/15/118932/000000?text=+) | Untested, but should work without issues
| Fluxbox | ![-](https://placehold.it/15/118932/000000?text=+) | Untested, but should work without issues
| iceWM | ![-](https://placehold.it/15/118932/000000?text=+) | No notable issues
| IceWM | ![-](https://placehold.it/15/118932/000000?text=+) | No issues
| Bspwm | ![-](https://placehold.it/15/118932/000000?text=+) | No issues
| Herbstluftwm | ![-](https://placehold.it/15/118932/000000?text=+) | `hc rule windowtype~'_NET_WM_WINDOW_TYPE_DESKTOP' manage=off` can be used to unmanage desktop windows
| AwesomeWM | ![-](https://placehold.it/15/f09c00/000000?text=+) | Can still be focused, may require other changes to config depending on layout
| kwin (KDE) | ![-](https://placehold.it/15/f09c00/000000?text=+) | [Issues with workspaces and stacking](https://github.com/wacossusca34/glava/issues/4), needs further testing
@@ -62,8 +63,7 @@ GLava aims to be compatible with _most_ EWMH compliant window managers. Below is
| EXWM | ![-](https://placehold.it/15/f03c15/000000?text=+) | EXWM does not have a desktop, and forces window decorations
| Unity | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing
| Enlightenment | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing
| Bspwm | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing
| xmonad | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing
| Xmonad | ![-](https://placehold.it/15/1589F0/000000?text=+) | Needs testing
| Any non EWMH-compliant WM | ![-](https://placehold.it/15/f03c15/000000?text=+) | Window types and hints will not work if the window manager does not support the EWMH standards.
## Licensing

View File

@@ -18,7 +18,6 @@
#include "render.h"
#include "xwin.h"
#define GLAVA_VERSION "1.4.1"
#ifdef GLAD_DEBUG
#define GLAVA_RELEASE_TYPE_PREFIX "debug, "
#else
@@ -199,7 +198,7 @@ int main(int argc, char** argv) {
bool verbose = false;
bool copy_mode = false;
int c, idx, n = 0;
int c, idx;
while ((c = getopt_long(argc, argv, opt_str, p_opts, &idx)) != -1) {
switch (c) {
case 'v': verbose = true; break;
@@ -259,7 +258,7 @@ int main(int argc, char** argv) {
}
pthread_t thread;
int thread_id = pthread_create(&thread, NULL, input_pulse, (void*) &audio);
pthread_create(&thread, NULL, input_pulse, (void*) &audio);
float lb[r->bufsize_request], rb[r->bufsize_request];
while (r->alive) {
@@ -272,7 +271,8 @@ int main(int argc, char** argv) {
pthread_mutex_lock(&audio.mutex);
modified = audio.modified;
if (modified) {
/* create our own copies of the audio buffers, so the streaming thread can continue to append to it */
/* create our own copies of the audio buffers, so the streaming
thread can continue to append to it */
memcpy(lb, (void*) audio.audio_out_l, r->bufsize_request * sizeof(float));
memcpy(rb, (void*) audio.audio_out_r, r->bufsize_request * sizeof(float));
audio.modified = false; /* set this flag to false until the next time we read */

View File

@@ -119,7 +119,7 @@ static void set_visible(GLFWwindow* w, bool visible) {
else glfwHideWindow(w);
}
static bool swap_buffers(GLFWwindow* w) {
static void swap_buffers(GLFWwindow* w) {
glfwSwapBuffers(w);
glfwPollEvents();
}

View File

@@ -15,6 +15,7 @@
#include <X11/Xlib.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/shape.h>
#include <X11/Xatom.h>
#include <glad/glad.h>
@@ -126,7 +127,7 @@ static void* create_and_bind(const char* name, const char* class,
if (!fmt || (transparent ? fmt->direct.alphaMask == 0 : fmt->direct.alphaMask != 0))
continue;
if (best < 0 || samp_buf && samples > samp) {
if (best < 0 || (samp_buf && samples > samp)) {
best = t;
samp = samples;
}
@@ -158,8 +159,10 @@ static void* create_and_bind(const char* name, const char* class,
abort();
}
bool desktop = false;
if (type)
xwin_settype(&wcb_glx, w, type);
desktop = xwin_settype(&wcb_glx, w, type);
for (size_t t = 0; t < states_sz; ++t)
xwin_addstate(&wcb_glx, w, states[t]);
@@ -181,6 +184,20 @@ static void* create_and_bind(const char* name, const char* class,
Atom dwin = XInternAtom(display, "WM_DELETE_WINDOW", false);
XSetWMProtocols(display, w->w, &dwin, 1);
// XReparentWindow(display, w->w, DefaultRootWindow(display), 0, 0);
/* Eliminate the window's effective region */
if (desktop){
int ignored;
if (XShapeQueryExtension(display, &ignored, &ignored)) {
Region region;
if ((region = XCreateRegion())) {
XShapeCombineRegion(display, w->w, ShapeInput, 0, 0, region, ShapeSet);
XDestroyRegion(region);
}
}
}
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = NULL;
glXSwapIntervalEXTProc glXSwapIntervalEXT = NULL;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
@@ -255,7 +272,6 @@ static void get_fbsize(struct glxwin* w, int* d, int* h) {
}
static void get_pos(struct glxwin* w, int* x, int* y) {
XWindowAttributes a;
Window _ignored;
XTranslateCoordinates(display, w->w, DefaultRootWindow(display), 0, 0, x, y, &_ignored);
}

View File

@@ -9,22 +9,22 @@
#include "fifo.h"
static pa_mainloop *m_pulseaudio_mainloop;
static pa_mainloop* m_pulseaudio_mainloop;
static void cb(__attribute__((unused)) pa_context *pulseaudio_context,
const pa_server_info *i,
void *userdata) {
static void cb(__attribute__((unused)) pa_context* pulseaudio_context,
const pa_server_info* i,
void* userdata) {
//getting default sink name
struct audio_data *audio = (struct audio_data *)userdata;
/* Obtain default sink name */
struct audio_data* audio = (struct audio_data*) userdata;
audio->source = malloc(sizeof(char) * 1024);
strcpy(audio->source,i->default_sink_name);
//appending .monitor suffix
/* Append `.monitor` suffix */
audio->source = strcat(audio->source, ".monitor");
//quiting mainloop
/* Quiting mainloop */
pa_context_disconnect(pulseaudio_context);
pa_context_unref(pulseaudio_context);
pa_mainloop_quit(m_pulseaudio_mainloop, 0);
@@ -32,10 +32,9 @@ static void cb(__attribute__((unused)) pa_context *pulseaudio_context,
}
static void pulseaudio_context_state_callback(pa_context *pulseaudio_context,
void *userdata) {
static void pulseaudio_context_state_callback(pa_context* pulseaudio_context, void* userdata) {
// make sure loop is ready
/* Ensure loop is ready */
switch (pa_context_get_state(pulseaudio_context))
{
case PA_CONTEXT_UNCONNECTED:
@@ -54,7 +53,6 @@ static void pulseaudio_context_state_callback(pa_context *pulseaudio_context,
exit(EXIT_FAILURE);
break;
case PA_CONTEXT_TERMINATED:
// printf("PulseAudio context terminated!\n");
pa_mainloop_quit(m_pulseaudio_mainloop, 0);
break;
}
@@ -63,29 +61,29 @@ static void pulseaudio_context_state_callback(pa_context *pulseaudio_context,
void get_pulse_default_sink(struct audio_data* audio) {
pa_mainloop_api *mainloop_api;
pa_context *pulseaudio_context;
pa_mainloop_api* mainloop_api;
pa_context* pulseaudio_context;
int ret;
// Create a mainloop API and connection to the default server
/* Create a mainloop API and connection to the default server */
m_pulseaudio_mainloop = pa_mainloop_new();
mainloop_api = pa_mainloop_get_api(m_pulseaudio_mainloop);
pulseaudio_context = pa_context_new(mainloop_api, "glava device list");
// This function connects to the pulse server
/* Connect to the PA server */
pa_context_connect(pulseaudio_context, NULL, PA_CONTEXT_NOFLAGS,
NULL);
// This function defines a callback so the server will tell us its state.
/* Define a callback so the server will tell us its state */
pa_context_set_state_callback(pulseaudio_context,
pulseaudio_context_state_callback,
(void*)audio);
// starting a mainloop to get default sink
/* Start mainloop to get default sink */
// starting with one non blokng iteration in case pulseaudio is not able to run
/* Start with one non blocking iteration in case pulseaudio is not able to run */
if (!(ret = pa_mainloop_iterate(m_pulseaudio_mainloop, 0, &ret))){
printf("Could not open pulseaudio mainloop to "
"find default device name: %d\n"
@@ -114,12 +112,11 @@ void get_pulse_default_sink(struct audio_data* audio) {
#endif
void* input_pulse(void* data) {
struct audio_data *audio = (struct audio_data *)data;
struct audio_data* audio = (struct audio_data*) data;
int i, n;
size_t ssz = audio->sample_sz;
float buf[ssz / 2];
/* The sample type to use */
const pa_sample_spec ss = {
.format = FSAMPLE_FORMAT,
.rate = audio->rate,
@@ -130,7 +127,7 @@ void* input_pulse(void* data) {
.fragsize = ssz
};
pa_simple *s = NULL;
pa_simple* s = NULL;
int error;
if (!(s = pa_simple_new(NULL, "glava", PA_STREAM_RECORD,
@@ -163,17 +160,17 @@ void* input_pulse(void* data) {
memmove(bl, &bl[ssz / 4], (fsz - (ssz / 4)) * sizeof(float));
memmove(br, &br[ssz / 4], (fsz - (ssz / 4)) * sizeof(float));
// sorting out channelss
/* sorting out channels */
for (n = 0, i = 0; i < ssz / 2; i += 2) {
// size_t idx = (i / 2) + (at * (BUFSIZE / 2));
/* size_t idx = (i / 2) + (at * (BUFSIZE / 2)); */
int idx = (fsz - (ssz / 4)) + n;
if (audio->channels == 1) bl[idx] = (buf[i] + buf[i + 1]) / 2;
// stereo storing channels in buffer
/* stereo storing channels in buffer */
if (audio->channels == 2) {
bl[idx] = buf[i];
br[idx] = buf[i + 1];

View File

@@ -506,7 +506,6 @@ void transform_smooth(struct gl_data* d, void** udaa, void* data) {
for (int t = 0; t < asz; ++t) {
float
db = log(t), /* buffer index on log scale */
v = b[t], /* value at this position */
avg = 0; /* adj value averages (weighted) */
/* Calculate real indexes for sampling at this position, since the
distance is specified in scalar values */
@@ -592,7 +591,7 @@ void transform_wrange(struct gl_data* d, void** _, void* data) {
void transform_window(struct gl_data* d, void** _, void* data) {
struct gl_sampler_data* s = (struct gl_sampler_data*) data;
float* b = s->buf, w;
float* b = s->buf;
size_t sz = s->sz, t;
for (t = 0; t < sz; ++t) {
@@ -737,7 +736,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
#ifdef GLAVA_GLX
DECL_WCB(wcb_glx);
if (!forced && !getenv("WAYLAND_DISPLAY") && getenv("DISPLAY")) {
if (!forced && getenv("DISPLAY")) {
backend = "glx";
}
#endif
@@ -765,7 +764,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
};
if (!gl->wcb) {
fprintf(stderr, "Invalid window creation backend selected: '%s'\n", gl->wcb);
fprintf(stderr, "Invalid window creation backend selected: '%s'\n", backend);
abort();
}

View File

@@ -31,7 +31,7 @@ struct gl_wcb {
int x, int y,
int version_major, int version_minor);
bool (*should_close) (void* ptr);
bool (*swap_buffers) (void* ptr);
void (*swap_buffers) (void* ptr);
void (*get_pos) (void* ptr, int* x, int* y);
void (*get_fbsize) (void* ptr, int* w, int* h);
void (*set_geometry) (void* ptr, int x, int y, int w, int h);

27
xwin.c
View File

@@ -67,7 +67,7 @@ bool xwin_should_render(struct renderer* rd) {
Atom actual_type;
int actual_format, t;
unsigned long nitems, bytes_after;
unsigned char* data;
unsigned char* data = NULL;
int handler(Display* d, XErrorEvent* e) { return 0; }
@@ -85,6 +85,11 @@ bool xwin_should_render(struct renderer* rd) {
prop = XInternAtom(d, "_NET_WM_STATE", true);
if (data) {
XFree(data);
data = NULL;
}
if (Success != XGetWindowProperty(d, active, prop, 0, LONG_MAX, false, AnyPropertyType,
&actual_type, &actual_format, &nitems, &bytes_after, &data)) {
goto close; /* some WMs are a little slow on creating _NET_WM_STATE, so errors may occur here */
@@ -95,14 +100,14 @@ bool xwin_should_render(struct renderer* rd) {
}
}
close:
if (data)
XFree(data);
if (should_close)
XCloseDisplay(d);
return ret;
}
/* Set window types defined by the EWMH standard, possible values:
-> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */
static void xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
static bool xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
const char* atom, const char* fmt, int mode) {
Window w = wcb->get_x11_window(impl);
Display* d = wcb->get_x11_display();
@@ -116,14 +121,19 @@ static void xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
default: formatted[t] = c;
}
}
bool ret = !strcmp(formatted, "DESKTOP");
char buf[256];
snprintf(buf, sizeof(buf), fmt, formatted);
Atom desk = XInternAtom(d, buf, false);
XChangeProperty(d, w, wtype, XA_ATOM, 32, mode, (unsigned char*) &desk, 1);
return ret;
}
void xwin_settype(struct gl_wcb* wcb, void* impl, const char* type) {
xwin_changeatom(wcb, impl, type, "_NET_WM_WINDOW_TYPE", "_NET_WM_WINDOW_TYPE_%s", PropModeReplace);
/* Set window types defined by the EWMH standard, possible values:
-> "desktop", "dock", "toolbar", "menu", "utility", "splash", "dialog", "normal" */
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* type) {
return xwin_changeatom(wcb, impl, type, "_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_%s", PropModeReplace);
}
void xwin_addstate(struct gl_wcb* wcb, void* impl, const char* state) {
@@ -160,14 +170,13 @@ unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
bool use_shm = true;
int x, y, w, h;
rd_get_wcb(rd)->get_fbsize(rd_get_impl_window(rd), &w, &h);
rd_get_wcb(rd)->get_pos(rd_get_impl_window(rd), &x, &y);
XColor c;
Display* d = rd_get_wcb(rd)->get_x11_display();
Drawable src = get_drawable(d, find_desktop(rd));
bool use_shm = XShmQueryExtension(d);
/* Obtain section of root pixmap */
@@ -191,7 +200,7 @@ unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) {
XShmGetImage(d, src, image, x, y, AllPlanes);
} else {
image = XGetImage(d, src, x, y, (unsigned int) w, (unsigned int) h,
ZPixmap, AllPlanes);
AllPlanes, ZPixmap);
}
/* Try to convert pixel bit depth to OpenGL storage format. The following formats\

2
xwin.h
View File

@@ -1,5 +1,5 @@
bool xwin_should_render(struct renderer* rd);
void 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_addstate(struct gl_wcb* wcb, void* impl, const char* state);
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture);