mirror of
https://github.com/artizirk/wdisplays.git
synced 2024-11-22 00:40:59 +02:00
Reorder render list when clicking a display
This commit is contained in:
parent
1fba2b78a8
commit
26af01ddc3
91
src/main.c
91
src/main.c
@ -248,9 +248,9 @@ static gboolean redraw_canvas(GtkWidget *widget, GdkFrameClock *frame_clock, gpo
|
|||||||
|
|
||||||
static void update_tick_callback(struct wd_state *state) {
|
static void update_tick_callback(struct wd_state *state) {
|
||||||
bool any_animate = false;
|
bool any_animate = false;
|
||||||
for (int i = 0; i < state->render.head_count; i++) {
|
struct wd_render_head_data *render;
|
||||||
struct wd_render_head_data *head = &state->render.heads[i];
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
if (state->render.updated_at < head->transition_begin + HOVER_USECS) {
|
if (state->render.updated_at < render->transition_begin + HOVER_USECS) {
|
||||||
any_animate = true;
|
any_animate = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -299,31 +299,34 @@ static void update_hovered(struct wd_state *state) {
|
|||||||
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
GdkFrameClock *clock = gtk_widget_get_frame_clock(state->canvas);
|
||||||
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
uint64_t tick = gdk_frame_clock_get_frame_time(clock);
|
||||||
g_autoptr(GList) seats = gdk_display_list_seats(display);
|
g_autoptr(GList) seats = gdk_display_list_seats(display);
|
||||||
struct wd_head *head;
|
bool any_hovered = false;
|
||||||
wl_list_for_each(head, &state->heads, link) {
|
struct wd_render_head_data *render;
|
||||||
struct wd_render_head_data *render = head->render;
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
if (render != NULL) {
|
bool init_hovered = render->hovered;
|
||||||
bool init_hovered = render->hovered;
|
render->hovered = false;
|
||||||
render->hovered = false;
|
if (any_hovered) {
|
||||||
if (state->clicked == head) {
|
continue;
|
||||||
render->hovered = true;
|
}
|
||||||
} else if (state->clicked == NULL) {
|
if (state->clicked == render) {
|
||||||
for (GList *iter = seats; iter != NULL; iter = iter->next) {
|
render->hovered = true;
|
||||||
double mouse_x;
|
any_hovered = true;
|
||||||
double mouse_y;
|
} else if (state->clicked == NULL) {
|
||||||
|
for (GList *iter = seats; iter != NULL; iter = iter->next) {
|
||||||
|
double mouse_x;
|
||||||
|
double mouse_y;
|
||||||
|
|
||||||
GdkDevice *pointer = gdk_seat_get_pointer(GDK_SEAT(iter->data));
|
GdkDevice *pointer = gdk_seat_get_pointer(GDK_SEAT(iter->data));
|
||||||
gdk_window_get_device_position_double(window, pointer, &mouse_x, &mouse_y, NULL);
|
gdk_window_get_device_position_double(window, pointer, &mouse_x, &mouse_y, NULL);
|
||||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||||
render->hovered = true;
|
render->hovered = true;
|
||||||
break;
|
any_hovered = true;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (init_hovered != render->hovered) {
|
}
|
||||||
render->transition_begin = tick;
|
if (init_hovered != render->hovered) {
|
||||||
}
|
render->transition_begin = tick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_cursor(state);
|
update_cursor(state);
|
||||||
@ -353,7 +356,6 @@ static void queue_canvas_draw(struct wd_state *state) {
|
|||||||
|
|
||||||
cache_scroll(state);
|
cache_scroll(state);
|
||||||
|
|
||||||
state->render.head_count = 0;
|
|
||||||
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
||||||
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
||||||
GtkBuilder *builder = GTK_BUILDER(g_object_get_data(G_OBJECT(form_iter->data), "builder"));
|
GtkBuilder *builder = GTK_BUILDER(g_object_get_data(G_OBJECT(form_iter->data), "builder"));
|
||||||
@ -368,16 +370,15 @@ static void queue_canvas_draw(struct wd_state *state) {
|
|||||||
scale = 1.;
|
scale = 1.;
|
||||||
|
|
||||||
struct wd_head *head = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
struct wd_head *head = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
||||||
struct wd_render_head_data *render = &state->render.heads[state->render.head_count];
|
if (head->render == NULL) {
|
||||||
|
head->render = calloc(1, sizeof(*head->render));
|
||||||
|
wl_list_insert(&state->render.heads, &head->render->link);
|
||||||
|
}
|
||||||
|
struct wd_render_head_data *render = head->render;
|
||||||
render->x1 = floor(x * state->zoom - state->render.scroll_x - state->render.x_origin);
|
render->x1 = floor(x * state->zoom - state->render.scroll_x - state->render.x_origin);
|
||||||
render->y1 = floor(y * state->zoom - state->render.scroll_y - state->render.y_origin);
|
render->y1 = floor(y * state->zoom - state->render.scroll_y - state->render.y_origin);
|
||||||
render->x2 = floor(render->x1 + w * state->zoom / scale);
|
render->x2 = floor(render->x1 + w * state->zoom / scale);
|
||||||
render->y2 = floor(render->y1 + h * state->zoom / scale);
|
render->y2 = floor(render->y1 + h * state->zoom / scale);
|
||||||
head->render = render;
|
|
||||||
|
|
||||||
state->render.head_count++;
|
|
||||||
if (state->render.head_count >= HEADS_MAX)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtk_gl_area_queue_render(GTK_GL_AREA(state->canvas));
|
gtk_gl_area_queue_render(GTK_GL_AREA(state->canvas));
|
||||||
@ -869,8 +870,8 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
|||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
if (event->button.type == GDK_BUTTON_PRESS) {
|
if (event->button.type == GDK_BUTTON_PRESS) {
|
||||||
if (event->button.button == 1) {
|
if (event->button.button == 1) {
|
||||||
int i = 0;
|
|
||||||
struct wd_head *head;
|
struct wd_head *head;
|
||||||
|
state->clicked = NULL;
|
||||||
wl_list_for_each(head, &state->heads, link) {
|
wl_list_for_each(head, &state->heads, link) {
|
||||||
struct wd_render_head_data *render = head->render;
|
struct wd_render_head_data *render = head->render;
|
||||||
if (render != NULL) {
|
if (render != NULL) {
|
||||||
@ -878,19 +879,27 @@ static gboolean canvas_click(GtkWidget *widget, GdkEvent *event,
|
|||||||
double mouse_y = event->button.y;
|
double mouse_y = event->button.y;
|
||||||
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
if (mouse_x >= render->x1 && mouse_x < render->x2 &&
|
||||||
mouse_y >= render->y1 && mouse_y < render->y2) {
|
mouse_y >= render->y1 && mouse_y < render->y2) {
|
||||||
state->clicked = head;
|
state->clicked = render;
|
||||||
state->click_offset.x = event->button.x - render->x1;
|
state->click_offset.x = event->button.x - render->x1;
|
||||||
state->click_offset.y = event->button.y - render->y1;
|
state->click_offset.y = event->button.y - render->y1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
if (state->clicked != NULL) {
|
if (state->clicked != NULL) {
|
||||||
|
wl_list_remove(&state->clicked->link);
|
||||||
|
wl_list_insert(&state->render.heads, &state->clicked->link);
|
||||||
|
|
||||||
|
struct wd_render_head_data *render;
|
||||||
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
|
render->updated_at = 0;
|
||||||
|
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));
|
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
||||||
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
||||||
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
||||||
if (state->clicked == other) {
|
if (state->clicked == other->render) {
|
||||||
gtk_stack_set_visible_child(GTK_STACK(state->stack), form_iter->data);
|
gtk_stack_set_visible_child(GTK_STACK(state->stack), form_iter->data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -939,7 +948,7 @@ static gboolean canvas_motion(GtkWidget *widget, GdkEvent *event,
|
|||||||
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
g_autoptr(GList) forms = gtk_container_get_children(GTK_CONTAINER(state->stack));
|
||||||
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
||||||
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
||||||
if (state->clicked == other) {
|
if (state->clicked == other->render) {
|
||||||
form = form_iter->data;
|
form = form_iter->data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -965,7 +974,7 @@ static gboolean canvas_motion(GtkWidget *widget, GdkEvent *event,
|
|||||||
|
|
||||||
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
for (GList *form_iter = forms; form_iter != NULL; form_iter = form_iter->next) {
|
||||||
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
const struct wd_head *other = g_object_get_data(G_OBJECT(form_iter->data), "head");
|
||||||
if (other != state->clicked && !(event->motion.state & GDK_SHIFT_MASK)) {
|
if (other->render != state->clicked && !(event->motion.state & GDK_SHIFT_MASK)) {
|
||||||
GtkBuilder *other_builder = GTK_BUILDER(g_object_get_data(G_OBJECT(form_iter->data), "builder"));
|
GtkBuilder *other_builder = GTK_BUILDER(g_object_get_data(G_OBJECT(form_iter->data), "builder"));
|
||||||
double x1 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(other_builder, "pos_x")));
|
double x1 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(other_builder, "pos_x")));
|
||||||
double y1 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(other_builder, "pos_y")));
|
double y1 = gtk_spin_button_get_value(GTK_SPIN_BUTTON(gtk_builder_get_object(other_builder, "pos_y")));
|
||||||
@ -1024,9 +1033,9 @@ static gboolean canvas_enter(GtkWidget *widget, GdkEvent *event,
|
|||||||
static gboolean canvas_leave(GtkWidget *widget, GdkEvent *event,
|
static gboolean canvas_leave(GtkWidget *widget, GdkEvent *event,
|
||||||
gpointer data) {
|
gpointer data) {
|
||||||
struct wd_state *state = data;
|
struct wd_state *state = data;
|
||||||
for (int i = 0; i < state->render.head_count; i++) {
|
struct wd_render_head_data *render;
|
||||||
struct wd_render_head_data *head = &state->render.heads[i];
|
wl_list_for_each(render, &state->render.heads, link) {
|
||||||
head->hovered = false;
|
render->hovered = false;
|
||||||
}
|
}
|
||||||
update_tick_callback(state);
|
update_tick_callback(state);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -312,10 +312,15 @@ static void wd_mode_destroy(struct wd_mode* mode) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void wd_head_destroy(struct wd_head *head) {
|
static void wd_head_destroy(struct wd_head *head) {
|
||||||
struct wd_mode *mode, *mode_tmp;
|
if (head->state->clicked == head->render) {
|
||||||
if (head->state->clicked == head) {
|
|
||||||
head->state->clicked = NULL;
|
head->state->clicked = NULL;
|
||||||
}
|
}
|
||||||
|
if (head->render != NULL) {
|
||||||
|
wl_list_remove(&head->render->link);
|
||||||
|
free(head->render);
|
||||||
|
head->render = NULL;
|
||||||
|
}
|
||||||
|
struct wd_mode *mode, *mode_tmp;
|
||||||
wl_list_for_each_safe(mode, mode_tmp, &head->modes, link) {
|
wl_list_for_each_safe(mode, mode_tmp, &head->modes, link) {
|
||||||
zwlr_output_mode_v1_destroy(mode->wlr_mode);
|
zwlr_output_mode_v1_destroy(mode->wlr_mode);
|
||||||
free(mode);
|
free(mode);
|
||||||
@ -630,6 +635,7 @@ struct wd_state *wd_state_create(void) {
|
|||||||
state->capture = true;
|
state->capture = true;
|
||||||
wl_list_init(&state->heads);
|
wl_list_init(&state->heads);
|
||||||
wl_list_init(&state->outputs);
|
wl_list_init(&state->outputs);
|
||||||
|
wl_list_init(&state->render.heads);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
src/render.c
39
src/render.c
@ -27,6 +27,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <epoxy/gl.h>
|
#include <epoxy/gl.h>
|
||||||
|
#include <wayland-util.h>
|
||||||
|
|
||||||
#define CANVAS_MARGIN 100
|
#define CANVAS_MARGIN 100
|
||||||
|
|
||||||
@ -228,10 +229,15 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
uint64_t tick) {
|
uint64_t tick) {
|
||||||
unsigned int tris = 0;
|
unsigned int tris = 0;
|
||||||
|
|
||||||
if (info->head_count > res->texture_count) {
|
unsigned int head_count = wl_list_length(&info->heads);
|
||||||
glGenTextures(info->head_count - res->texture_count,
|
if (head_count >= HEADS_MAX) {
|
||||||
|
head_count = HEADS_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (head_count > res->texture_count) {
|
||||||
|
glGenTextures(head_count - res->texture_count,
|
||||||
res->textures + res->texture_count);
|
res->textures + res->texture_count);
|
||||||
for (int i = res->texture_count; i < info->head_count; i++) {
|
for (int i = res->texture_count; i < head_count; i++) {
|
||||||
glBindTexture(GL_TEXTURE_2D, res->textures[i]);
|
glBindTexture(GL_TEXTURE_2D, res->textures[i]);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
@ -239,11 +245,12 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
}
|
}
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
res->texture_count = info->head_count;
|
res->texture_count = head_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < info->head_count; i++) {
|
struct wd_render_head_data *head;
|
||||||
struct wd_render_head_data *head = &info->heads[i];
|
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->tris + i * BT_UV_QUAD_SIZE;
|
||||||
float x1 = head->x1;
|
float x1 = head->x1;
|
||||||
float y1 = head->y1;
|
float y1 = head->y1;
|
||||||
@ -261,6 +268,10 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
PUSH_POINT_UV(tri_ptr, x2, y2, 1.f, t2)
|
PUSH_POINT_UV(tri_ptr, x2, y2, 1.f, t2)
|
||||||
|
|
||||||
tris += 6;
|
tris += 6;
|
||||||
|
i++;
|
||||||
|
if (i >= HEADS_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glClearColor(info->bg_color[0], info->bg_color[1], info->bg_color[2], 1.f);
|
glClearColor(info->bg_color[0], info->bg_color[1], info->bg_color[2], 1.f);
|
||||||
@ -284,8 +295,8 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
glUniform1i(res->texture_texture_uniform, 0);
|
glUniform1i(res->texture_texture_uniform, 0);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
for (int i = 0; i < info->head_count; i++) {
|
i = 0;
|
||||||
struct wd_render_head_data *head = &info->heads[i];
|
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||||
glBindTexture(GL_TEXTURE_2D, res->textures[i]);
|
glBindTexture(GL_TEXTURE_2D, res->textures[i]);
|
||||||
if (head->updated_at == tick) {
|
if (head->updated_at == tick) {
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, head->tex_stride / 4);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, head->tex_stride / 4);
|
||||||
@ -297,14 +308,18 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
glUniformMatrix4fv(res->texture_color_transform_uniform, 1, GL_FALSE,
|
glUniformMatrix4fv(res->texture_color_transform_uniform, 1, GL_FALSE,
|
||||||
head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR);
|
head->swap_rgb ? TRANSFORM_RGB : TRANSFORM_BGR);
|
||||||
glDrawArrays(GL_TRIANGLES, i * 6, 6);
|
glDrawArrays(GL_TRIANGLES, i * 6, 6);
|
||||||
|
i++;
|
||||||
|
if (i >= HEADS_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tris = 0;
|
tris = 0;
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
for (int i = 0; i < info->head_count; i++) {
|
i = 0;
|
||||||
struct wd_render_head_data *head = &info->heads[i];
|
wl_list_for_each_reverse(head, &info->heads, link) {
|
||||||
if (head->hovered || tick < head->transition_begin + HOVER_USECS) {
|
if (head->hovered || tick < head->transition_begin + HOVER_USECS) {
|
||||||
float *tri_ptr = res->tris + j++ * BT_COLOR_QUAD_SIZE;
|
float *tri_ptr = res->tris + j++ * BT_COLOR_QUAD_SIZE;
|
||||||
float x1 = head->x1;
|
float x1 = head->x1;
|
||||||
@ -343,6 +358,10 @@ void wd_gl_render(struct wd_gl_data *res, struct wd_render_data *info,
|
|||||||
|
|
||||||
tris += 6;
|
tris += 6;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
|
if (i >= HEADS_MAX) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tris > 0) {
|
if (tris > 0) {
|
||||||
|
@ -144,6 +144,8 @@ struct wd_head {
|
|||||||
struct wd_gl_data;
|
struct wd_gl_data;
|
||||||
|
|
||||||
struct wd_render_head_data {
|
struct wd_render_head_data {
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
float x1;
|
float x1;
|
||||||
float y1;
|
float y1;
|
||||||
float x2;
|
float x2;
|
||||||
@ -177,8 +179,7 @@ struct wd_render_data {
|
|||||||
int y_origin;
|
int y_origin;
|
||||||
uint64_t updated_at;
|
uint64_t updated_at;
|
||||||
|
|
||||||
unsigned int head_count;
|
struct wl_list heads;
|
||||||
struct wd_render_head_data heads[HEADS_MAX];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wd_point {
|
struct wd_point {
|
||||||
@ -200,7 +201,7 @@ struct wd_state {
|
|||||||
bool capture;
|
bool capture;
|
||||||
double zoom;
|
double zoom;
|
||||||
|
|
||||||
struct wd_head *clicked;
|
struct wd_render_head_data *clicked;
|
||||||
/* top left, bottom right */
|
/* top left, bottom right */
|
||||||
struct wd_point click_offset;
|
struct wd_point click_offset;
|
||||||
bool panning;
|
bool panning;
|
||||||
|
Loading…
Reference in New Issue
Block a user