mirror of
https://github.com/artizirk/wdisplays.git
synced 2024-11-24 09:20:59 +02:00
Display grid lines when moving a display
This commit is contained in:
parent
e0f382af84
commit
d9b868077a
90
src/main.c
90
src/main.c
@ -154,7 +154,7 @@ static gboolean send_apply(gpointer data) {
|
||||
GdkDisplay *display = gdk_window_get_display(window);
|
||||
struct wl_display *wl_display = gdk_wayland_display_get_wl_display(display);
|
||||
wd_apply_state(state, outputs, wl_display);
|
||||
state->apply_pending = false;
|
||||
state->apply_pending = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ static void apply_state(struct wd_state *state) {
|
||||
|
||||
/* queue this once per iteration in order to prevent duplicate updates */
|
||||
if (!state->apply_pending) {
|
||||
state->apply_pending = true;
|
||||
state->apply_pending = TRUE;
|
||||
g_idle_add(send_apply, state);
|
||||
}
|
||||
}
|
||||
@ -257,11 +257,12 @@ static void cache_scroll(struct wd_state *state) {
|
||||
static gboolean redraw_canvas(GtkWidget *widget, GdkFrameClock *frame_clock, gpointer data);
|
||||
|
||||
static void update_tick_callback(struct wd_state *state) {
|
||||
bool any_animate = false;
|
||||
bool any_animate = FALSE;
|
||||
struct wd_render_head_data *render;
|
||||
wl_list_for_each(render, &state->render.heads, link) {
|
||||
if (state->render.updated_at < render->transition_begin + HOVER_USECS) {
|
||||
any_animate = true;
|
||||
if (state->render.updated_at < render->hover_begin + HOVER_USECS
|
||||
|| state->render.updated_at < render->click_begin + HOVER_USECS) {
|
||||
any_animate = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -279,12 +280,12 @@ static void update_tick_callback(struct wd_state *state) {
|
||||
}
|
||||
|
||||
static void update_cursor(struct wd_state *state) {
|
||||
bool any_hovered = false;
|
||||
bool any_hovered = FALSE;
|
||||
struct wd_head *head;
|
||||
wl_list_for_each(head, &state->heads, link) {
|
||||
struct wd_render_head_data *render = head->render;
|
||||
if (render != NULL && render->hovered) {
|
||||
any_hovered = true;
|
||||
any_hovered = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -300,6 +301,15 @@ static void update_cursor(struct wd_state *state) {
|
||||
}
|
||||
}
|
||||
|
||||
static inline void flip_anim(uint64_t *timer, uint64_t tick) {
|
||||
uint64_t animate_end = *timer + HOVER_USECS;
|
||||
if (tick < animate_end) {
|
||||
*timer = tick - (animate_end - tick);
|
||||
} else {
|
||||
*timer = tick;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_hovered(struct wd_state *state) {
|
||||
GdkDisplay *display = gdk_display_get_default();
|
||||
GdkWindow *window = gtk_widget_get_window(state->canvas);
|
||||
@ -309,17 +319,17 @@ static void update_hovered(struct wd_state *state) {
|
||||
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
||||
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
||||
g_autoptr(GList) seats = gdk_display_list_seats(display);
|
||||
bool any_hovered = false;
|
||||
bool any_hovered = FALSE;
|
||||
struct wd_render_head_data *render;
|
||||
wl_list_for_each(render, &state->render.heads, link) {
|
||||
bool init_hovered = render->hovered;
|
||||
render->hovered = false;
|
||||
render->hovered = FALSE;
|
||||
if (any_hovered) {
|
||||
continue;
|
||||
}
|
||||
if (state->clicked == render) {
|
||||
render->hovered = true;
|
||||
any_hovered = true;
|
||||
render->hovered = TRUE;
|
||||
any_hovered = TRUE;
|
||||
} else if (state->clicked == NULL) {
|
||||
for (GList *iter = seats; iter != NULL; iter = iter->next) {
|
||||
double mouse_x;
|
||||
@ -329,14 +339,14 @@ static void update_hovered(struct wd_state *state) {
|
||||
gdk_window_get_device_position_double(window, pointer, &mouse_x, &mouse_y, NULL);
|
||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||
render->hovered = true;
|
||||
any_hovered = true;
|
||||
render->hovered = TRUE;
|
||||
any_hovered = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (init_hovered != render->hovered) {
|
||||
render->transition_begin = tick;
|
||||
flip_anim(&render->hover_begin, tick);
|
||||
}
|
||||
}
|
||||
update_cursor(state);
|
||||
@ -812,11 +822,6 @@ static cairo_surface_t *draw_head(PangoContext *pango,
|
||||
cairo_set_source_color(cr, info->border_color);
|
||||
cairo_fill(cr);
|
||||
|
||||
cairo_set_line_width(cr, 1.);
|
||||
cairo_rectangle(cr, 0, 0, width, height);
|
||||
cairo_set_source_color(cr, info->fg_color);
|
||||
cairo_stroke(cr);
|
||||
|
||||
PangoLayout *layout = pango_layout_new(pango);
|
||||
pango_layout_set_text(layout, name, -1);
|
||||
int text_width = pango_units_from_double(width - TEXT_MARGIN * 2);
|
||||
@ -862,7 +867,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
||||
render->tex_width = frame->width;
|
||||
render->tex_height = frame->height;
|
||||
render->pixels = frame->pixels;
|
||||
render->preview = true;
|
||||
render->preview = TRUE;
|
||||
render->updated_at = tick;
|
||||
render->y_invert = frame->y_invert;
|
||||
render->swap_rgb = frame->swap_rgb;
|
||||
@ -875,7 +880,7 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
||||
|| render->pixels == NULL || size_changed(render)) {
|
||||
render->tex_width = render->x2 - render->x1;
|
||||
render->tex_height = render->y2 - render->y1;
|
||||
render->preview = false;
|
||||
render->preview = FALSE;
|
||||
if (head->surface != NULL) {
|
||||
cairo_surface_destroy(head->surface);
|
||||
}
|
||||
@ -885,9 +890,9 @@ static void canvas_render(GtkGLArea *area, GdkGLContext *context, gpointer data)
|
||||
render->tex_stride = cairo_image_surface_get_stride(head->surface);
|
||||
render->updated_at = tick;
|
||||
render->active.rotation = 0;
|
||||
render->active.x_invert = false;
|
||||
render->y_invert = false;
|
||||
render->swap_rgb = false;
|
||||
render->active.x_invert = FALSE;
|
||||
render->y_invert = FALSE;
|
||||
render->swap_rgb = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -911,6 +916,23 @@ static void canvas_unrealize(GtkWidget *widget, gpointer data) {
|
||||
state->gl_data = NULL;
|
||||
}
|
||||
|
||||
static void set_clicked_head(struct wd_state *state,
|
||||
struct wd_render_head_data *clicked) {
|
||||
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
||||
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
||||
if (clicked != state->clicked) {
|
||||
if (state->clicked != NULL) {
|
||||
state->clicked->clicked = FALSE;
|
||||
flip_anim(&state->clicked->click_begin, tick);
|
||||
}
|
||||
if (clicked != NULL) {
|
||||
clicked->clicked = TRUE;
|
||||
flip_anim(&clicked->click_begin, tick);
|
||||
}
|
||||
}
|
||||
state->clicked = clicked;
|
||||
}
|
||||
|
||||
static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
||||
gpointer data) {
|
||||
struct wd_state *state = data;
|
||||
@ -923,7 +945,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
||||
double mouse_y = event->button.y;
|
||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||
state->clicked = render;
|
||||
set_clicked_head(state, render);
|
||||
state->click_offset.x = event->button.x - render->x1;
|
||||
state->click_offset.y = event->button.y - render->y1;
|
||||
break;
|
||||
@ -936,7 +958,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
||||
struct wd_render_head_data *render;
|
||||
wl_list_for_each(render, &state->render.heads, link) {
|
||||
render->updated_at = 0;
|
||||
render->preview = true;
|
||||
render->preview = TRUE;
|
||||
}
|
||||
gtk_gl_area_queue_render(GTK_GL_AREA(state->canvas));
|
||||
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
||||
@ -949,7 +971,7 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
||||
}
|
||||
}
|
||||
} else if (event->button.button == 2) {
|
||||
state->panning = true;
|
||||
state->panning = TRUE;
|
||||
state->pan_last.x = event->button.x;
|
||||
state->pan_last.y = event->button.y;
|
||||
}
|
||||
@ -961,10 +983,10 @@ static gboolean canvas_release(GtkWidget *widget, GdkEvent *event,
|
||||
gpointer data) {
|
||||
struct wd_state *state = data;
|
||||
if (event->button.button == 1) {
|
||||
state->clicked = NULL;
|
||||
set_clicked_head(state, NULL);
|
||||
}
|
||||
if (event->button.button == 2) {
|
||||
state->panning = false;
|
||||
state->panning = FALSE;
|
||||
}
|
||||
update_cursor(state);
|
||||
return TRUE;
|
||||
@ -1084,10 +1106,10 @@ static gboolean canvas_enter(GtkWidget *widget, GdkEvent *event,
|
||||
gpointer data) {
|
||||
struct wd_state *state = data;
|
||||
if (!(event->crossing.state & GDK_BUTTON1_MASK)) {
|
||||
state->clicked = NULL;
|
||||
set_clicked_head(state, NULL);
|
||||
}
|
||||
if (!(event->crossing.state & GDK_BUTTON2_MASK)) {
|
||||
state->panning = false;
|
||||
state->panning = FALSE;
|
||||
}
|
||||
update_cursor(state);
|
||||
return TRUE;
|
||||
@ -1098,7 +1120,7 @@ static gboolean canvas_leave(GtkWidget *widget, GdkEvent *event,
|
||||
struct wd_state *state = data;
|
||||
struct wd_render_head_data *render;
|
||||
wl_list_for_each(render, &state->render.heads, link) {
|
||||
render->hovered = false;
|
||||
render->hovered = FALSE;
|
||||
}
|
||||
update_tick_callback(state);
|
||||
return TRUE;
|
||||
@ -1321,12 +1343,12 @@ static void activate(GtkApplication* app, gpointer user_data) {
|
||||
wd_fatal_error(1, "Compositor doesn't support xdg-output-unstable-v1");
|
||||
}
|
||||
if (state->copy_manager == NULL) {
|
||||
state->capture = false;
|
||||
state->capture = FALSE;
|
||||
g_simple_action_set_state(capture_action, g_variant_new_boolean(state->capture));
|
||||
g_simple_action_set_enabled(capture_action, FALSE);
|
||||
}
|
||||
if (state->layer_shell == NULL) {
|
||||
state->show_overlay = false;
|
||||
state->show_overlay = FALSE;
|
||||
g_simple_action_set_state(overlay_action, g_variant_new_boolean(state->show_overlay));
|
||||
g_simple_action_set_enabled(overlay_action, FALSE);
|
||||
}
|
||||
|
240
src/render.c
240
src/render.c
@ -37,6 +37,18 @@
|
||||
#define BT_COLOR_QUAD_SIZE (6 * BT_COLOR_VERT_SIZE)
|
||||
#define BT_COLOR_MAX (BT_COLOR_QUAD_SIZE * HEADS_MAX)
|
||||
|
||||
#define BT_LINE_VERT_SIZE (2 + 4)
|
||||
#define BT_LINE_QUAD_SIZE (8 * BT_LINE_VERT_SIZE)
|
||||
#define BT_LINE_EXT_SIZE (24 * BT_LINE_VERT_SIZE)
|
||||
#define BT_LINE_MAX (BT_LINE_EXT_SIZE * (HEADS_MAX + 1))
|
||||
|
||||
enum gl_buffers {
|
||||
TEXTURE_BUFFER,
|
||||
COLOR_BUFFER,
|
||||
LINE_BUFFER,
|
||||
NUM_BUFFERS
|
||||
};
|
||||
|
||||
struct wd_gl_data {
|
||||
GLuint color_program;
|
||||
GLuint color_vertex_shader;
|
||||
@ -54,12 +66,12 @@ struct wd_gl_data {
|
||||
GLuint texture_texture_uniform;
|
||||
GLuint texture_color_transform_uniform;
|
||||
|
||||
GLuint buffers[2];
|
||||
GLuint buffers[NUM_BUFFERS];
|
||||
|
||||
unsigned texture_count;
|
||||
GLuint textures[HEADS_MAX];
|
||||
|
||||
float tris[BT_COLOR_MAX];
|
||||
float verts[BT_LINE_MAX];
|
||||
};
|
||||
|
||||
static const char *color_vertex_shader_src = "\
|
||||
@ -186,15 +198,19 @@ struct wd_gl_data *wd_gl_setup(void) {
|
||||
res->texture_color_transform_uniform = glGetUniformLocation(
|
||||
res->texture_program, "color_transform");
|
||||
|
||||
glGenBuffers(2, res->buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[0]);
|
||||
glGenBuffers(NUM_BUFFERS, res->buffers);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[TEXTURE_BUFFER]);
|
||||
glBufferData(GL_ARRAY_BUFFER, BT_UV_MAX * sizeof(float),
|
||||
NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[1]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[COLOR_BUFFER]);
|
||||
glBufferData(GL_ARRAY_BUFFER, BT_COLOR_MAX * sizeof(float),
|
||||
NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[LINE_BUFFER]);
|
||||
glBufferData(GL_ARRAY_BUFFER, BT_LINE_MAX * sizeof(float),
|
||||
NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -210,27 +226,50 @@ static const GLfloat TRANSFORM_BGR[16] = {
|
||||
1, 0, 0, 0,
|
||||
0, 0, 0, 1};
|
||||
|
||||
#define PUSH_POINT(_start, _a, _b) \
|
||||
#define PUSH_POINT_COLOR(_start, _a, _b, _color, _alpha) \
|
||||
*((_start)++) = (_a);\
|
||||
*((_start)++) = (_b);
|
||||
*((_start)++) = (_b);\
|
||||
*((_start)++) = ((_color)[0]);\
|
||||
*((_start)++) = ((_color)[1]);\
|
||||
*((_start)++) = ((_color)[2]);\
|
||||
*((_start)++) = (_alpha);
|
||||
|
||||
#define PUSH_COLOR(_start, _a, _b, _c, _d) \
|
||||
#define PUSH_POINT_UV(_start, _a, _b, _c, _d) \
|
||||
*((_start)++) = (_a);\
|
||||
*((_start)++) = (_b);\
|
||||
*((_start)++) = (_c);\
|
||||
*((_start)++) = (_d);
|
||||
|
||||
#define PUSH_POINT_UV(_start, _a, _b, _c, _d) \
|
||||
PUSH_COLOR(_start, _a, _b, _c, _d)
|
||||
static inline float lerp(float x, float y, float a) {
|
||||
return x * (1.f - a) + y * a;
|
||||
}
|
||||
|
||||
static inline void lerp_color(float out[3], float x[3], float y[3], float a) {
|
||||
out[0] = lerp(x[0], y[0], a);
|
||||
out[1] = lerp(x[1], y[1], a);
|
||||
out[2] = lerp(x[2], y[2], a);
|
||||
out[3] = lerp(x[3], y[3], a);
|
||||
}
|
||||
|
||||
static inline float ease(float d) {
|
||||
d *= 2.f;
|
||||
if (d <= 1.f) {
|
||||
d = d * d;
|
||||
} else {
|
||||
d -= 1.f;
|
||||
d = d * (2.f - d) + 1.f;
|
||||
}
|
||||
d /= 2.f;
|
||||
return d;
|
||||
}
|
||||
|
||||
void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
uint64_t tick) {
|
||||
unsigned int tris = 0;
|
||||
unsigned int tri_verts = 0;
|
||||
|
||||
unsigned int head_count = wl_list_length(&info->heads);
|
||||
if (head_count >= HEADS_MAX) {
|
||||
if (head_count >= HEADS_MAX)
|
||||
head_count = HEADS_MAX;
|
||||
}
|
||||
|
||||
if (head_count > res->texture_count) {
|
||||
glGenTextures(head_count - res->texture_count,
|
||||
@ -250,7 +289,7 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
struct wd_render_head_data *head;
|
||||
int i = 0;
|
||||
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||
float *tri_ptr = res->tris + i * BT_UV_QUAD_SIZE;
|
||||
float *tri_ptr = res->verts + i * BT_UV_QUAD_SIZE;
|
||||
float x1 = head->active.x_invert ? head->x2 : head->x1;
|
||||
float y1 = head->y_invert ? head->y2 : head->y1;
|
||||
float x2 = head->active.x_invert ? head->x1 : head->x2;
|
||||
@ -285,11 +324,10 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
PUSH_POINT_UV(tri_ptr, x2, y1, sb, tb)
|
||||
PUSH_POINT_UV(tri_ptr, x2, y2, sc, tc)
|
||||
|
||||
tris += 6;
|
||||
tri_verts += 6;
|
||||
i++;
|
||||
if (i >= HEADS_MAX) {
|
||||
if (i >= HEADS_MAX)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glClearColor(info->bg_color[0], info->bg_color[1], info->bg_color[2], 1.f);
|
||||
@ -297,11 +335,11 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
|
||||
float screen_size[2] = { info->viewport_width, info->viewport_height };
|
||||
|
||||
if (tris > 0) {
|
||||
if (tri_verts > 0) {
|
||||
glUseProgram(res->texture_program);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[0]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[TEXTURE_BUFFER]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||
tris * BT_UV_VERT_SIZE * sizeof(float), res->tris);
|
||||
tri_verts * BT_UV_VERT_SIZE * sizeof(float), res->verts);
|
||||
glEnableVertexAttribArray(res->texture_position_attribute);
|
||||
glEnableVertexAttribArray(res->texture_uv_attribute);
|
||||
glVertexAttribPointer(res->texture_position_attribute,
|
||||
@ -328,19 +366,23 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR);
|
||||
glDrawArrays(GL_TRIANGLES, i * 6, 6);
|
||||
i++;
|
||||
if (i >= HEADS_MAX) {
|
||||
if (i >= HEADS_MAX)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tris = 0;
|
||||
tri_verts = 0;
|
||||
|
||||
int j = 0;
|
||||
i = 0;
|
||||
bool any_clicked = false;
|
||||
uint64_t click_begin = 0;
|
||||
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||
if (head->hovered || tick < head->transition_begin + HOVER_USECS) {
|
||||
float *tri_ptr = res->tris + j++ * BT_COLOR_QUAD_SIZE;
|
||||
any_clicked = head->clicked || any_clicked;
|
||||
if (head->click_begin > click_begin)
|
||||
click_begin = head->click_begin;
|
||||
if (head->hovered || tick < head->hover_begin + HOVER_USECS) {
|
||||
float *tri_ptr = res->verts + j++ * BT_COLOR_QUAD_SIZE;
|
||||
float x1 = head->x1;
|
||||
float y1 = head->y1;
|
||||
float x2 = head->x2;
|
||||
@ -348,48 +390,32 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
|
||||
float *color = info->selection_color;
|
||||
float d = fminf(
|
||||
(tick - head->transition_begin) / (double) HOVER_USECS, 1.f);
|
||||
if (!head->hovered) {
|
||||
(tick - head->hover_begin) / (double) HOVER_USECS, 1.f);
|
||||
if (!head->hovered)
|
||||
d = 1.f - d;
|
||||
}
|
||||
d *= 2.f;
|
||||
if (d <= 1.f) {
|
||||
d = d * d;
|
||||
} else {
|
||||
d -= 1.f;
|
||||
d = d * (2.f - d) + 1.f;
|
||||
}
|
||||
d /= 2.f;
|
||||
float alpha = color[3] * d * .5f;
|
||||
float alpha = color[3] * ease(d) * .5f;
|
||||
|
||||
PUSH_POINT(tri_ptr, x1, y1)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT(tri_ptr, x2, y1)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT(tri_ptr, x1, y2)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT(tri_ptr, x1, y2)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT(tri_ptr, x2, y1)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT(tri_ptr, x2, y2)
|
||||
PUSH_COLOR(tri_ptr, color[0], color[1], color[2], alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x1, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x2, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x1, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x1, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x2, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(tri_ptr, x2, y2, color, alpha)
|
||||
|
||||
tris += 6;
|
||||
tri_verts += 6;
|
||||
}
|
||||
i++;
|
||||
if (i >= HEADS_MAX) {
|
||||
if (i >= HEADS_MAX)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tris > 0) {
|
||||
if (tri_verts > 0) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glUseProgram(res->color_program);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[1]);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[COLOR_BUFFER]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||
tris * BT_COLOR_VERT_SIZE * sizeof(float), res->tris);
|
||||
tri_verts * BT_COLOR_VERT_SIZE * sizeof(float), res->verts);
|
||||
glEnableVertexAttribArray(res->color_position_attribute);
|
||||
glEnableVertexAttribArray(res->color_color_attribute);
|
||||
glVertexAttribPointer(res->color_position_attribute, 2, GL_FLOAT, GL_FALSE,
|
||||
@ -397,13 +423,113 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
||||
glVertexAttribPointer(res->color_color_attribute, 4, GL_FLOAT, GL_FALSE,
|
||||
BT_COLOR_VERT_SIZE * sizeof(float), (void *) (2 * sizeof(float)));
|
||||
glUniform2fv(res->color_screen_size_uniform, 1, screen_size);
|
||||
glDrawArrays(GL_TRIANGLES, 0, tris);
|
||||
glDrawArrays(GL_TRIANGLES, 0, tri_verts);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
unsigned int line_verts = 0;
|
||||
i = 0;
|
||||
float *line_ptr = res->verts;
|
||||
if (any_clicked || (click_begin && tick < click_begin + HOVER_USECS)) {
|
||||
const float ox = -info->scroll_x - info->x_origin;
|
||||
const float oy = -info->scroll_y - info->y_origin;
|
||||
const float sx = screen_size[0];
|
||||
const float sy = screen_size[1];
|
||||
|
||||
float color[4];
|
||||
lerp_color(color, info->selection_color, info->fg_color, .5f);
|
||||
float d = fminf(
|
||||
(tick - click_begin) / (double) HOVER_USECS, 1.f);
|
||||
if (!any_clicked)
|
||||
d = 1.f - d;
|
||||
float alpha = color[3] * ease(d) * .5f;
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, ox, oy, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, sx, oy, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, ox, oy, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, ox, sy, color, alpha)
|
||||
|
||||
line_verts += 4;
|
||||
}
|
||||
wl_list_for_each(head, &info->heads, link) {
|
||||
float x1 = head->x1;
|
||||
float y1 = head->y1;
|
||||
float x2 = head->x2;
|
||||
float y2 = head->y2;
|
||||
|
||||
float *color = info->fg_color;
|
||||
float alpha = color[3] * (head->clicked ? .5f : .25f);
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||
|
||||
line_verts += 8;
|
||||
|
||||
if (any_clicked || (click_begin && tick < click_begin + HOVER_USECS)) {
|
||||
float d = fminf(
|
||||
(tick - click_begin) / (double) HOVER_USECS, 1.f);
|
||||
if (!any_clicked)
|
||||
d = 1.f - d;
|
||||
alpha = color[3] * ease(d) * (head->clicked ? .15f : .075f);
|
||||
|
||||
const float sx = screen_size[0];
|
||||
const float sy = screen_size[1];
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, 0, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, 0, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y1, color, alpha)
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, sx, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, 0, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y1, color, alpha)
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, sx, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, sy, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x2, y2, color, alpha)
|
||||
|
||||
PUSH_POINT_COLOR(line_ptr, 0, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, sy, color, alpha)
|
||||
PUSH_POINT_COLOR(line_ptr, x1, y2, color, alpha)
|
||||
|
||||
line_verts += 16;
|
||||
}
|
||||
|
||||
i++;
|
||||
if (i >= HEADS_MAX)
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_verts > 0) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glUseProgram(res->color_program);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, res->buffers[LINE_BUFFER]);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0,
|
||||
line_verts * BT_LINE_VERT_SIZE * sizeof(float), res->verts);
|
||||
glEnableVertexAttribArray(res->color_position_attribute);
|
||||
glEnableVertexAttribArray(res->color_color_attribute);
|
||||
glVertexAttribPointer(res->color_position_attribute, 2, GL_FLOAT, GL_FALSE,
|
||||
BT_LINE_VERT_SIZE * sizeof(float), (void *) (0 * sizeof(float)));
|
||||
glVertexAttribPointer(res->color_color_attribute, 4, GL_FLOAT, GL_FALSE,
|
||||
BT_LINE_VERT_SIZE * sizeof(float), (void *) (2 * sizeof(float)));
|
||||
glUniform2fv(res->color_screen_size_uniform, 1, screen_size);
|
||||
glDrawArrays(GL_LINES, 0, line_verts);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
void wd_gl_cleanup(struct wd_gl_data *res) {
|
||||
glDeleteBuffers(2, res->buffers);
|
||||
glDeleteBuffers(NUM_BUFFERS, res->buffers);
|
||||
glDeleteShader(res->texture_fragment_shader);
|
||||
glDeleteShader(res->texture_vertex_shader);
|
||||
glDeleteProgram(res->texture_program);
|
||||
|
@ -156,7 +156,8 @@ struct wd_render_head_flags {
|
||||
struct wd_render_head_data {
|
||||
struct wl_list link;
|
||||
uint64_t updated_at;
|
||||
uint64_t transition_begin;
|
||||
uint64_t hover_begin;
|
||||
uint64_t click_begin;
|
||||
|
||||
float x1;
|
||||
float y1;
|
||||
@ -175,6 +176,7 @@ struct wd_render_head_data {
|
||||
bool y_invert;
|
||||
bool swap_rgb;
|
||||
bool hovered;
|
||||
bool clicked;
|
||||
};
|
||||
|
||||
struct wd_render_data {
|
||||
|
Loading…
Reference in New Issue
Block a user