Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d49be40fd3 | ||
|
|
fb1d85dbf9 | ||
|
|
31ebab0549 | ||
|
|
3f621420a3 | ||
|
|
9a9c6eaa37 | ||
|
|
3e06fa683a | ||
|
|
b971c1c8f9 | ||
|
|
45b614a692 | ||
|
|
fc80db664b | ||
|
|
75a3affbc0 | ||
|
|
198596eaee | ||
|
|
e694261f4d | ||
|
|
8c3b9a5f21 | ||
|
|
ebade264ea | ||
|
|
469b8ec7ad | ||
|
|
4cc8a5e3ba | ||
|
|
309b1beeec | ||
|
|
7b72a28f19 | ||
|
|
b83c7cc59e | ||
|
|
6318c57ff7 | ||
|
|
279437dcd1 |
8
LICENSE
8
LICENSE
@@ -1,7 +1,7 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
@@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
<https://www.gnu.org/licenses/>.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
The GNU General Public License does not permit incorporating your program
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||||
|
|||||||
10
Makefile
10
Makefile
@@ -4,11 +4,11 @@ obj = $(src:.c=.o)
|
|||||||
# Build type parameter
|
# Build type parameter
|
||||||
|
|
||||||
ifeq ($(BUILD),debug)
|
ifeq ($(BUILD),debug)
|
||||||
CFLAGS_BUILD = -O0 -ggdb -Wall -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
CFLAGS_BUILD = -O0 -ggdb -Wall #-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls
|
||||||
GLAD_GEN = c-debug
|
GLAD_GEN = c-debug
|
||||||
ASAN = -lasan
|
# ASAN = -lasan
|
||||||
else
|
else
|
||||||
CFLAGS_BUILD = -O2 -march=native
|
CFLAGS_BUILD = -O2 -march=native -Wstringop-overflow=0
|
||||||
GLAD_GEN = c
|
GLAD_GEN = c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@@ -32,13 +32,13 @@ endif
|
|||||||
ifeq ($(INSTALL),unix)
|
ifeq ($(INSTALL),unix)
|
||||||
CFLAGS_INSTALL = -DGLAVA_UNIX
|
CFLAGS_INSTALL = -DGLAVA_UNIX
|
||||||
ifdef XDG_CONFIG_DIRS
|
ifdef XDG_CONFIG_DIRS
|
||||||
SHADER_DIR = $(firstword $(subst :, ,$XDG_CONFIG_DIR))/glava
|
SHADER_DIR = $(firstword $(subst :, ,$(XDG_CONFIG_DIRS)))/glava
|
||||||
else
|
else
|
||||||
SHADER_DIR = etc/xdg/glava
|
SHADER_DIR = etc/xdg/glava
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef DISABLE_GLFW
|
ifdef ENABLE_GLFW
|
||||||
CFLAGS_GLFW = -DGLAVA_GLFW
|
CFLAGS_GLFW = -DGLAVA_GLFW
|
||||||
LDFLAGS_GLFW = -lglfw
|
LDFLAGS_GLFW = -lglfw
|
||||||
endif
|
endif
|
||||||
|
|||||||
23
README.md
23
README.md
@@ -19,7 +19,6 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla
|
|||||||
|
|
||||||
- X11
|
- X11
|
||||||
- PulseAudio
|
- PulseAudio
|
||||||
- GLFW 3.1+ (optional, disable with `DISABLE_GLFW=1`)
|
|
||||||
- Linux or BSD
|
- Linux or BSD
|
||||||
|
|
||||||
**Additional compile time requirements:**
|
**Additional compile time requirements:**
|
||||||
@@ -28,9 +27,13 @@ You can pass `BUILD=debug` to the makefile for debug builds of both glad and gla
|
|||||||
- python (required to generate bindings with glad)
|
- python (required to generate bindings with glad)
|
||||||
- GCC (this program uses GNU C features)
|
- GCC (this program uses GNU C features)
|
||||||
|
|
||||||
|
**Optional requirements:**
|
||||||
|
|
||||||
|
- GLFW 3.1+ (optional, enable with `ENABLE_GLFW=1`)
|
||||||
|
|
||||||
**Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile GLava:
|
**Ubuntu/Debian users:** the following command ensures you have all the needed packages and headers to compile GLava:
|
||||||
```bash
|
```bash
|
||||||
sudo apt-get install libpulse0 libpulse-dev libglfw3 libglfw3-dev libglx0 libxext6 libxext-dev python make gcc
|
sudo apt-get install libpulse0 libpulse-dev libglfw3 libglfw3-dev libxext6 libxext-dev libxcomposite-dev python make gcc
|
||||||
```
|
```
|
||||||
|
|
||||||
## [Configuration](https://github.com/wacossusca34/glava/wiki)
|
## [Configuration](https://github.com/wacossusca34/glava/wiki)
|
||||||
@@ -39,9 +42,9 @@ GLava will start by looking for an entry point in the user configuration folder
|
|||||||
|
|
||||||
You should start by running `glava --copy-config`. This will copy over default configuration files and create symlinks to modules in your user config folder. GLava will either load system configuration files or the user provided ones, so it's not advised to copy these files selectively.
|
You should start by running `glava --copy-config`. This will copy over default configuration files and create symlinks to modules in your user config folder. GLava will either load system configuration files or the user provided ones, so it's not advised to copy these files selectively.
|
||||||
|
|
||||||
To embed GLava in your desktop (for EWMH compliant window managers), use `#request setxwintype "desktop"` and then position it accordingly with `#request setgeometry x y width height`. You may want to also use `#request setforcegeometry true` for some window managers.
|
To embed GLava in your desktop (for EWMH compliant window managers), run it with the `--desktop` flag and then position it accordingly with `#request setgeometry x y width height` in your `rc.glsl`.
|
||||||
|
|
||||||
\* On an XDG compliant Linux or BSD system. OSX will use `/Library/glava` and `~/Library/Preferences/glava` instead.
|
\* On an XDG compliant Linux or BSD system.
|
||||||
|
|
||||||
## Desktop window compatibility
|
## Desktop window compatibility
|
||||||
|
|
||||||
@@ -50,21 +53,23 @@ GLava aims to be compatible with _most_ EWMH compliant window managers. Below is
|
|||||||
| WM | ! | Details
|
| WM | ! | Details
|
||||||
| :---: | --- | --- |
|
| :---: | --- | --- |
|
||||||
| Mutter (GNOME, Budgie) |  | `"native"` (default) opacity should be used
|
| Mutter (GNOME, Budgie) |  | `"native"` (default) opacity should be used
|
||||||
|
| KWin (KDE) |  | No issues
|
||||||
| Openbox (LXDE or standalone) |  | No issues
|
| Openbox (LXDE or standalone) |  | No issues
|
||||||
| Xfwm (XFCE) |  | Untested, but should work without issues
|
| Xfwm (XFCE) |  | No issues
|
||||||
| Fluxbox |  | Untested, but should work without issues
|
| Fluxbox |  | No issues
|
||||||
| IceWM |  | No issues
|
| IceWM |  | No issues
|
||||||
| Bspwm |  | No issues
|
| Bspwm |  | No issues
|
||||||
| Herbstluftwm |  | `hc rule windowtype~'_NET_WM_WINDOW_TYPE_DESKTOP' manage=off` can be used to unmanage desktop windows
|
| Herbstluftwm |  | `hc rule windowtype~'_NET_WM_WINDOW_TYPE_DESKTOP' manage=off` can be used to unmanage desktop windows
|
||||||
|
| Unity |  | No issues
|
||||||
| AwesomeWM |  | Can still be focused, may require other changes to config depending on layout
|
| AwesomeWM |  | Can still be focused, may require other changes to config depending on layout
|
||||||
| kwin (KDE) |  | [Issues with workspaces and stacking](https://github.com/wacossusca34/glava/issues/4), needs further testing
|
|
||||||
| i3 (and i3-gaps) |  | [i3 does not respect the `"desktop"` window type](https://github.com/wacossusca34/glava/issues/6)
|
| i3 (and i3-gaps) |  | [i3 does not respect the `"desktop"` window type](https://github.com/wacossusca34/glava/issues/6)
|
||||||
| EXWM |  | EXWM does not have a desktop, and forces window decorations
|
| EXWM |  | EXWM does not have a desktop, and forces window decorations
|
||||||
| Unity |  | Needs testing
|
|
||||||
| Enlightenment |  | Needs testing
|
| Enlightenment |  | Needs testing
|
||||||
| Xmonad |  | Needs testing
|
| Xmonad |  | Needs testing
|
||||||
| Any non EWMH-compliant WM |  | Window types and hints will not work if the window manager does not support the EWMH standards.
|
| Any non EWMH-compliant WM |  | Window types and hints will not work if the window manager does not support the EWMH standards.
|
||||||
|
|
||||||
|
Note that some WMs listed without issues have specific overrides when using the `--desktop` flag. See `shaders/env_*.glsl` files for details.
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
GLava is licensed under the terms of the GPLv3. GLava includes some (heavily modified) source code that originated from [cava](https://github.com/karlstav/cava), which was initially provided under the MIT license. The source files that originated from cava are the following:
|
GLava is licensed under the terms of the GPLv3. GLava includes some (heavily modified) source code that originated from [cava](https://github.com/karlstav/cava), which was initially provided under the MIT license. The source files that originated from cava are the following:
|
||||||
@@ -86,4 +91,4 @@ The below copyright applies for the modifications to the files listed above, and
|
|||||||
|
|
||||||
## Porting
|
## Porting
|
||||||
|
|
||||||
GLava was built with GLFW, making the graphics frontend mostly compatible if it were to be ported to Windows, and I have taken all the Xlib-specific code and placed it into `xwin.c` if anyone decides they wish to attempt at a port.
|
GLava was built with GLFW, making the graphics frontend mostly compatible if it were to be ported to Windows, and I have taken most of the Xlib-specific code and placed it into `xwin.c` if anyone decides they wish to attempt at a port.
|
||||||
|
|||||||
2
glad
2
glad
Submodule glad updated: ec01ac515d...c33992f23c
19
glava.c
19
glava.c
@@ -159,6 +159,9 @@ static const char* help_str =
|
|||||||
"Available arguments:\n"
|
"Available arguments:\n"
|
||||||
"-h, --help show this help and exit\n"
|
"-h, --help show this help and exit\n"
|
||||||
"-v, --verbose enables printing of detailed information about execution\n"
|
"-v, --verbose enables printing of detailed information about execution\n"
|
||||||
|
"-d, --desktop enables running glava as a desktop window by detecting the\n"
|
||||||
|
" desktop environment and setting the appropriate properties\n"
|
||||||
|
" automatically. Can override properties in \"rc.glsl\".\n"
|
||||||
"-m, --force-mod=NAME forces the specified module to load instead, ignoring any\n"
|
"-m, --force-mod=NAME forces the specified module to load instead, ignoring any\n"
|
||||||
" `#request mod` instances in the entry point.\n"
|
" `#request mod` instances in the entry point.\n"
|
||||||
"-e, --entry=NAME specifies the name of the file to look for when loading shaders,\n"
|
"-e, --entry=NAME specifies the name of the file to look for when loading shaders,\n"
|
||||||
@@ -174,10 +177,11 @@ static const char* help_str =
|
|||||||
GLAVA_VERSION_STRING "\n"
|
GLAVA_VERSION_STRING "\n"
|
||||||
" -- Copyright (C) 2017 Levi Webb\n";
|
" -- Copyright (C) 2017 Levi Webb\n";
|
||||||
|
|
||||||
static const char* opt_str = "hvVe:Cm:b:";
|
static const char* opt_str = "dhvVe:Cm:b:";
|
||||||
static struct option p_opts[] = {
|
static struct option p_opts[] = {
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"verbose", no_argument, 0, 'v'},
|
{"verbose", no_argument, 0, 'v'},
|
||||||
|
{"desktop", no_argument, 0, 'd'},
|
||||||
{"entry", required_argument, 0, 'e'},
|
{"entry", required_argument, 0, 'e'},
|
||||||
{"force-mod", required_argument, 0, 'm'},
|
{"force-mod", required_argument, 0, 'm'},
|
||||||
{"copy-config", no_argument, 0, 'C'},
|
{"copy-config", no_argument, 0, 'C'},
|
||||||
@@ -195,14 +199,14 @@ int main(int argc, char** argv) {
|
|||||||
const char* force = NULL;
|
const char* force = NULL;
|
||||||
const char* backend = NULL;
|
const char* backend = NULL;
|
||||||
const char* system_shader_paths[] = { user_path, install_path, NULL };
|
const char* system_shader_paths[] = { user_path, install_path, NULL };
|
||||||
bool verbose = false;
|
bool verbose = false, copy_mode = false, desktop = false;
|
||||||
bool copy_mode = false;
|
|
||||||
|
|
||||||
int c, idx;
|
int c, idx;
|
||||||
while ((c = getopt_long(argc, argv, opt_str, p_opts, &idx)) != -1) {
|
while ((c = getopt_long(argc, argv, opt_str, p_opts, &idx)) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'v': verbose = true; break;
|
case 'v': verbose = true; break;
|
||||||
case 'C': copy_mode = true; break;
|
case 'C': copy_mode = true; break;
|
||||||
|
case 'd': desktop = true; break;
|
||||||
case 'e': entry = optarg; break;
|
case 'e': entry = optarg; break;
|
||||||
case 'm': force = optarg; break;
|
case 'm': force = optarg; break;
|
||||||
case 'b': backend = optarg; break;
|
case 'b': backend = optarg; break;
|
||||||
@@ -224,7 +228,7 @@ int main(int argc, char** argv) {
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer* r = rd_new(system_shader_paths, entry, force, backend);
|
renderer* r = rd_new(system_shader_paths, entry, force, backend, desktop);
|
||||||
|
|
||||||
float b0[r->bufsize_request], b1[r->bufsize_request];
|
float b0[r->bufsize_request], b1[r->bufsize_request];
|
||||||
size_t t;
|
size_t t;
|
||||||
@@ -244,7 +248,7 @@ int main(int argc, char** argv) {
|
|||||||
.rate = (unsigned int) r->rate_request,
|
.rate = (unsigned int) r->rate_request,
|
||||||
.format = -1,
|
.format = -1,
|
||||||
.terminate = 0,
|
.terminate = 0,
|
||||||
.channels = 2,
|
.channels = r->mirror_input ? 1 : 2,
|
||||||
.audio_out_r = b0,
|
.audio_out_r = b0,
|
||||||
.audio_out_l = b1,
|
.audio_out_l = b1,
|
||||||
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
.mutex = PTHREAD_MUTEX_INITIALIZER,
|
||||||
@@ -279,10 +283,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
pthread_mutex_unlock(&audio.mutex);
|
pthread_mutex_unlock(&audio.mutex);
|
||||||
|
|
||||||
/* Only render if needed (ie. stop rendering when fullscreen windows are focused) */
|
if (!rd_update(r, lb, rb, r->bufsize_request, modified)) {
|
||||||
if (xwin_should_render(r)) {
|
|
||||||
rd_update(r, lb, rb, r->bufsize_request, modified);
|
|
||||||
} else {
|
|
||||||
/* Sleep for 50ms and then attempt to render again */
|
/* Sleep for 50ms and then attempt to render again */
|
||||||
struct timespec tv = {
|
struct timespec tv = {
|
||||||
.tv_sec = 0, .tv_nsec = 50 * 1000000
|
.tv_sec = 0, .tv_nsec = 50 * 1000000
|
||||||
|
|||||||
@@ -70,7 +70,8 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
size_t states_sz,
|
size_t states_sz,
|
||||||
int d, int h,
|
int d, int h,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
int version_major, int version_minor) {
|
int version_major, int version_minor,
|
||||||
|
bool clickthrough) {
|
||||||
|
|
||||||
GLFWwindow* w;
|
GLFWwindow* w;
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ static void swap_buffers(GLFWwindow* w) {
|
|||||||
glfwSwapBuffers(w);
|
glfwSwapBuffers(w);
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
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); }
|
||||||
@@ -132,6 +133,9 @@ static void get_pos (GLFWwindow* w, int* x, int* y) { glfwGetWindowPo
|
|||||||
static double get_time (GLFWwindow* w) { return glfwGetTime(); }
|
static double get_time (GLFWwindow* w) { return glfwGetTime(); }
|
||||||
static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); }
|
static void set_time (GLFWwindow* w, double time) { glfwSetTime(time); }
|
||||||
static void set_swap (int i) { glfwSwapInterval(i); }
|
static void set_swap (int i) { glfwSwapInterval(i); }
|
||||||
|
static void raise (GLFWwindow* w) { glfwShowWindow(w); }
|
||||||
|
|
||||||
|
static const char* get_environment(void) { return xwin_detect_wm(&wcb_glfw); }
|
||||||
|
|
||||||
WCB_ATTACH("glfw", wcb_glfw);
|
WCB_ATTACH("glfw", wcb_glfw);
|
||||||
|
|
||||||
|
|||||||
64
glx_wcb.c
64
glx_wcb.c
@@ -176,6 +176,8 @@ struct glxwin {
|
|||||||
bool should_close;
|
bool should_close;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Atom ATOM__MOTIF_WM_HINTS, ATOM_WM_DELETE_WINDOW, ATOM_WM_PROTOCOLS, ATOM__NET_ACTIVE_WINDOW;
|
||||||
|
|
||||||
static void init(void) {
|
static void init(void) {
|
||||||
display = XOpenDisplay(NULL);
|
display = XOpenDisplay(NULL);
|
||||||
if (!display) {
|
if (!display) {
|
||||||
@@ -210,6 +212,8 @@ static void init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define resolve(name) do { name = (typeof(name)) resolve_f(#name); } while (0)
|
#define resolve(name) do { name = (typeof(name)) resolve_f(#name); } while (0)
|
||||||
|
#define intern(name, only_if_exists) \
|
||||||
|
do { ATOM_##name = XInternAtom(display, #name, only_if_exists); } while (0)
|
||||||
|
|
||||||
resolve(glXChooseFBConfig);
|
resolve(glXChooseFBConfig);
|
||||||
resolve(glXGetVisualFromFBConfig);
|
resolve(glXGetVisualFromFBConfig);
|
||||||
@@ -218,7 +222,13 @@ static void init(void) {
|
|||||||
resolve(glXGetCurrentDrawable);
|
resolve(glXGetCurrentDrawable);
|
||||||
resolve(glXGetProcAddressARB);
|
resolve(glXGetProcAddressARB);
|
||||||
resolve(glXSwapBuffers);
|
resolve(glXSwapBuffers);
|
||||||
|
|
||||||
|
intern(_MOTIF_WM_HINTS, false);
|
||||||
|
intern(WM_DELETE_WINDOW, true);
|
||||||
|
intern(WM_PROTOCOLS, true);
|
||||||
|
intern(_NET_ACTIVE_WINDOW, false);
|
||||||
|
|
||||||
|
#undef intern
|
||||||
#undef resolve
|
#undef resolve
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,10 +242,8 @@ static void apply_decorations(Window w) {
|
|||||||
|
|
||||||
hints.flags = 2;
|
hints.flags = 2;
|
||||||
hints.decorations = 0;
|
hints.decorations = 0;
|
||||||
|
|
||||||
Atom motif = XInternAtom(display, "_MOTIF_WM_HINTS", false);
|
|
||||||
|
|
||||||
XChangeProperty(display, w, motif, motif, 32, PropModeReplace,
|
XChangeProperty(display, w, ATOM__MOTIF_WM_HINTS, ATOM__MOTIF_WM_HINTS, 32, PropModeReplace,
|
||||||
(unsigned char*) &hints, sizeof(hints) / sizeof(long));
|
(unsigned char*) &hints, sizeof(hints) / sizeof(long));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,7 +253,8 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
size_t states_sz,
|
size_t states_sz,
|
||||||
int d, int h,
|
int d, int h,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
int version_major, int version_minor) {
|
int version_major, int version_minor,
|
||||||
|
bool clickthrough) {
|
||||||
struct glxwin* w = malloc(sizeof(struct glxwin));
|
struct glxwin* w = malloc(sizeof(struct glxwin));
|
||||||
w->time = 0.0D;
|
w->time = 0.0D;
|
||||||
w->should_close = false;
|
w->should_close = false;
|
||||||
@@ -299,7 +308,7 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
XFree(xvi);
|
XFree(xvi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best == -1) {
|
if (best == -1) {
|
||||||
fprintf(stderr, "Could not find suitable format for FBConfig\n");
|
fprintf(stderr, "Could not find suitable format for FBConfig\n");
|
||||||
abort();
|
abort();
|
||||||
@@ -311,11 +320,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;
|
attr.event_mask = ExposureMask | KeyPressMask | StructureNotifyMask | PropertyChangeMask;
|
||||||
attr.background_pixmap = None;
|
attr.background_pixmap = None;
|
||||||
attr.border_pixel = 0;
|
attr.border_pixel = 0;
|
||||||
|
|
||||||
if (!(w->w = XCreateWindow(display, DefaultRootWindow(display),
|
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,
|
CWColormap | CWEventMask | CWBackPixmap | CWBorderPixel,
|
||||||
@@ -345,14 +354,11 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
XFree(vi);
|
XFree(vi);
|
||||||
|
|
||||||
XStoreName(display, w->w, name);
|
XStoreName(display, w->w, name);
|
||||||
|
|
||||||
Atom dwin = XInternAtom(display, "WM_DELETE_WINDOW", false);
|
|
||||||
XSetWMProtocols(display, w->w, &dwin, 1);
|
|
||||||
|
|
||||||
// XReparentWindow(display, w->w, DefaultRootWindow(display), 0, 0);
|
XSetWMProtocols(display, w->w, &ATOM_WM_DELETE_WINDOW, 1);
|
||||||
|
|
||||||
/* Eliminate the window's effective region */
|
/* Eliminate the window's effective region */
|
||||||
if (desktop){
|
if (desktop || clickthrough) {
|
||||||
int ignored;
|
int ignored;
|
||||||
if (XShapeQueryExtension(display, &ignored, &ignored)) {
|
if (XShapeQueryExtension(display, &ignored, &ignored)) {
|
||||||
Region region;
|
Region region;
|
||||||
@@ -389,9 +395,34 @@ static void* create_and_bind(const char* name, const char* class,
|
|||||||
|
|
||||||
if (glXSwapIntervalEXT) glXSwapIntervalEXT(display, drawable, swap);
|
if (glXSwapIntervalEXT) glXSwapIntervalEXT(display, drawable, swap);
|
||||||
|
|
||||||
|
// XSelectInput(display, DefaultRootWindow(display), VisibilityChangeMask | PropertyChangeMask);
|
||||||
|
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void raise(struct glxwin* w) {
|
||||||
|
XClientMessageEvent ev = {
|
||||||
|
.type = ClientMessage,
|
||||||
|
.serial = 0,
|
||||||
|
.send_event = true,
|
||||||
|
.display = display,
|
||||||
|
.window = w->w,
|
||||||
|
.message_type = ATOM__NET_ACTIVE_WINDOW,
|
||||||
|
.format = 32,
|
||||||
|
.data = { .l = {
|
||||||
|
[0] = 1, /* source indication -- `1` when coming from an application */
|
||||||
|
[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) */
|
||||||
|
XSendEvent(display, DefaultRootWindow(display), false, StructureNotifyMask, (XEvent*) &ev);
|
||||||
|
/* Raise the client in the X11 stacking order (sometimes works, can be blocked by the WM) */
|
||||||
|
XRaiseWindow(display, w->w);
|
||||||
|
XFlush(display);
|
||||||
|
}
|
||||||
|
|
||||||
static void set_swap (int _swap) { swap = _swap; }
|
static void set_swap (int _swap) { swap = _swap; }
|
||||||
static void set_floating (bool _floating) { floating = _floating; }
|
static void set_floating (bool _floating) { floating = _floating; }
|
||||||
static void set_decorated (bool _decorated) { decorated = _decorated; }
|
static void set_decorated (bool _decorated) { decorated = _decorated; }
|
||||||
@@ -420,10 +451,11 @@ static void swap_buffers(struct glxwin* w) {
|
|||||||
XNextEvent(display, &ev);
|
XNextEvent(display, &ev);
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case ClientMessage:
|
case ClientMessage:
|
||||||
if (ev.xclient.message_type == XInternAtom(display, "WM_PROTOCOLS", 1)
|
if (ev.xclient.message_type == ATOM_WM_PROTOCOLS
|
||||||
&& ev.xclient.data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", 1)) {
|
&& ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW) {
|
||||||
w->should_close = true;
|
w->should_close = true;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -454,6 +486,8 @@ static void set_time (struct glxwin* w, double time) { w->time = get_t
|
|||||||
static Display* get_x11_display(struct glxwin* w) { return display; }
|
static Display* get_x11_display(struct glxwin* w) { return display; }
|
||||||
static Window get_x11_window (struct glxwin* w) { return w->w; }
|
static Window get_x11_window (struct glxwin* w) { return w->w; }
|
||||||
|
|
||||||
|
static const char* get_environment(void) { return xwin_detect_wm(&wcb_glx); }
|
||||||
|
|
||||||
WCB_ATTACH("glx", wcb_glx);
|
WCB_ATTACH("glx", wcb_glx);
|
||||||
|
|
||||||
#endif /* GLAVA_GLX */
|
#endif /* GLAVA_GLX */
|
||||||
|
|||||||
@@ -168,7 +168,11 @@ void* input_pulse(void* data) {
|
|||||||
|
|
||||||
int idx = (fsz - (ssz / 4)) + n;
|
int idx = (fsz - (ssz / 4)) + n;
|
||||||
|
|
||||||
if (audio->channels == 1) bl[idx] = (buf[i] + buf[i + 1]) / 2;
|
if (audio->channels == 1) {
|
||||||
|
float sample = (buf[i] + buf[i + 1]) / 2;
|
||||||
|
bl[idx] = sample;
|
||||||
|
br[idx] = sample;
|
||||||
|
}
|
||||||
|
|
||||||
/* stereo storing channels in buffer */
|
/* stereo storing channels in buffer */
|
||||||
if (audio->channels == 2) {
|
if (audio->channels == 2) {
|
||||||
|
|||||||
113
render.c
113
render.c
@@ -108,8 +108,9 @@ struct gl_data {
|
|||||||
int rate; /* framerate */
|
int rate; /* framerate */
|
||||||
double tcounter;
|
double tcounter;
|
||||||
int fcounter, ucounter, kcounter;
|
int fcounter, ucounter, kcounter;
|
||||||
bool print_fps, avg_window, interpolate, force_geometry, copy_desktop,
|
bool print_fps, avg_window, interpolate, force_geometry, force_raised,
|
||||||
smooth_pass, premultiply_alpha;
|
copy_desktop, smooth_pass, premultiply_alpha, check_fullscreen,
|
||||||
|
clickthrough;
|
||||||
void** t_data;
|
void** t_data;
|
||||||
float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio,
|
float gravity_step, target_spu, fr, ur, smooth_distance, smooth_ratio,
|
||||||
smooth_factor, fft_scale, fft_cutoff;
|
smooth_factor, fft_scale, fft_cutoff;
|
||||||
@@ -680,11 +681,15 @@ static struct gl_bind_src* lookup_bind_src(const char* str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct renderer* rd_new(const char** paths, const char* entry,
|
struct renderer* rd_new(const char** paths, const char* entry,
|
||||||
const char* force_mod, const char* force_backend) {
|
const char* force_mod, const char* force_backend,
|
||||||
|
bool auto_desktop) {
|
||||||
|
|
||||||
|
xwin_wait_for_wm();
|
||||||
|
|
||||||
renderer* r = malloc(sizeof(struct renderer));
|
renderer* r = malloc(sizeof(struct renderer));
|
||||||
*r = (struct renderer) {
|
*r = (struct renderer) {
|
||||||
.alive = true,
|
.alive = true,
|
||||||
|
.mirror_input = false,
|
||||||
.gl = malloc(sizeof(struct gl_data)),
|
.gl = malloc(sizeof(struct gl_data)),
|
||||||
.bufsize_request = 8192,
|
.bufsize_request = 8192,
|
||||||
.rate_request = 22000,
|
.rate_request = 22000,
|
||||||
@@ -711,6 +716,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
.gravity_step = 4.2,
|
.gravity_step = 4.2,
|
||||||
.interpolate = true,
|
.interpolate = true,
|
||||||
.force_geometry = false,
|
.force_geometry = false,
|
||||||
|
.force_raised = false,
|
||||||
.smooth_factor = 0.025,
|
.smooth_factor = 0.025,
|
||||||
.smooth_distance = 0.01,
|
.smooth_distance = 0.01,
|
||||||
.smooth_ratio = 4,
|
.smooth_ratio = 4,
|
||||||
@@ -718,11 +724,13 @@ 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,
|
||||||
.smooth_pass = true,
|
.smooth_pass = true,
|
||||||
.fft_scale = 10.2F,
|
.fft_scale = 10.2F,
|
||||||
.fft_cutoff = 0.3F,
|
.fft_cutoff = 0.3F,
|
||||||
.geometry = { 0, 0, 500, 400 },
|
.geometry = { 0, 0, 500, 400 },
|
||||||
.clear_color = { 0.0F, 0.0F, 0.0F, 0.0F }
|
.clear_color = { 0.0F, 0.0F, 0.0F, 0.0F },
|
||||||
|
.clickthrough = false
|
||||||
};
|
};
|
||||||
|
|
||||||
bool forced = force_backend != NULL;
|
bool forced = force_backend != NULL;
|
||||||
@@ -786,7 +794,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
char* xwintype = NULL, * wintitle = "GLava";
|
char* xwintype = NULL, * wintitle = "GLava";
|
||||||
char** xwinstates = malloc(1);
|
char** xwinstates = malloc(1);
|
||||||
size_t xwinstates_sz = 0;
|
size_t xwinstates_sz = 0;
|
||||||
bool loading_module = true, loading_smooth_pass = false;
|
bool loading_module = true, loading_smooth_pass = false, loading_presets = false;;
|
||||||
struct gl_sfbo* current = NULL;
|
struct gl_sfbo* current = NULL;
|
||||||
size_t t_count = 0;
|
size_t t_count = 0;
|
||||||
|
|
||||||
@@ -816,6 +824,14 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "setmirror", .fmt = "b",
|
||||||
|
.handler = RHANDLER(name, args, { r->mirror_input = *(bool*) args[0]; })
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "setfullscreencheck", .fmt = "b",
|
||||||
|
.handler = RHANDLER(name, args, { gl->check_fullscreen = *(bool*) args[0]; })
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.name = "setbg", .fmt = "s",
|
.name = "setbg", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
@@ -845,7 +861,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
if (loading_module && !force_mod) {
|
if (loading_module && !force_mod) {
|
||||||
size_t len = strlen((char*) args[0]);
|
size_t len = strlen((char*) args[0]);
|
||||||
char* str = malloc(sizeof(char) * (strlen((char*) args[0]) + 1));
|
char* str = malloc(sizeof(char) * (len + 1));
|
||||||
strncpy(str, (char*) args[0], len + 1);
|
strncpy(str, (char*) args[0], len + 1);
|
||||||
module = str;
|
module = str;
|
||||||
}
|
}
|
||||||
@@ -885,16 +901,22 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
{
|
{
|
||||||
.name = "addxwinstate", .fmt = "s",
|
.name = "addxwinstate", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
++xwinstates_sz;
|
if (!auto_desktop || loading_presets) {
|
||||||
xwinstates = realloc(xwinstates, sizeof(*xwinstates) * xwinstates_sz);
|
++xwinstates_sz;
|
||||||
xwinstates[xwinstates_sz - 1] = strdup((char*) args[0]);
|
xwinstates = realloc(xwinstates, sizeof(*xwinstates) * xwinstates_sz);
|
||||||
|
xwinstates[xwinstates_sz - 1] = strdup((char*) args[0]);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ .name = "setsource", .fmt = "s",
|
{ .name = "setsource", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, {
|
.handler = RHANDLER(name, args, {
|
||||||
r->audio_source_request = strdup((char*) args[0]); }) },
|
r->audio_source_request = strdup((char*) args[0]); }) },
|
||||||
|
{ .name = "setclickthrough", .fmt = "b",
|
||||||
|
.handler = RHANDLER(name, args, { gl->clickthrough = *(bool*) args[0]; }) },
|
||||||
{ .name = "setforcegeometry", .fmt = "b",
|
{ .name = "setforcegeometry", .fmt = "b",
|
||||||
.handler = RHANDLER(name, args, { gl->force_geometry = *(bool*) args[0]; }) },
|
.handler = RHANDLER(name, args, { gl->force_geometry = *(bool*) args[0]; }) },
|
||||||
|
{ .name = "setforceraised", .fmt = "b",
|
||||||
|
.handler = RHANDLER(name, args, { gl->force_raised = *(bool*) args[0]; }) },
|
||||||
{ .name = "setxwintype", .fmt = "s",
|
{ .name = "setxwintype", .fmt = "s",
|
||||||
.handler = RHANDLER(name, args, { xwintype = strdup((char*) args[0]); }) },
|
.handler = RHANDLER(name, args, { xwintype = strdup((char*) args[0]); }) },
|
||||||
{ .name = "setshaderversion", .fmt = "i",
|
{ .name = "setshaderversion", .fmt = "i",
|
||||||
@@ -1023,12 +1045,18 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
directories will be populated with symlinks to the installed modules. */
|
directories will be populated with symlinks to the installed modules. */
|
||||||
|
|
||||||
const char* data;
|
const char* data;
|
||||||
size_t d_len;
|
const char* env = gl->wcb->get_environment();
|
||||||
|
size_t d_len, e_len;
|
||||||
|
|
||||||
for (const char** i = paths; (data = *i) != NULL; ++i) {
|
for (const char** i = paths; (data = *i) != NULL; ++i) {
|
||||||
d_len = strlen(data);
|
d_len = strlen(data);
|
||||||
|
e_len = env ? strlen(env) : 0;
|
||||||
size_t se_len = strlen(entry);
|
size_t se_len = strlen(entry);
|
||||||
size_t bsz = se_len + d_len + 2;
|
/* '/' + \0 + "env_" + ".glsl" = 11 char padding, min 7 for "default" */
|
||||||
|
size_t bsz = se_len + 11;
|
||||||
|
if (d_len > e_len && d_len >= 7) bsz += d_len;
|
||||||
|
else if (e_len >= 7) bsz += e_len;
|
||||||
|
else bsz += 7;
|
||||||
char se_buf[bsz];
|
char se_buf[bsz];
|
||||||
snprintf(se_buf, bsz, "%s/%s", data, entry);
|
snprintf(se_buf, bsz, "%s/%s", data, entry);
|
||||||
|
|
||||||
@@ -1040,7 +1068,7 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
if (errno != ENOENT &&
|
if (errno != ENOENT &&
|
||||||
errno != ENOTDIR &&
|
errno != ENOTDIR &&
|
||||||
errno != ELOOP ) {
|
errno != ELOOP ) {
|
||||||
fprintf(stderr, "failed to load entry '%s': %s\n", se_buf, strerror(errno));
|
fprintf(stderr, "Failed to load entry '%s': %s\n", se_buf, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
} else continue;
|
} else continue;
|
||||||
}
|
}
|
||||||
@@ -1058,6 +1086,42 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
ext_process(&ext, se_buf);
|
ext_process(&ext, se_buf);
|
||||||
|
|
||||||
munmap((void*) map, st.st_size);
|
munmap((void*) map, st.st_size);
|
||||||
|
|
||||||
|
if (auto_desktop) {
|
||||||
|
if (env) {
|
||||||
|
snprintf(se_buf, bsz, "%s/env_%s.glsl", data, env);
|
||||||
|
fd = open(se_buf, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
if (errno != ENOENT &&
|
||||||
|
errno != ENOTDIR &&
|
||||||
|
errno != ELOOP) {
|
||||||
|
fprintf(stderr, "Failed to load desktop environment specific presets at '%s': %s\n", se_buf, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
} else {
|
||||||
|
printf("No presets for current desktop environment (\"%s\"), using default presets for embedding\n", env);
|
||||||
|
snprintf(se_buf, bsz, "%s/env_default.glsl", data);
|
||||||
|
fd = open(se_buf, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "Failed to load default presets at '%s': %s\n", se_buf, strerror(errno));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fstat(fd, &st);
|
||||||
|
map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
|
ext.source = map;
|
||||||
|
ext.source_len = st.st_size;
|
||||||
|
|
||||||
|
loading_presets = true;
|
||||||
|
ext_process(&ext, se_buf);
|
||||||
|
loading_presets = false;
|
||||||
|
|
||||||
|
munmap((void*) map, st.st_size);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Failed to detect the desktop environment! Is the window manager EWMH compliant?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1070,13 +1134,10 @@ struct renderer* rd_new(const char** paths, const char* entry,
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(gl->w = gl->wcb->create_and_bind(wintitle, "GLava", xwintype,
|
gl->w = gl->wcb->create_and_bind(wintitle, "GLava", xwintype, (const char**) xwinstates, xwinstates_sz,
|
||||||
(const char**) xwinstates, xwinstates_sz,
|
gl->geometry[2], gl->geometry[3], gl->geometry[0], gl->geometry[1],
|
||||||
gl->geometry[2], gl->geometry[3],
|
context_version_major, context_version_minor, gl->clickthrough);
|
||||||
gl->geometry[0], gl->geometry[1],
|
if (!gl->w) abort();
|
||||||
context_version_major, context_version_minor))) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xwintype) free(xwintype);
|
if (xwintype) free(xwintype);
|
||||||
if (xwinstates) free(xwinstates);
|
if (xwinstates) free(xwinstates);
|
||||||
@@ -1269,13 +1330,17 @@ void rd_time(struct renderer* r) {
|
|||||||
gl->wcb->set_time(gl->w, 0.0D); /* reset time for measuring this frame */
|
gl->wcb->set_time(gl->w, 0.0D); /* reset time for measuring this frame */
|
||||||
}
|
}
|
||||||
|
|
||||||
void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modified) {
|
bool rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modified) {
|
||||||
struct gl_data* gl = r->gl;
|
struct gl_data* gl = r->gl;
|
||||||
size_t t, a, fbsz = bsz * sizeof(float);
|
size_t t, a, fbsz = bsz * sizeof(float);
|
||||||
|
|
||||||
r->alive = !gl->wcb->should_close(gl->w);
|
r->alive = !gl->wcb->should_close(gl->w);
|
||||||
if (!r->alive)
|
if (!r->alive)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
|
/* Stop rendering when fullscreen windows are focused */
|
||||||
|
if (gl->check_fullscreen && !xwin_should_render(r))
|
||||||
|
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 */
|
||||||
float uratio = (gl->ur / gl->fr); /* update : framerate ratio */
|
float uratio = (gl->ur / gl->fr); /* update : framerate ratio */
|
||||||
@@ -1617,10 +1682,16 @@ void rd_update(struct renderer* r, float* lb, float* rb, size_t bsz, bool modifi
|
|||||||
gl->geometry[0], gl->geometry[1],
|
gl->geometry[0], gl->geometry[1],
|
||||||
gl->geometry[2], gl->geometry[3]);
|
gl->geometry[2], gl->geometry[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gl->force_raised) {
|
||||||
|
gl->wcb->raise(gl->w);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restore interpolation settings */
|
/* Restore interpolation settings */
|
||||||
gl->interpolate = old_interpolate;
|
gl->interpolate = old_interpolate;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* rd_get_impl_window (struct renderer* r) { return r->gl->w; }
|
void* rd_get_impl_window (struct renderer* r) { return r->gl->w; }
|
||||||
|
|||||||
14
render.h
14
render.h
@@ -5,15 +5,16 @@
|
|||||||
struct gl_data;
|
struct gl_data;
|
||||||
|
|
||||||
typedef struct renderer {
|
typedef struct renderer {
|
||||||
bool alive;
|
bool alive, mirror_input;
|
||||||
size_t bufsize_request, rate_request, samplesize_request;
|
size_t bufsize_request, rate_request, samplesize_request;
|
||||||
char* audio_source_request;
|
char* audio_source_request;
|
||||||
struct gl_data* gl;
|
struct gl_data* gl;
|
||||||
} renderer;
|
} renderer;
|
||||||
|
|
||||||
struct renderer* rd_new (const char** paths, const char* entry,
|
struct renderer* rd_new (const char** paths, const char* entry,
|
||||||
const char* force_mod, const char* force_backend);
|
const char* force_mod, const char* force_backend,
|
||||||
void rd_update (struct renderer*, float* lb, float* rb,
|
bool auto_desktop);
|
||||||
|
bool rd_update (struct renderer*, float* lb, float* rb,
|
||||||
size_t bsz, bool modified);
|
size_t bsz, bool modified);
|
||||||
void rd_destroy (struct renderer*);
|
void rd_destroy (struct renderer*);
|
||||||
void rd_time (struct renderer*);
|
void rd_time (struct renderer*);
|
||||||
@@ -29,9 +30,11 @@ struct gl_wcb {
|
|||||||
size_t states_sz,
|
size_t states_sz,
|
||||||
int w, int h,
|
int w, int h,
|
||||||
int x, int y,
|
int x, int y,
|
||||||
int version_major, int version_minor);
|
int version_major, int version_minor,
|
||||||
|
bool clickthrough);
|
||||||
bool (*should_close) (void* ptr);
|
bool (*should_close) (void* ptr);
|
||||||
void (*swap_buffers) (void* ptr);
|
void (*swap_buffers) (void* ptr);
|
||||||
|
void (*raise) (void* ptr);
|
||||||
void (*get_pos) (void* ptr, int* x, int* y);
|
void (*get_pos) (void* ptr, int* x, int* y);
|
||||||
void (*get_fbsize) (void* ptr, int* w, int* h);
|
void (*get_fbsize) (void* ptr, int* w, int* h);
|
||||||
void (*set_geometry) (void* ptr, int x, int y, int w, int h);
|
void (*set_geometry) (void* ptr, int x, int y, int w, int h);
|
||||||
@@ -44,6 +47,7 @@ struct gl_wcb {
|
|||||||
double (*get_time) (void* ptr);
|
double (*get_time) (void* ptr);
|
||||||
void (*set_time) (void* ptr, double time);
|
void (*set_time) (void* ptr, double time);
|
||||||
void (*set_visible) (void* ptr, bool visible);
|
void (*set_visible) (void* ptr, bool visible);
|
||||||
|
const char* (*get_environment) (void);
|
||||||
#ifdef GLAVA_RDX11
|
#ifdef GLAVA_RDX11
|
||||||
Display* (*get_x11_display)(void);
|
Display* (*get_x11_display)(void);
|
||||||
Window (*get_x11_window) (void* ptr);
|
Window (*get_x11_window) (void* ptr);
|
||||||
@@ -63,6 +67,7 @@ struct gl_wcb {
|
|||||||
WCB_FUNC(create_and_bind), \
|
WCB_FUNC(create_and_bind), \
|
||||||
WCB_FUNC(should_close), \
|
WCB_FUNC(should_close), \
|
||||||
WCB_FUNC(swap_buffers), \
|
WCB_FUNC(swap_buffers), \
|
||||||
|
WCB_FUNC(raise), \
|
||||||
WCB_FUNC(set_swap), \
|
WCB_FUNC(set_swap), \
|
||||||
WCB_FUNC(get_pos), \
|
WCB_FUNC(get_pos), \
|
||||||
WCB_FUNC(get_fbsize), \
|
WCB_FUNC(get_fbsize), \
|
||||||
@@ -75,6 +80,7 @@ struct gl_wcb {
|
|||||||
WCB_FUNC(set_time), \
|
WCB_FUNC(set_time), \
|
||||||
WCB_FUNC(get_time), \
|
WCB_FUNC(get_time), \
|
||||||
WCB_FUNC(set_visible), \
|
WCB_FUNC(set_visible), \
|
||||||
|
WCB_FUNC(get_environment), \
|
||||||
WCB_FUNC(get_x11_display), \
|
WCB_FUNC(get_x11_display), \
|
||||||
WCB_FUNC(get_x11_window) \
|
WCB_FUNC(get_x11_window) \
|
||||||
}
|
}
|
||||||
|
|||||||
8
shaders/env_KWin.glsl
Normal file
8
shaders/env_KWin.glsl
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#request setdecorated false
|
||||||
|
#request setxwintype "normal"
|
||||||
|
#request addxwinstate "below"
|
||||||
|
#request addxwinstate "skip_taskbar"
|
||||||
|
#request addxwinstate "skip_pager"
|
||||||
|
#request addxwinstate "pinned"
|
||||||
|
#request setclickthrough true
|
||||||
|
|
||||||
2
shaders/env_Openbox.glsl
Normal file
2
shaders/env_Openbox.glsl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#request setxwintype "desktop"
|
||||||
|
#request addxwinstate "pinned"
|
||||||
3
shaders/env_Xfwm4.glsl
Normal file
3
shaders/env_Xfwm4.glsl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#request setxwintype "desktop"
|
||||||
|
#request addxwinstate "pinned"
|
||||||
|
#request addxwinstate "below"
|
||||||
2
shaders/env_awesome.glsl
Normal file
2
shaders/env_awesome.glsl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#request setxwintype "desktop"
|
||||||
|
#request addxwinstate "pinned"
|
||||||
1
shaders/env_default.glsl
Normal file
1
shaders/env_default.glsl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#request setxwintype "desktop"
|
||||||
@@ -21,11 +21,6 @@
|
|||||||
#request setfocused false
|
#request setfocused false
|
||||||
#request setmaximized false
|
#request setmaximized false
|
||||||
|
|
||||||
/* Force window geometry (locking the window in place), useful
|
|
||||||
for some pesky WMs that try to reposition the window when
|
|
||||||
embedding in the desktop. */
|
|
||||||
#request setforcegeometry false
|
|
||||||
|
|
||||||
/* Set window background opacity mode. Possible values are:
|
/* Set window background opacity mode. Possible values are:
|
||||||
|
|
||||||
"native" - True transparency provided by the compositor. Can
|
"native" - True transparency provided by the compositor. Can
|
||||||
@@ -41,6 +36,9 @@
|
|||||||
"none" - Disable window opacity completely. */
|
"none" - Disable window opacity completely. */
|
||||||
#request setopacity "native"
|
#request setopacity "native"
|
||||||
|
|
||||||
|
/* Whether to mirror left and right audio input channels from PulseAudio.*/
|
||||||
|
#request setmirror false
|
||||||
|
|
||||||
/* OpenGL context and GLSL shader versions, do not change unless
|
/* OpenGL context and GLSL shader versions, do not change unless
|
||||||
you *absolutely* know what you are doing. */
|
you *absolutely* know what you are doing. */
|
||||||
#request setversion 3 3
|
#request setversion 3 3
|
||||||
@@ -63,10 +61,7 @@
|
|||||||
|
|
||||||
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). More information can be found at:
|
converted to uppercase). */
|
||||||
|
|
||||||
https://standards.freedesktop.org/wm-spec/wm-spec-1.3.html#idm140130317606816
|
|
||||||
*/
|
|
||||||
#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).
|
||||||
@@ -74,7 +69,7 @@
|
|||||||
|
|
||||||
"modal", "sticky", "maximized_vert", "maximized_horz",
|
"modal", "sticky", "maximized_vert", "maximized_horz",
|
||||||
"shaded", "skip_taskbar", "skip_pager", "hidden", "fullscreen",
|
"shaded", "skip_taskbar", "skip_pager", "hidden", "fullscreen",
|
||||||
"above", "below", "demands_attention", "focused"
|
"above", "below", "demands_attention", "focused", "pinned"
|
||||||
|
|
||||||
This will add _NET_WM_STATE_(TYPE) atoms to _NET_WM_STATE,
|
This will add _NET_WM_STATE_(TYPE) atoms to _NET_WM_STATE,
|
||||||
where (TYPE) is one of the window states listed (after being
|
where (TYPE) is one of the window states listed (after being
|
||||||
@@ -89,6 +84,13 @@
|
|||||||
// #request addxwinstate "skip_taskbar"
|
// #request addxwinstate "skip_taskbar"
|
||||||
// #request addxwinstate "skip_pager"
|
// #request addxwinstate "skip_pager"
|
||||||
// #request addxwinstate "above"
|
// #request addxwinstate "above"
|
||||||
|
// #request addxwinstate "pinned"
|
||||||
|
|
||||||
|
/* (X11 only) Use the XShape extension to support clicking through
|
||||||
|
the GLava window. Useful when you want to interact with other
|
||||||
|
desktop windows (icons, menus, desktop shells). Enabled by
|
||||||
|
default when GLava itself is a desktop window. */
|
||||||
|
#request setclickthrough false
|
||||||
|
|
||||||
/* PulseAudio source. Can be a number or a name of an audio
|
/* PulseAudio source. Can be a number or a name of an audio
|
||||||
sink or device to record from. Set to "auto" to use the
|
sink or device to record from. Set to "auto" to use the
|
||||||
@@ -120,6 +122,12 @@
|
|||||||
simple set to zero (or lower) to disable the frame limiter. */
|
simple 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
|
||||||
|
focused window and halts GLava's rendering if it is
|
||||||
|
fullscreen. This prevents rendering from interfering with
|
||||||
|
other graphically intensive tasks. */
|
||||||
|
#request setfullscreencheck true
|
||||||
|
|
||||||
/* 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
|
||||||
Second'. Updates are performed when new data is submitted
|
Second'. Updates are performed when new data is submitted
|
||||||
@@ -175,6 +183,21 @@
|
|||||||
value unless you have a strange PulseAudio configuration. */
|
value unless you have a strange PulseAudio configuration. */
|
||||||
#request setsamplerate 22050
|
#request setsamplerate 22050
|
||||||
|
|
||||||
|
/* ** DEPRECATED **
|
||||||
|
Force window geometry (locking the window in place), useful
|
||||||
|
for some pesky WMs that try to reposition the window when
|
||||||
|
embedding in the desktop.
|
||||||
|
|
||||||
|
This routinely sends X11 events and should be avoided. */
|
||||||
|
#request setforcegeometry false
|
||||||
|
|
||||||
|
/* ** DEPRECATED **
|
||||||
|
Force window to be raised (focused in some WMs), useful for
|
||||||
|
WMs that have their own stacking order for desktop windows.
|
||||||
|
|
||||||
|
This routinely sends X11 events and should be avoided. */
|
||||||
|
#request setforceraised false
|
||||||
|
|
||||||
/* ** DEPRECATED **
|
/* ** DEPRECATED **
|
||||||
Scale down the audio buffer before any operations are
|
Scale down the audio buffer before any operations are
|
||||||
performed on the data. Higher values are faster.
|
performed on the data. Higher values are faster.
|
||||||
|
|||||||
150
xwin.c
150
xwin.c
@@ -8,6 +8,8 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <sys/ipc.h>
|
#include <sys/ipc.h>
|
||||||
#include <sys/shm.h>
|
#include <sys/shm.h>
|
||||||
|
|
||||||
@@ -23,11 +25,13 @@
|
|||||||
#include "render.h"
|
#include "render.h"
|
||||||
#include "xwin.h"
|
#include "xwin.h"
|
||||||
|
|
||||||
static Window find_desktop(struct renderer* r) {
|
/* Note: currently unused */
|
||||||
|
Window* xwin_get_desktop_layer(struct gl_wcb* wcb) {
|
||||||
static Window desktop;
|
static Window desktop;
|
||||||
static bool searched = false;
|
static bool searched = false;
|
||||||
if (!searched) {
|
if (!searched) {
|
||||||
Display* d = rd_get_wcb(r)->get_x11_display();
|
Display* d = wcb->get_x11_display();
|
||||||
|
Atom class = XInternAtom(d, "WM_CLASS", false);
|
||||||
desktop = DefaultRootWindow(d);
|
desktop = DefaultRootWindow(d);
|
||||||
Window _ignored, * children;
|
Window _ignored, * children;
|
||||||
unsigned int nret;
|
unsigned int nret;
|
||||||
@@ -39,18 +43,102 @@ static Window find_desktop(struct renderer* r) {
|
|||||||
if (name) {
|
if (name) {
|
||||||
/* Mutter-based window managers */
|
/* Mutter-based window managers */
|
||||||
if (!strcmp(name, "mutter guard window")) {
|
if (!strcmp(name, "mutter guard window")) {
|
||||||
printf("Using mutter guard window instead of root window\n");
|
printf("Reparenting to mutter guard window instead of root window\n");
|
||||||
// desktop = children[t];
|
desktop = children[t];
|
||||||
t = nret; /* break after */
|
t = nret; /* break after */
|
||||||
}
|
}
|
||||||
XFree(name);
|
XFree(name);
|
||||||
}
|
}
|
||||||
|
unsigned long bytes;
|
||||||
|
XTextProperty text = {};
|
||||||
|
char** list;
|
||||||
|
int list_sz;
|
||||||
|
/* Get WM_CLASS property */
|
||||||
|
if (Success == XGetWindowProperty(d, children[t], class, 0, 512, false, AnyPropertyType,
|
||||||
|
&text.encoding, &text.format, &text.nitems, &bytes,
|
||||||
|
&text.value)) {
|
||||||
|
/* decode string array */
|
||||||
|
if (Success == XmbTextPropertyToTextList(d, &text, &list, &list_sz)) {
|
||||||
|
if (list_sz >= 1 && !strcmp(list[0], "plasmashell")) {
|
||||||
|
desktop = children[t];
|
||||||
|
t = nret;
|
||||||
|
}
|
||||||
|
XFreeStringList(list);
|
||||||
|
}
|
||||||
|
XFree(text.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
XFree(children);
|
XFree(children);
|
||||||
}
|
}
|
||||||
searched = true;
|
searched = true;
|
||||||
}
|
}
|
||||||
return desktop;
|
return &desktop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xwin_wait_for_wm(void) {
|
||||||
|
Display* d = XOpenDisplay(0);
|
||||||
|
|
||||||
|
Atom check = None;
|
||||||
|
bool exists = false;
|
||||||
|
struct timespec tv = { .tv_sec = 0, .tv_nsec = 50 * 1000000 };
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (check == None) {
|
||||||
|
check = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", true);
|
||||||
|
}
|
||||||
|
if (check) {
|
||||||
|
int num_prop, idx;
|
||||||
|
Atom* props = XListProperties(d, DefaultRootWindow(d), &num_prop);
|
||||||
|
for (idx = 0; idx < num_prop; ++idx) {
|
||||||
|
if (props[idx] == check) {
|
||||||
|
exists = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XFree(props);
|
||||||
|
}
|
||||||
|
if (!exists) nanosleep(&tv, NULL);
|
||||||
|
} while (!exists);
|
||||||
|
|
||||||
|
XCloseDisplay(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* xwin_detect_wm(struct gl_wcb* wcb) {
|
||||||
|
Display* d = wcb->get_x11_display();
|
||||||
|
Atom check = XInternAtom(d, "_NET_SUPPORTING_WM_CHECK", false);
|
||||||
|
Atom name = XInternAtom(d, "_NET_WM_NAME", false);
|
||||||
|
Atom type = XInternAtom(d, "UTF8_STRING", false);
|
||||||
|
union {
|
||||||
|
Atom a;
|
||||||
|
int i;
|
||||||
|
long unsigned int lui;
|
||||||
|
} ignored;
|
||||||
|
|
||||||
|
unsigned long nitems = 0;
|
||||||
|
unsigned char* wm_name = NULL;
|
||||||
|
Window* wm_check;
|
||||||
|
if (Success != XGetWindowProperty(d, DefaultRootWindow(d), check, 0, 1024, false, XA_WINDOW,
|
||||||
|
&ignored.a, &ignored.i, &nitems, &ignored.lui, (unsigned char**) &wm_check)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nitems > 0 && Success == XGetWindowProperty(d, *wm_check, name, 0, 1024, false, type,
|
||||||
|
&ignored.a, &ignored.i, &nitems, &ignored.lui, &wm_name)) {
|
||||||
|
if (nitems > 0) {
|
||||||
|
static const char* wm_name_store = NULL;
|
||||||
|
if (wm_name_store) XFree((unsigned char*) wm_name_store);
|
||||||
|
wm_name_store = (const char*) wm_name;
|
||||||
|
} else {
|
||||||
|
XFree(wm_name);
|
||||||
|
wm_name = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XFree(wm_check);
|
||||||
|
printf("wm_name: \"%s\"\n", wm_name);
|
||||||
|
|
||||||
|
return (const char*) wm_name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool xwin_should_render(struct renderer* rd) {
|
bool xwin_should_render(struct renderer* rd) {
|
||||||
@@ -107,37 +195,51 @@ bool xwin_should_render(struct renderer* rd) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
|
/* Create string copy on stack with upcase chars */
|
||||||
|
#define S_UPPER(in, out) char out[strlen(in) + 1]; \
|
||||||
|
do { \
|
||||||
|
for (size_t t = 0; t < sizeof(out) / sizeof(char); ++t) { \
|
||||||
|
char c = in[t]; \
|
||||||
|
switch (c) { \
|
||||||
|
case 'a' ... 'z': c -= 'a' - 'A'; \
|
||||||
|
default: out[t] = c; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static void xwin_changeatom(struct gl_wcb* wcb, void* impl, const char* type,
|
||||||
const char* atom, const char* fmt, int mode) {
|
const char* atom, const char* fmt, int mode) {
|
||||||
Window w = wcb->get_x11_window(impl);
|
Window w = wcb->get_x11_window(impl);
|
||||||
Display* d = wcb->get_x11_display();
|
Display* d = wcb->get_x11_display();
|
||||||
Atom wtype = XInternAtom(d, atom, false);
|
Atom wtype = XInternAtom(d, atom, false);
|
||||||
size_t len = strlen(type), t;
|
|
||||||
char formatted[len + 1];
|
|
||||||
for (t = 0; t < len + 1; ++t) {
|
|
||||||
char c = type[t];
|
|
||||||
switch (c) {
|
|
||||||
case 'a' ... 'z': c -= 'a' - 'A';
|
|
||||||
default: formatted[t] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool ret = !strcmp(formatted, "DESKTOP");
|
|
||||||
char buf[256];
|
char buf[256];
|
||||||
snprintf(buf, sizeof(buf), fmt, formatted);
|
snprintf(buf, sizeof(buf), fmt, type);
|
||||||
Atom desk = XInternAtom(d, buf, false);
|
Atom desk = XInternAtom(d, buf, false);
|
||||||
XChangeProperty(d, w, wtype, XA_ATOM, 32, mode, (unsigned char*) &desk, 1);
|
XChangeProperty(d, w, wtype, XA_ATOM, 32, mode, (unsigned char*) &desk, 1);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set window types defined by the EWMH standard, possible values:
|
/* Set window types defined by the EWMH standard, possible values:
|
||||||
-> "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* type) {
|
bool xwin_settype(struct gl_wcb* wcb, void* impl, const char* rtype) {
|
||||||
return xwin_changeatom(wcb, impl, type, "_NET_WM_WINDOW_TYPE",
|
S_UPPER(rtype, type);
|
||||||
"_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");
|
||||||
}
|
}
|
||||||
|
|
||||||
void xwin_addstate(struct gl_wcb* wcb, void* impl, const char* state) {
|
void xwin_addstate(struct gl_wcb* wcb, void* impl, const char* rstate) {
|
||||||
xwin_changeatom(wcb, impl, state, "_NET_WM_STATE", "_NET_WM_STATE_%s", PropModeAppend);
|
S_UPPER(rstate, state);
|
||||||
|
if (strcmp(state, "PINNED"))
|
||||||
|
xwin_changeatom(wcb, impl, state, "_NET_WM_STATE", "_NET_WM_STATE_%s", PropModeAppend);
|
||||||
|
else
|
||||||
|
xwin_setdesktop(wcb, impl, XWIN_ALL_DESKTOPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void xwin_setdesktop(struct gl_wcb* wcb, void* impl, unsigned long desktop) {
|
||||||
|
Window w = wcb->get_x11_window(impl);
|
||||||
|
Display* d = wcb->get_x11_display();
|
||||||
|
Atom wtype = XInternAtom(d, "_NET_WM_DESKTOP", false);
|
||||||
|
XChangeProperty(d, w, wtype, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) &desktop, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Drawable get_drawable(Display* d, Window w) {
|
static Drawable get_drawable(Display* d, Window w) {
|
||||||
@@ -175,7 +277,7 @@ unsigned int xwin_copyglbg(struct renderer* rd, unsigned int tex) {
|
|||||||
rd_get_wcb(rd)->get_pos(rd_get_impl_window(rd), &x, &y);
|
rd_get_wcb(rd)->get_pos(rd_get_impl_window(rd), &x, &y);
|
||||||
XColor c;
|
XColor c;
|
||||||
Display* d = rd_get_wcb(rd)->get_x11_display();
|
Display* d = rd_get_wcb(rd)->get_x11_display();
|
||||||
Drawable src = get_drawable(d, find_desktop(rd));
|
Drawable src = get_drawable(d, DefaultRootWindow(d));
|
||||||
bool use_shm = XShmQueryExtension(d);
|
bool use_shm = XShmQueryExtension(d);
|
||||||
|
|
||||||
/* Obtain section of root pixmap */
|
/* Obtain section of root pixmap */
|
||||||
|
|||||||
13
xwin.h
13
xwin.h
@@ -1,5 +1,18 @@
|
|||||||
|
|
||||||
|
#define XWIN_ALL_DESKTOPS 0xFFFFFFFF
|
||||||
|
|
||||||
|
#ifndef XWIN_H
|
||||||
|
#define XWIN_H
|
||||||
|
|
||||||
|
typedef unsigned long int Window;
|
||||||
|
|
||||||
bool xwin_should_render(struct renderer* rd);
|
bool xwin_should_render(struct renderer* rd);
|
||||||
|
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_addstate(struct gl_wcb* wcb, void* impl, const char* state);
|
void xwin_addstate(struct gl_wcb* wcb, void* impl, const char* state);
|
||||||
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture);
|
unsigned int xwin_copyglbg(struct renderer* rd, unsigned int texture);
|
||||||
|
Window* xwin_get_desktop_layer(struct gl_wcb* wcb);
|
||||||
|
const char* xwin_detect_wm(struct gl_wcb* wcb);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user