mirror of
https://github.com/swaywm/sway.git
synced 2026-04-28 06:46:26 -04:00
Initial implementation of configurable GLESv2 drop shadows
This commit is contained in:
parent
bdd4d69205
commit
678aee73e5
13 changed files with 453 additions and 5 deletions
|
|
@ -190,6 +190,10 @@ sway_cmd cmd_workspace;
|
|||
sway_cmd cmd_workspace_layout;
|
||||
sway_cmd cmd_ws_auto_back_and_forth;
|
||||
sway_cmd cmd_xwayland;
|
||||
sway_cmd cmd_shadows_focused;
|
||||
sway_cmd cmd_shadows_focused_inactive;
|
||||
sway_cmd cmd_shadows_unfocused;
|
||||
sway_cmd cmd_shadows_urgent;
|
||||
|
||||
sway_cmd bar_cmd_bindcode;
|
||||
sway_cmd bar_cmd_binding_mode_indicator;
|
||||
|
|
|
|||
|
|
@ -317,6 +317,12 @@ struct border_colors {
|
|||
float child_border[4];
|
||||
};
|
||||
|
||||
struct shadow_config {
|
||||
int offset;
|
||||
int radius;
|
||||
float color[4];
|
||||
};
|
||||
|
||||
enum edge_border_types {
|
||||
E_NONE, /**< Don't hide edge borders */
|
||||
E_VERTICAL, /**< hide vertical edge borders */
|
||||
|
|
@ -504,6 +510,15 @@ struct sway_config {
|
|||
float background[4];
|
||||
} border_colors;
|
||||
|
||||
#if HAVE_SHADOWS
|
||||
struct {
|
||||
struct shadow_config focused;
|
||||
struct shadow_config focused_inactive;
|
||||
struct shadow_config unfocused;
|
||||
struct shadow_config urgent;
|
||||
} shadow_config;
|
||||
#endif
|
||||
|
||||
// floating view
|
||||
int32_t floating_maximum_width;
|
||||
int32_t floating_maximum_height;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ struct sway_workspace *output_get_active_workspace(struct sway_output *output);
|
|||
void output_render(struct sway_output *output, struct timespec *when,
|
||||
pixman_region32_t *damage);
|
||||
|
||||
void output_init_shadow_shader();
|
||||
|
||||
void output_surface_for_each_surface(struct sway_output *output,
|
||||
struct wlr_surface *surface, double ox, double oy,
|
||||
sway_surface_iterator_func_t iterator, void *user_data);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ if get_option('tray').enabled() and not tray_deps_found
|
|||
endif
|
||||
have_tray = (not get_option('tray').disabled()) and tray_deps_found
|
||||
|
||||
have_shadows = (not get_option('shadows').disabled())
|
||||
conf_data = configuration_data()
|
||||
|
||||
conf_data.set10('HAVE_XWAYLAND', have_xwayland)
|
||||
|
|
@ -94,6 +95,7 @@ conf_data.set10('HAVE_GDK_PIXBUF', gdk_pixbuf.found())
|
|||
conf_data.set10('HAVE_SYSTEMD', systemd.found())
|
||||
conf_data.set10('HAVE_ELOGIND', elogind.found())
|
||||
conf_data.set10('HAVE_TRAY', have_tray)
|
||||
conf_data.set10('HAVE_SHADOWS', have_shadows)
|
||||
|
||||
scdoc = dependency('scdoc', version: '>=1.9.2', native: true, required: get_option('man-pages'))
|
||||
if scdoc.found()
|
||||
|
|
@ -244,6 +246,7 @@ status = [
|
|||
'elogind: @0@'.format(elogind.found()),
|
||||
'tray: @0@'.format(have_tray),
|
||||
'man-pages: @0@'.format(scdoc.found()),
|
||||
'shadows: @0@'.format(have_shadows),
|
||||
'',
|
||||
]
|
||||
message('\n'.join(status))
|
||||
|
|
|
|||
|
|
@ -6,3 +6,4 @@ option('xwayland', type: 'feature', value: 'auto', description: 'Enable support
|
|||
option('tray', type: 'feature', value: 'auto', description: 'Enable support for swaybar tray')
|
||||
option('gdk-pixbuf', type: 'feature', value: 'auto', description: 'Enable support for more image formats in swaybg')
|
||||
option('man-pages', type: 'feature', value: 'auto', description: 'Generate and install man pages')
|
||||
option('shadows', type: 'feature', value: 'auto', description: 'Enable GLES2 drop shadow support')
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ static struct cmd_handler handlers[] = {
|
|||
{ "client.urgent", cmd_client_urgent },
|
||||
{ "default_border", cmd_default_border },
|
||||
{ "default_floating_border", cmd_default_floating_border },
|
||||
{ "exec", cmd_exec },
|
||||
{ "exec_always", cmd_exec_always },
|
||||
{ "exec", cmd_exec },
|
||||
{ "floating_maximum_size", cmd_floating_maximum_size },
|
||||
{ "floating_minimum_size", cmd_floating_minimum_size },
|
||||
{ "floating_modifier", cmd_floating_modifier },
|
||||
|
|
@ -67,9 +67,9 @@ static struct cmd_handler handlers[] = {
|
|||
{ "focus_on_window_activation", cmd_focus_on_window_activation },
|
||||
{ "focus_wrapping", cmd_focus_wrapping },
|
||||
{ "font", cmd_font },
|
||||
{ "for_window", cmd_for_window },
|
||||
{ "force_display_urgency_hint", cmd_force_display_urgency_hint },
|
||||
{ "force_focus_wrapping", cmd_force_focus_wrapping },
|
||||
{ "for_window", cmd_for_window },
|
||||
{ "fullscreen", cmd_fullscreen },
|
||||
{ "gaps", cmd_gaps },
|
||||
{ "hide_edge_borders", cmd_hide_edge_borders },
|
||||
|
|
@ -84,6 +84,10 @@ static struct cmd_handler handlers[] = {
|
|||
{ "popup_during_fullscreen", cmd_popup_during_fullscreen },
|
||||
{ "seat", cmd_seat },
|
||||
{ "set", cmd_set },
|
||||
{ "shadows.focused", cmd_shadows_focused},
|
||||
{ "shadows.focused_inactive", cmd_shadows_focused_inactive},
|
||||
{ "shadows.unfocused", cmd_shadows_unfocused},
|
||||
{ "shadows.urgent", cmd_shadows_urgent},
|
||||
{ "show_marks", cmd_show_marks },
|
||||
{ "smart_borders", cmd_smart_borders },
|
||||
{ "smart_gaps", cmd_smart_gaps },
|
||||
|
|
@ -95,8 +99,8 @@ static struct cmd_handler handlers[] = {
|
|||
{ "unbindcode", cmd_unbindcode },
|
||||
{ "unbindswitch", cmd_unbindswitch },
|
||||
{ "unbindsym", cmd_unbindsym },
|
||||
{ "workspace", cmd_workspace },
|
||||
{ "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
|
||||
{ "workspace", cmd_workspace },
|
||||
};
|
||||
|
||||
/* Config-time only commands. Keep alphabetized */
|
||||
|
|
|
|||
|
|
@ -117,3 +117,4 @@ struct cmd_results *cmd_client_noop(int argc, char **argv) {
|
|||
sway_log(SWAY_INFO, "Warning: %s is ignored by sway", argv[-1]);
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
91
sway/commands/shadows.c
Normal file
91
sway/commands/shadows.c
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#include "log.h"
|
||||
#include "sway/commands.h"
|
||||
#include "sway/config.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/tree/container.h"
|
||||
|
||||
/**
|
||||
* Parse the hex string into an integer.
|
||||
*/
|
||||
static bool parse_color_int(char *hexstring, uint32_t *dest) {
|
||||
if (hexstring[0] != '#') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen(hexstring) != 7 && strlen(hexstring) != 9) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++hexstring;
|
||||
char *end;
|
||||
uint32_t decimal = strtol(hexstring, &end, 16);
|
||||
|
||||
if (*end != '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strlen(hexstring) == 6) {
|
||||
// Add alpha
|
||||
decimal = (decimal << 8) | 0xff;
|
||||
}
|
||||
|
||||
*dest = decimal;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the hex string into a float value.
|
||||
*/
|
||||
static bool parse_color_float(char *hexstring, float dest[static 4]) {
|
||||
uint32_t decimal;
|
||||
if (!parse_color_int(hexstring, &decimal)) {
|
||||
return false;
|
||||
}
|
||||
dest[0] = ((decimal >> 24) & 0xff) / 255.0;
|
||||
dest[1] = ((decimal >> 16) & 0xff) / 255.0;
|
||||
dest[2] = ((decimal >> 8) & 0xff) / 255.0;
|
||||
dest[3] = (decimal & 0xff) / 255.0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static struct cmd_results *handle_shadow_cmd(int argc, char **argv, struct shadow_config* class, const char* cmd_name) {
|
||||
|
||||
struct cmd_results *error = NULL;
|
||||
if ((error = checkarg(argc, cmd_name, EXPECTED_EQUAL_TO, 3))) {
|
||||
return error;
|
||||
}
|
||||
|
||||
class->radius = atoi(argv[0]);
|
||||
class->offset = atoi(argv[1]);
|
||||
|
||||
if (!parse_color_float(argv[2], class->color)) {
|
||||
return cmd_results_new(CMD_INVALID,
|
||||
"Unable to parse shadow color '%s'", argv[0]);
|
||||
}
|
||||
|
||||
if (config->active) {
|
||||
for (int i = 0; i < root->outputs->length; ++i) {
|
||||
struct sway_output *output = root->outputs->items[i];
|
||||
output_damage_whole(output);
|
||||
}
|
||||
}
|
||||
|
||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_shadows_focused(int argc, char **argv) {
|
||||
return handle_shadow_cmd(argc, argv, &config->shadow_config.focused, "shadows.focused");
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_shadows_focused_inactive(int argc, char **argv) {
|
||||
return handle_shadow_cmd(argc, argv, &config->shadow_config.focused_inactive, "shadows.focused_inactive");
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_shadows_unfocused(int argc, char **argv) {
|
||||
return handle_shadow_cmd(argc, argv, &config->shadow_config.unfocused, "shadows.unfocused");
|
||||
}
|
||||
|
||||
struct cmd_results *cmd_shadows_urgent(int argc, char **argv) {
|
||||
return handle_shadow_cmd(argc, argv, &config->shadow_config.urgent, "shadows.urgent");
|
||||
}
|
||||
|
|
@ -331,6 +331,22 @@ static void config_defaults(struct sway_config *config) {
|
|||
|
||||
set_color(config->border_colors.background, 0xFFFFFF);
|
||||
|
||||
config->shadow_config.focused.radius = 25;
|
||||
config->shadow_config.focused.offset = 5;
|
||||
set_color(config->shadow_config.focused.color, 0x203040);
|
||||
|
||||
config->shadow_config.focused_inactive.radius = 25;
|
||||
config->shadow_config.focused_inactive.offset = 5;
|
||||
set_color(config->shadow_config.focused_inactive.color, 0x404040);
|
||||
|
||||
config->shadow_config.unfocused.radius = 25;
|
||||
config->shadow_config.unfocused.offset = 5;
|
||||
set_color(config->shadow_config.unfocused.color, 0x000000);
|
||||
|
||||
config->shadow_config.urgent.radius = 25;
|
||||
config->shadow_config.urgent.offset = 5;
|
||||
set_color(config->shadow_config.urgent.color, 0x402020);
|
||||
|
||||
// Security
|
||||
if (!(config->command_policies = create_list())) goto cleanup;
|
||||
if (!(config->feature_policies = create_list())) goto cleanup;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@
|
|||
#include "sway/tree/view.h"
|
||||
#include "sway/tree/workspace.h"
|
||||
|
||||
#if HAVE_SHADOWS
|
||||
#include <GLES2/gl2.h>
|
||||
#endif
|
||||
|
||||
struct render_data {
|
||||
pixman_region32_t *damage;
|
||||
float alpha;
|
||||
|
|
@ -269,12 +273,238 @@ static void render_saved_view(struct sway_view *view,
|
|||
&box, matrix, alpha);
|
||||
}
|
||||
|
||||
#if HAVE_SHADOWS
|
||||
|
||||
static bool check_shader_compilation(unsigned shader, const char* type) {
|
||||
int success;
|
||||
char infoLog[1024];
|
||||
if (strcmp(type,"PROGRAM") != 0) {
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
|
||||
sway_log(SWAY_ERROR, "ERROR::SHADER_COMPILATION_ERROR of type: %s ", type);
|
||||
sway_log(SWAY_ERROR, "%s", infoLog);
|
||||
sway_log(SWAY_ERROR, " -- --------------------------------------------------- -- ");
|
||||
}
|
||||
} else {
|
||||
glGetProgramiv(shader, GL_LINK_STATUS, &success);
|
||||
if (!success) {
|
||||
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
|
||||
sway_log(SWAY_ERROR, "ERROR::SHADER_LINKING_ERROR of type: %s ", type);
|
||||
sway_log(SWAY_ERROR, "%s", infoLog);
|
||||
sway_log(SWAY_ERROR, " -- --------------------------------------------------- -- ");
|
||||
}
|
||||
}
|
||||
return !!success;
|
||||
}
|
||||
|
||||
static unsigned shadow_shader = 0;
|
||||
|
||||
void output_init_shadow_shader() {
|
||||
if (shadow_shader != 0) return;
|
||||
sway_log(SWAY_INFO, "Initializing shadow shader");
|
||||
static const char* vcode =
|
||||
"uniform mat3 proj;\n"
|
||||
"uniform vec4 color;\n"
|
||||
"attribute vec2 pos;\n"
|
||||
"attribute vec2 texcoord;\n"
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec2 v_texcoord;\n"
|
||||
"\n"
|
||||
"void main() {\n"
|
||||
" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n"
|
||||
" v_color = color;\n"
|
||||
" v_texcoord = texcoord;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* fcode =
|
||||
"precision mediump float; \n"
|
||||
"varying vec4 v_color; \n"
|
||||
"varying vec2 v_texcoord; \n"
|
||||
"uniform float aspect; \n"
|
||||
"uniform float radius; \n"
|
||||
" \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" vec2 pos = v_texcoord; \n"
|
||||
" \n"
|
||||
" //pos.x /= aspect; \n"
|
||||
" \n"
|
||||
" float dx = smoothstep(0.0, radius * aspect, min(pos.x, 1.0 - pos.x)); \n"
|
||||
" float dy = smoothstep(0.0, radius, min(pos.y, 1.0 - pos.y)); \n"
|
||||
" \n"
|
||||
" float alpha = dx * dy; \n"
|
||||
" gl_FragColor = vec4(v_color.rgb, v_color.a * alpha); \n"
|
||||
"} \n";
|
||||
|
||||
unsigned int vertex, fragment;
|
||||
|
||||
unsigned int shader;
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
sway_log(SWAY_INFO, "vertex shader: %d", vertex);
|
||||
glShaderSource(vertex, 1, &vcode, NULL);
|
||||
glCompileShader(vertex);
|
||||
bool failed = !check_shader_compilation(vertex, "VERTEX");
|
||||
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
sway_log(SWAY_INFO, "fragment shader: %d", fragment);
|
||||
glShaderSource(fragment, 1, &fcode, NULL);
|
||||
glCompileShader(fragment);
|
||||
failed |= !check_shader_compilation(fragment, "FRAGMENT");
|
||||
|
||||
shader = glCreateProgram();
|
||||
glAttachShader(shader, vertex);
|
||||
glAttachShader(shader, fragment);
|
||||
glLinkProgram(shader);
|
||||
failed |= !check_shader_compilation(shader, "PROGRAM");
|
||||
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
if (!failed) {
|
||||
shadow_shader = shader;
|
||||
} else {
|
||||
sway_log(SWAY_ERROR, "Failure initializing shadow shader");
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_quad()
|
||||
{
|
||||
GLfloat verts[] = {
|
||||
1, 0, // top right
|
||||
0, 0, // top left
|
||||
1, 1, // bottom right
|
||||
0, 1, // bottom left
|
||||
};
|
||||
GLfloat texcoord[] = {
|
||||
1, 0, // top right
|
||||
0, 0, // top left
|
||||
1, 1, // bottom right
|
||||
0, 1, // bottom left
|
||||
};
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
}
|
||||
|
||||
static void render_shadow(struct sway_output *output, pixman_region32_t *output_damage, struct wlr_box box,
|
||||
float rotation, float alpha, struct shadow_config* shadow) {
|
||||
|
||||
if (shadow_shader == 0) return;
|
||||
|
||||
float offset = shadow->offset, radius = shadow->radius;
|
||||
|
||||
box.x += offset - radius / 2.f;
|
||||
box.y += offset - radius / 2.f;
|
||||
box.height += radius;
|
||||
box.width += radius;
|
||||
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
// struct wlr_renderer *renderer =
|
||||
// wlr_backend_get_renderer(wlr_output->backend);
|
||||
|
||||
box.x -= output->lx * wlr_output->scale;
|
||||
box.y -= output->ly * wlr_output->scale;
|
||||
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_union_rect(
|
||||
&damage, &damage, box.x, box.y, box.width, box.height);
|
||||
pixman_region32_intersect(&damage, &damage, output_damage);
|
||||
bool damaged = pixman_region32_not_empty(&damage);
|
||||
if (!damaged) {
|
||||
goto damage_finish;
|
||||
}
|
||||
|
||||
float matrix[9];
|
||||
wlr_matrix_project_box(matrix,
|
||||
&box,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL,
|
||||
rotation,
|
||||
wlr_output->transform_matrix);
|
||||
|
||||
int nrects;
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
scissor_output(output->wlr_output, &rects[i]);
|
||||
|
||||
float transposition[9];
|
||||
wlr_matrix_transpose(transposition, matrix);
|
||||
|
||||
// save current shader and blend settings
|
||||
GLint prevShader;
|
||||
glGetIntegerv(GL_CURRENT_PROGRAM, &prevShader);
|
||||
GLboolean blendEnabled;
|
||||
glGetBooleanv(GL_BLEND, &blendEnabled);
|
||||
GLint blendSrc;
|
||||
GLint blendDst;
|
||||
glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrc);
|
||||
glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDst);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glUseProgram(shadow_shader);
|
||||
|
||||
// update the uniform color
|
||||
glUniformMatrix3fv(glGetUniformLocation(shadow_shader, "proj"),
|
||||
1,
|
||||
false,
|
||||
transposition);
|
||||
glUniform4f(glGetUniformLocation(shadow_shader, "color"),
|
||||
shadow->color[0],
|
||||
shadow->color[1],
|
||||
shadow->color[2],
|
||||
alpha);
|
||||
glUniform1f(glGetUniformLocation(shadow_shader, "aspect"),
|
||||
box.height / (float)box.width);
|
||||
glUniform1f(glGetUniformLocation(shadow_shader, "radius"),
|
||||
radius / (float)box.height);
|
||||
draw_quad();
|
||||
|
||||
// restore state
|
||||
glUseProgram(prevShader);
|
||||
if (blendEnabled) glEnable(GL_BLEND);
|
||||
else glDisable(GL_BLEND);
|
||||
glBlendFunc(blendSrc, blendDst);
|
||||
}
|
||||
|
||||
damage_finish:
|
||||
pixman_region32_fini(&damage);
|
||||
}
|
||||
|
||||
static void render_shadow_for_view(struct sway_output *output, pixman_region32_t *damage,
|
||||
struct sway_container *con, struct shadow_config *shadow) {
|
||||
|
||||
float output_scale = output->wlr_output->scale;
|
||||
struct sway_container_state *state = &con->current;
|
||||
|
||||
struct wlr_box shadow_box = {state->x, state->content_y, state->width, state->height};
|
||||
scale_box(&shadow_box, output_scale);
|
||||
render_shadow(output, damage, shadow_box, 0, con->alpha, shadow);
|
||||
}
|
||||
#else
|
||||
void output_init_shadow_shader() {}
|
||||
|
||||
static void render_shadow_for_view(struct sway_output *output, pixman_region32_t *damage,
|
||||
struct sway_container *con, struct shadow_config *shadow) {
|
||||
|
||||
#endif
|
||||
// SHADOWS END
|
||||
|
||||
/**
|
||||
* Render a view's surface and left/bottom/right borders.
|
||||
*/
|
||||
static void render_view(struct sway_output *output, pixman_region32_t *damage,
|
||||
struct sway_container *con, struct border_colors *colors) {
|
||||
struct sway_view *view = con->view;
|
||||
|
||||
if (view->saved_buffer) {
|
||||
render_saved_view(view, output, damage, view->container->alpha);
|
||||
} else if (view->surface) {
|
||||
|
|
@ -285,11 +515,12 @@ static void render_view(struct sway_output *output, pixman_region32_t *damage,
|
|||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box;
|
||||
float output_scale = output->wlr_output->scale;
|
||||
float color[4];
|
||||
struct sway_container_state *state = &con->current;
|
||||
|
||||
struct wlr_box box;
|
||||
float color[4];
|
||||
|
||||
if (state->border_left) {
|
||||
memcpy(&color, colors->child_border, sizeof(float) * 4);
|
||||
premultiply_alpha(color, con->alpha);
|
||||
|
|
@ -678,28 +909,35 @@ static void render_containers_linear(struct sway_output *output,
|
|||
if (child->view) {
|
||||
struct sway_view *view = child->view;
|
||||
struct border_colors *colors;
|
||||
struct shadow_config *shadow;
|
||||
struct wlr_texture *title_texture;
|
||||
struct wlr_texture *marks_texture;
|
||||
struct sway_container_state *state = &child->current;
|
||||
|
||||
if (view_is_urgent(view)) {
|
||||
colors = &config->border_colors.urgent;
|
||||
shadow = &config->shadow_config.urgent;
|
||||
title_texture = child->title_urgent;
|
||||
marks_texture = child->marks_urgent;
|
||||
} else if (state->focused || parent->focused) {
|
||||
colors = &config->border_colors.focused;
|
||||
shadow = &config->shadow_config.focused;
|
||||
title_texture = child->title_focused;
|
||||
marks_texture = child->marks_focused;
|
||||
} else if (child == parent->active_child) {
|
||||
colors = &config->border_colors.focused_inactive;
|
||||
shadow = &config->shadow_config.focused_inactive;
|
||||
title_texture = child->title_focused_inactive;
|
||||
marks_texture = child->marks_focused_inactive;
|
||||
} else {
|
||||
colors = &config->border_colors.unfocused;
|
||||
shadow = &config->shadow_config.unfocused;
|
||||
title_texture = child->title_unfocused;
|
||||
marks_texture = child->marks_unfocused;
|
||||
}
|
||||
|
||||
render_shadow_for_view(output, damage, child, shadow);
|
||||
|
||||
if (state->border == B_NORMAL) {
|
||||
render_titlebar(output, damage, child, state->x,
|
||||
state->y, state->width, colors,
|
||||
|
|
@ -727,6 +965,32 @@ static void render_containers_tabbed(struct sway_output *output,
|
|||
struct border_colors *current_colors = &config->border_colors.unfocused;
|
||||
int tab_width = parent->box.width / parent->children->length;
|
||||
|
||||
#if HAVE_SHADOWS
|
||||
struct shadow_config *current_shadow = &config->shadow_config.unfocused;
|
||||
|
||||
// Render shadow
|
||||
for (int i = 0; i < parent->children->length; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
struct sway_view *view = child->view;
|
||||
struct sway_container_state *cstate = &child->current;
|
||||
bool urgent = view ?
|
||||
view_is_urgent(view) : container_has_urgent_child(child);
|
||||
|
||||
if (child == current) {
|
||||
if (urgent) {
|
||||
current_shadow = &config->shadow_config.urgent;
|
||||
} else if (cstate->focused || parent->focused) {
|
||||
current_shadow = &config->shadow_config.focused;
|
||||
} else if (child == parent->active_child) {
|
||||
current_shadow = &config->shadow_config.focused_inactive;
|
||||
} else {
|
||||
current_shadow = &config->shadow_config.unfocused;
|
||||
}
|
||||
}
|
||||
}
|
||||
render_shadow_for_view(output, damage, current, current_shadow);
|
||||
#endif
|
||||
|
||||
// Render tabs
|
||||
for (int i = 0; i < parent->children->length; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
|
|
@ -790,14 +1054,42 @@ static void render_containers_stacked(struct sway_output *output,
|
|||
}
|
||||
struct sway_container *current = parent->active_child;
|
||||
struct border_colors *current_colors = &config->border_colors.unfocused;
|
||||
struct shadow_config *current_shadows = &config->shadow_config.unfocused;
|
||||
size_t titlebar_height = container_titlebar_height();
|
||||
|
||||
#if HAVE_SHADOWS
|
||||
struct shadow_config *current_shadow = &config->shadow_config.unfocused;
|
||||
|
||||
// Render shadow
|
||||
for (int i = 0; i < parent->children->length; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
struct sway_view *view = child->view;
|
||||
struct sway_container_state *cstate = &child->current;
|
||||
bool urgent = view ?
|
||||
view_is_urgent(view) : container_has_urgent_child(child);
|
||||
|
||||
if (child == current) {
|
||||
if (urgent) {
|
||||
current_shadow = &config->shadow_config.urgent;
|
||||
} else if (cstate->focused || parent->focused) {
|
||||
current_shadow = &config->shadow_config.focused;
|
||||
} else if (child == parent->active_child) {
|
||||
current_shadow = &config->shadow_config.focused_inactive;
|
||||
} else {
|
||||
current_shadow = &config->shadow_config.unfocused;
|
||||
}
|
||||
}
|
||||
}
|
||||
render_shadow_for_view(output, damage, current, current_shadow);
|
||||
#endif
|
||||
|
||||
// Render titles
|
||||
for (int i = 0; i < parent->children->length; ++i) {
|
||||
struct sway_container *child = parent->children->items[i];
|
||||
struct sway_view *view = child->view;
|
||||
struct sway_container_state *cstate = &child->current;
|
||||
struct border_colors *colors;
|
||||
struct shadow_config *shadows;
|
||||
struct wlr_texture *title_texture;
|
||||
struct wlr_texture *marks_texture;
|
||||
bool urgent = view ?
|
||||
|
|
@ -805,18 +1097,22 @@ static void render_containers_stacked(struct sway_output *output,
|
|||
|
||||
if (urgent) {
|
||||
colors = &config->border_colors.urgent;
|
||||
shadows = &config->shadow_config.urgent;
|
||||
title_texture = child->title_urgent;
|
||||
marks_texture = child->marks_urgent;
|
||||
} else if (cstate->focused || parent->focused) {
|
||||
colors = &config->border_colors.focused;
|
||||
shadows = &config->shadow_config.focused;
|
||||
title_texture = child->title_focused;
|
||||
marks_texture = child->marks_focused;
|
||||
} else if (child == parent->active_child) {
|
||||
colors = &config->border_colors.focused_inactive;
|
||||
shadows = &config->shadow_config.focused_inactive;
|
||||
title_texture = child->title_focused_inactive;
|
||||
marks_texture = child->marks_focused_inactive;
|
||||
} else {
|
||||
colors = &config->border_colors.unfocused;
|
||||
shadows = &config->shadow_config.unfocused;
|
||||
title_texture = child->title_unfocused;
|
||||
marks_texture = child->marks_unfocused;
|
||||
}
|
||||
|
|
@ -827,6 +1123,7 @@ static void render_containers_stacked(struct sway_output *output,
|
|||
|
||||
if (child == current) {
|
||||
current_colors = colors;
|
||||
current_shadows = shadows;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -903,23 +1200,29 @@ static void render_floating_container(struct sway_output *soutput,
|
|||
if (con->view) {
|
||||
struct sway_view *view = con->view;
|
||||
struct border_colors *colors;
|
||||
struct shadow_config *shadows;
|
||||
struct wlr_texture *title_texture;
|
||||
struct wlr_texture *marks_texture;
|
||||
|
||||
if (view_is_urgent(view)) {
|
||||
colors = &config->border_colors.urgent;
|
||||
shadows = &config->shadow_config.urgent;
|
||||
title_texture = con->title_urgent;
|
||||
marks_texture = con->marks_urgent;
|
||||
} else if (con->current.focused) {
|
||||
colors = &config->border_colors.focused;
|
||||
shadows = &config->shadow_config.focused;
|
||||
title_texture = con->title_focused;
|
||||
marks_texture = con->marks_focused;
|
||||
} else {
|
||||
colors = &config->border_colors.unfocused;
|
||||
shadows = &config->shadow_config.unfocused;
|
||||
title_texture = con->title_unfocused;
|
||||
marks_texture = con->marks_unfocused;
|
||||
}
|
||||
|
||||
render_shadow_for_view(soutput, damage, con, shadows);
|
||||
|
||||
if (con->current.border == B_NORMAL) {
|
||||
render_titlebar(soutput, damage, con, con->current.x,
|
||||
con->current.y, con->current.width, colors,
|
||||
|
|
|
|||
|
|
@ -339,6 +339,11 @@ static void ipc_json_describe_workspace(struct sway_workspace *workspace,
|
|||
json_object_new_string(
|
||||
ipc_json_orientation_description(workspace->layout)));
|
||||
|
||||
json_object *gaps = json_object_new_object();
|
||||
json_object_object_add(gaps, "inner", json_object_new_int(workspace->gaps_inner));
|
||||
// Add outer
|
||||
json_object_object_add(object, "gaps", gaps);
|
||||
|
||||
// Floating
|
||||
json_object *floating_array = json_object_new_array();
|
||||
for (int i = 0; i < workspace->floating->length; ++i) {
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ sway_sources = files(
|
|||
'commands/workspace_layout.c',
|
||||
'commands/ws_auto_back_and_forth.c',
|
||||
'commands/xwayland.c',
|
||||
'commands/shadows.c',
|
||||
|
||||
'commands/bar/bind.c',
|
||||
'commands/bar/binding_mode_indicator.c',
|
||||
|
|
|
|||
|
|
@ -101,6 +101,8 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
|
|||
output->workspaces = create_list();
|
||||
output->current.workspaces = create_list();
|
||||
|
||||
output_init_shadow_shader();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue