Skip to content
This repository has been archived by the owner on Nov 1, 2021. It is now read-only.

scene: add wlr_scene_xdg_popup_create #3298

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/wlr/types/wlr_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

struct wlr_output;
struct wlr_output_layout;
struct wlr_xdg_popup;

enum wlr_scene_node_type {
WLR_SCENE_NODE_ROOT,
Expand Down Expand Up @@ -298,4 +299,11 @@ bool wlr_scene_attach_output_layout(struct wlr_scene *scene,
struct wlr_scene_node *wlr_scene_subsurface_tree_create(
struct wlr_scene_node *parent, struct wlr_surface *surface);

/**
* Add a node displaying an xdg_popup and all of its sub-surfaces to the
* scene-graph.
*/
struct wlr_scene_node *wlr_scene_xdg_popup_create(
struct wlr_scene_node *parent, struct wlr_xdg_popup *popup);

#endif
1 change: 1 addition & 0 deletions types/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ wlr_files += files(
'scene/subsurface_tree.c',
'scene/wlr_scene.c',
'scene/output_layout.c',
'scene/xdg_shell.c',
'seat/wlr_seat_keyboard.c',
'seat/wlr_seat_pointer.c',
'seat/wlr_seat_touch.c',
Expand Down
114 changes: 114 additions & 0 deletions types/scene/xdg_shell.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include <stdlib.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_xdg_shell.h>

struct wlr_scene_xdg_popup {
struct wlr_scene_tree *tree;
struct wlr_xdg_popup *popup;
struct wlr_scene_node *surface_node;

struct wl_listener tree_destroy;
struct wl_listener popup_destroy;
struct wl_listener popup_map;
struct wl_listener popup_unmap;
struct wl_listener popup_ack_configure;
};

static void scene_popup_handle_tree_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_xdg_popup *scene_popup =
wl_container_of(listener, scene_popup, tree_destroy);
// tree and surface_node will be cleaned up by scene_node_finish
wl_list_remove(&scene_popup->tree_destroy.link);
wl_list_remove(&scene_popup->popup_destroy.link);
wl_list_remove(&scene_popup->popup_map.link);
wl_list_remove(&scene_popup->popup_unmap.link);
wl_list_remove(&scene_popup->popup_ack_configure.link);
free(scene_popup);
}

static void scene_popup_handle_popup_destroy(struct wl_listener *listener,
void *data) {
struct wlr_scene_xdg_popup *scene_popup =
wl_container_of(listener, scene_popup, popup_destroy);
wlr_scene_node_destroy(&scene_popup->tree->node);
}

static void scene_popup_handle_popup_map(struct wl_listener *listener,
void *data) {
struct wlr_scene_xdg_popup *scene_popup =
wl_container_of(listener, scene_popup, popup_map);
wlr_scene_node_set_enabled(&scene_popup->tree->node, true);
}

static void scene_popup_handle_popup_unmap(struct wl_listener *listener,
void *data) {
struct wlr_scene_xdg_popup *scene_popup =
wl_container_of(listener, scene_popup, popup_unmap);
wlr_scene_node_set_enabled(&scene_popup->tree->node, false);
}

static void scene_popup_update_position(
struct wlr_scene_xdg_popup *scene_popup) {
struct wlr_xdg_popup *popup = scene_popup->popup;

struct wlr_box geo = {0};
wlr_xdg_surface_get_geometry(popup->base, &geo);

wlr_scene_node_set_position(&scene_popup->tree->node,
popup->geometry.x - geo.x, popup->geometry.y - geo.y);
}

static void scene_popup_handle_popup_ack_configure(struct wl_listener *listener,
void *data) {
struct wlr_scene_xdg_popup *scene_popup =
wl_container_of(listener, scene_popup, popup_ack_configure);
scene_popup_update_position(scene_popup);
}

struct wlr_scene_node *wlr_scene_xdg_popup_create(
struct wlr_scene_node *parent, struct wlr_xdg_popup *popup) {
struct wlr_scene_xdg_popup *scene_popup = calloc(1, sizeof(*scene_popup));
if (scene_popup == NULL) {
return NULL;
}

scene_popup->popup = popup;

scene_popup->tree = wlr_scene_tree_create(parent);
if (scene_popup->tree == NULL) {
free(scene_popup);
return NULL;
}

scene_popup->surface_node = wlr_scene_subsurface_tree_create(
&scene_popup->tree->node, popup->base->surface);
if (scene_popup->surface_node == NULL) {
wlr_scene_node_destroy(&scene_popup->tree->node);
free(scene_popup);
return NULL;
}

scene_popup->tree_destroy.notify = scene_popup_handle_tree_destroy;
wl_signal_add(&scene_popup->tree->node.events.destroy,
&scene_popup->tree_destroy);

scene_popup->popup_destroy.notify = scene_popup_handle_popup_destroy;
wl_signal_add(&popup->base->events.destroy, &scene_popup->popup_destroy);

scene_popup->popup_map.notify = scene_popup_handle_popup_map;
wl_signal_add(&popup->base->events.map, &scene_popup->popup_map);

scene_popup->popup_unmap.notify = scene_popup_handle_popup_unmap;
wl_signal_add(&popup->base->events.unmap, &scene_popup->popup_unmap);

scene_popup->popup_ack_configure.notify =
scene_popup_handle_popup_ack_configure;
wl_signal_add(&popup->base->events.ack_configure,
&scene_popup->popup_ack_configure);

wlr_scene_node_set_enabled(&scene_popup->tree->node, popup->base->mapped);
scene_popup_update_position(scene_popup);

return &scene_popup->tree->node;
}