Render popups separately from their toplevel view when possible

This commit is contained in:
Jente Hidskes 2020-01-05 14:39:56 +01:00
parent 2db815aa23
commit a53dca91ce
7 changed files with 101 additions and 33 deletions

View file

@ -100,7 +100,7 @@ output_for_each_surface_iterator(struct wlr_surface *surface, int sx, int sy, vo
data->user_iterator(data->output, surface, &box, data->user_data); data->user_iterator(data->output, surface, &box, data->user_data);
} }
static void void
output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface, output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface,
double ox, double oy, cg_surface_iterator_func_t iterator, double ox, double oy, cg_surface_iterator_func_t iterator,
void *user_data) void *user_data)
@ -116,7 +116,7 @@ output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *su
wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data); wlr_surface_for_each_surface(surface, output_for_each_surface_iterator, &data);
} }
void static void
output_view_for_each_surface(struct cg_output *output, struct cg_view *view, output_view_for_each_surface(struct cg_output *output, struct cg_view *view,
cg_surface_iterator_func_t iterator, void *user_data) cg_surface_iterator_func_t iterator, void *user_data)
{ {
@ -132,6 +132,49 @@ output_view_for_each_surface(struct cg_output *output, struct cg_view *view,
view_for_each_surface(view, output_for_each_surface_iterator, &data); view_for_each_surface(view, output_for_each_surface_iterator, &data);
} }
void
output_view_for_each_popup(struct cg_output *output, struct cg_view *view,
cg_surface_iterator_func_t iterator, void *user_data)
{
struct surface_iterator_data data = {
.user_iterator = iterator,
.user_data = user_data,
.output = output,
.ox = view->lx,
.oy = view->ly,
};
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &data.ox, &data.oy);
view_for_each_popup(view, output_for_each_surface_iterator, &data);
}
void
output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons,
cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_drag_icon *drag_icon;
wl_list_for_each(drag_icon, drag_icons, link) {
if (drag_icon->wlr_drag_icon->mapped) {
double ox = drag_icon->lx;
double oy = drag_icon->ly;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy);
output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface,
ox, oy, iterator, user_data);
}
}
}
static void
output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_view *view;
wl_list_for_each_reverse(view, &output->server->views, link) {
output_view_for_each_surface(output, view, iterator, user_data);
}
output_drag_icons_for_each_surface(output, &output->server->seat->drag_icons, iterator, user_data);
}
struct send_frame_done_data { struct send_frame_done_data {
struct timespec when; struct timespec when;
}; };
@ -187,33 +230,6 @@ output_damage_surface(struct cg_output *output, struct wlr_surface *surface,
output_surface_for_each_surface(output, surface, ox, oy, damage_surface_iterator, &whole); output_surface_for_each_surface(output, surface, ox, oy, damage_surface_iterator, &whole);
} }
void
output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons,
cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_drag_icon *drag_icon;
wl_list_for_each(drag_icon, drag_icons, link) {
if (drag_icon->wlr_drag_icon->mapped) {
double ox = drag_icon->lx;
double oy = drag_icon->ly;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy);
output_surface_for_each_surface(output, drag_icon->wlr_drag_icon->surface,
ox, oy, iterator, user_data);
}
}
}
static void
output_for_each_surface(struct cg_output *output, cg_surface_iterator_func_t iterator, void *user_data)
{
struct cg_view *view;
wl_list_for_each_reverse(view, &output->server->views, link) {
output_view_for_each_surface(output, view, iterator, user_data);
}
output_drag_icons_for_each_surface(output, &output->server->seat->drag_icons, iterator, user_data);
}
static void static void
handle_output_damage_frame(struct wl_listener *listener, void *data) handle_output_damage_frame(struct wl_listener *listener, void *data)
{ {

View file

@ -26,7 +26,10 @@ struct cg_output {
typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data); typedef void (*cg_surface_iterator_func_t)(struct cg_output *output, struct wlr_surface *surface, struct wlr_box *box, void *user_data);
void handle_new_output(struct wl_listener *listener, void *data); void handle_new_output(struct wl_listener *listener, void *data);
void output_view_for_each_surface(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator, void *user_data); void output_surface_for_each_surface(struct cg_output *output, struct wlr_surface *surface,
double ox, double oy, cg_surface_iterator_func_t iterator,
void *user_data);
void output_view_for_each_popup(struct cg_output *output, struct cg_view *view, cg_surface_iterator_func_t iterator, void *user_data);
void output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, cg_surface_iterator_func_t iterator, void *user_data); void output_drag_icons_for_each_surface(struct cg_output *output, struct wl_list *drag_icons, cg_surface_iterator_func_t iterator, void *user_data);
void output_damage_surface(struct cg_output *output, struct wlr_surface *surface, double lx, double ly, bool whole); void output_damage_surface(struct cg_output *output, struct wlr_surface *surface, double lx, double ly, bool whole);
void output_set_window_title(struct cg_output *output, const char *title); void output_set_window_title(struct cg_output *output, const char *title);

View file

@ -115,8 +115,32 @@ render_view_toplevels(struct cg_view *view, struct cg_output *output, pixman_reg
struct render_data data = { struct render_data data = {
.damage = damage, .damage = damage,
}; };
double ox = view->lx;
double oy = view->ly;
wlr_output_layout_output_coords(output->server->output_layout, output->wlr_output, &ox, &oy);
output_surface_for_each_surface(output, view->wlr_surface, ox, oy,
render_surface_iterator, &data);
}
output_view_for_each_surface(output, view, render_surface_iterator, &data); static void
render_popup_iterator(struct cg_output *output, struct wlr_surface *surface,
struct wlr_box *box, void *data)
{
/* Render this popup's surface. */
render_surface_iterator(output, surface, box, data);
/* Render this popup's child toplevels. */
output_surface_for_each_surface(output, surface, box->x, box->y,
render_surface_iterator, data);
}
static void
render_view_popups(struct cg_view *view, struct cg_output *output, pixman_region32_t *damage)
{
struct render_data data = {
.damage = damage,
};
output_view_for_each_popup(output, view, render_popup_iterator, &data);
} }
void void
@ -151,8 +175,11 @@ output_render(struct cg_output *output, pixman_region32_t *damage)
struct cg_view *view; struct cg_view *view;
wl_list_for_each_reverse(view, &server->views, link) { wl_list_for_each_reverse(view, &server->views, link) {
render_view_toplevels(view, output, damage); render_view_toplevels(view, output, damage);
// TODO: popups on top view, possibly use focused view for this }
// TODO: render only top view, possibly use focused view for this
struct cg_view *focused_view = seat_get_focus(server->seat);
if (focused_view) {
render_view_popups(focused_view, output, damage);
} }
render_drag_icons(output, damage, &server->seat->drag_icons); render_drag_icons(output, damage, &server->seat->drag_icons);

9
view.c
View file

@ -197,6 +197,15 @@ view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator
view->impl->for_each_surface(view, iterator, data); view->impl->for_each_surface(view, iterator, data);
} }
void
view_for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data)
{
if (!view->impl->for_each_popup) {
return;
}
view->impl->for_each_popup(view, iterator, data);
}
void void
view_unmap(struct cg_view *view) view_unmap(struct cg_view *view)
{ {

3
view.h
View file

@ -46,6 +46,8 @@ struct cg_view_impl {
void (*destroy)(struct cg_view *view); void (*destroy)(struct cg_view *view);
void (*for_each_surface)(struct cg_view *view, wlr_surface_iterator_func_t iterator, void (*for_each_surface)(struct cg_view *view, wlr_surface_iterator_func_t iterator,
void *data); void *data);
void (*for_each_popup)(struct cg_view *view, wlr_surface_iterator_func_t iterator,
void *data);
struct wlr_surface *(*wlr_surface_at)(struct cg_view *view, double sx, double sy, struct wlr_surface *(*wlr_surface_at)(struct cg_view *view, double sx, double sy,
double *sub_x, double *sub_y); double *sub_x, double *sub_y);
}; };
@ -76,6 +78,7 @@ void view_damage_whole(struct cg_view *view);
void view_activate(struct cg_view *view, bool activate); void view_activate(struct cg_view *view, bool activate);
void view_position(struct cg_view *view); void view_position(struct cg_view *view);
void view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data); void view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data);
void view_for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data);
void view_unmap(struct cg_view *view); void view_unmap(struct cg_view *view);
void view_map(struct cg_view *view, struct wlr_surface *surface); void view_map(struct cg_view *view, struct wlr_surface *surface);
void view_destroy(struct cg_view *view); void view_destroy(struct cg_view *view);

View file

@ -222,6 +222,13 @@ for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, voi
wlr_xdg_surface_for_each_surface(xdg_shell_view->xdg_surface, iterator, data); wlr_xdg_surface_for_each_surface(xdg_shell_view->xdg_surface, iterator, data);
} }
static void
for_each_popup(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data)
{
struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view);
wlr_xdg_surface_for_each_popup(xdg_shell_view->xdg_surface, iterator, data);
}
static struct wlr_surface * static struct wlr_surface *
wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y) wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y)
{ {
@ -297,6 +304,7 @@ static const struct cg_view_impl xdg_shell_view_impl = {
.maximize = maximize, .maximize = maximize,
.destroy = destroy, .destroy = destroy,
.for_each_surface = for_each_surface, .for_each_surface = for_each_surface,
.for_each_popup = for_each_popup,
.wlr_surface_at = wlr_surface_at, .wlr_surface_at = wlr_surface_at,
}; };

View file

@ -180,6 +180,8 @@ static const struct cg_view_impl xwayland_view_impl = {
.maximize = maximize, .maximize = maximize,
.destroy = destroy, .destroy = destroy,
.for_each_surface = for_each_surface, .for_each_surface = for_each_surface,
/* XWayland doesn't have a separate popup iterator. */
.for_each_popup = NULL,
.wlr_surface_at = wlr_surface_at, .wlr_surface_at = wlr_surface_at,
}; };