aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-05 12:32:42 -0400
committerLibravatar GitHub <noreply@github.com>2018-04-05 12:32:42 -0400
commitb3a1cf10735572bf0a13e66bbc6c2a1d452c5385 (patch)
treed3fb74ee77369ad52edeba7bac1f3ada907d3099
parentError handling in swaylock daemonize() (diff)
parentImplement shell views (diff)
downloadsway-b3a1cf10735572bf0a13e66bbc6c2a1d452c5385.tar.gz
sway-b3a1cf10735572bf0a13e66bbc6c2a1d452c5385.tar.zst
sway-b3a1cf10735572bf0a13e66bbc6c2a1d452c5385.zip
Merge pull request #1742 from emersion/shell-views
Implement shell views
-rw-r--r--include/sway/tree/view.h104
-rw-r--r--sway/desktop/wl_shell.c79
-rw-r--r--sway/desktop/xdg_shell_v6.c110
-rw-r--r--sway/desktop/xwayland.c123
-rw-r--r--sway/tree/view.c13
5 files changed, 225 insertions, 204 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index f32ccc5a..d4dace4a 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -8,10 +8,47 @@
8#include "sway/input/seat.h" 8#include "sway/input/seat.h"
9 9
10struct sway_container; 10struct sway_container;
11struct sway_view;
12 11
13struct sway_xdg_surface_v6 { 12enum sway_view_type {
14 struct sway_view *view; 13 SWAY_VIEW_WL_SHELL,
14 SWAY_VIEW_XDG_SHELL_V6,
15 SWAY_VIEW_XWAYLAND,
16};
17
18enum sway_view_prop {
19 VIEW_PROP_TITLE,
20 VIEW_PROP_APP_ID,
21 VIEW_PROP_CLASS,
22 VIEW_PROP_INSTANCE,
23};
24
25struct sway_view_impl {
26 const char *(*get_prop)(struct sway_view *view,
27 enum sway_view_prop prop);
28 void (*configure)(struct sway_view *view, double ox, double oy, int width,
29 int height);
30 void (*set_activated)(struct sway_view *view, bool activated);
31 void (*close)(struct sway_view *view);
32 void (*destroy)(struct sway_view *view);
33};
34
35struct sway_view {
36 enum sway_view_type type;
37 const struct sway_view_impl *impl;
38
39 struct sway_container *swayc; // NULL for unmanaged views
40 struct wlr_surface *surface; // NULL for unmapped views
41 int width, height;
42
43 union {
44 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
45 struct wlr_xwayland_surface *wlr_xwayland_surface;
46 struct wlr_wl_shell_surface *wlr_wl_shell_surface;
47 };
48};
49
50struct sway_xdg_shell_v6_view {
51 struct sway_view view;
15 52
16 struct wl_listener commit; 53 struct wl_listener commit;
17 struct wl_listener request_move; 54 struct wl_listener request_move;
@@ -24,8 +61,8 @@ struct sway_xdg_surface_v6 {
24 int pending_width, pending_height; 61 int pending_width, pending_height;
25}; 62};
26 63
27struct sway_xwayland_surface { 64struct sway_xwayland_view {
28 struct sway_view *view; 65 struct sway_view view;
29 66
30 struct wl_listener commit; 67 struct wl_listener commit;
31 struct wl_listener request_move; 68 struct wl_listener request_move;
@@ -46,8 +83,8 @@ struct sway_xwayland_unmanaged {
46 struct wl_listener destroy; 83 struct wl_listener destroy;
47}; 84};
48 85
49struct sway_wl_shell_surface { 86struct sway_wl_shell_view {
50 struct sway_view *view; 87 struct sway_view view;
51 88
52 struct wl_listener commit; 89 struct wl_listener commit;
53 struct wl_listener request_move; 90 struct wl_listener request_move;
@@ -58,54 +95,6 @@ struct sway_wl_shell_surface {
58 int pending_width, pending_height; 95 int pending_width, pending_height;
59}; 96};
60 97
61enum sway_view_type {
62 SWAY_VIEW_WL_SHELL,
63 SWAY_VIEW_XDG_SHELL_V6,
64 SWAY_VIEW_XWAYLAND,
65};
66
67enum sway_view_prop {
68 VIEW_PROP_TITLE,
69 VIEW_PROP_APP_ID,
70 VIEW_PROP_CLASS,
71 VIEW_PROP_INSTANCE,
72};
73
74struct sway_view_impl {
75 const char *(*get_prop)(struct sway_view *view,
76 enum sway_view_prop prop);
77 void (*configure)(struct sway_view *view, double ox, double oy, int width,
78 int height);
79 void (*set_activated)(struct sway_view *view, bool activated);
80 void (*close)(struct sway_view *view);
81};
82
83struct sway_view {
84 enum sway_view_type type;
85 const struct sway_view_impl *impl;
86
87 struct sway_container *swayc; // NULL for unmanaged views
88 struct wlr_surface *surface; // NULL for unmapped views
89 int width, height;
90
91 union {
92 struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
93 struct wlr_xwayland_surface *wlr_xwayland_surface;
94 struct wlr_wl_shell_surface *wlr_wl_shell_surface;
95 };
96
97 union {
98 struct sway_xdg_surface_v6 *sway_xdg_surface_v6;
99 struct sway_xwayland_surface *sway_xwayland_surface;
100 struct sway_wl_shell_surface *sway_wl_shell_surface;
101 };
102};
103
104struct sway_view *view_create(enum sway_view_type type,
105 const struct sway_view_impl *impl);
106
107void view_destroy(struct sway_view *view);
108
109const char *view_get_title(struct sway_view *view); 98const char *view_get_title(struct sway_view *view);
110 99
111const char *view_get_app_id(struct sway_view *view); 100const char *view_get_app_id(struct sway_view *view);
@@ -127,6 +116,11 @@ void view_damage_from(struct sway_view *view);
127 116
128// view implementation 117// view implementation
129 118
119void view_init(struct sway_view *view, enum sway_view_type type,
120 const struct sway_view_impl *impl);
121
122void view_destroy(struct sway_view *view);
123
130void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); 124void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
131 125
132void view_unmap(struct sway_view *view); 126void view_unmap(struct sway_view *view);
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index a470674d..5955fa9d 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -11,13 +11,17 @@
11#include "sway/input/input-manager.h" 11#include "sway/input/input-manager.h"
12#include "log.h" 12#include "log.h"
13 13
14static bool assert_wl_shell(struct sway_view *view) { 14static struct sway_wl_shell_view *wl_shell_view_from_view(
15 return sway_assert(view->type == SWAY_VIEW_WL_SHELL, 15 struct sway_view *view) {
16 "Expecting wl_shell view!"); 16 if (!sway_assert(view->type == SWAY_VIEW_WL_SHELL,
17 "Expected wl_shell view")) {
18 return NULL;
19 }
20 return (struct sway_wl_shell_view *)view;
17} 21}
18 22
19static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { 23static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
20 if (!assert_wl_shell(view)) { 24 if (wl_shell_view_from_view(view) == NULL) {
21 return NULL; 25 return NULL;
22 } 26 }
23 switch (prop) { 27 switch (prop) {
@@ -32,23 +36,34 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
32 36
33static void configure(struct sway_view *view, double ox, double oy, int width, 37static void configure(struct sway_view *view, double ox, double oy, int width,
34 int height) { 38 int height) {
35 if (!assert_wl_shell(view)) { 39 struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view);
40 if (wl_shell_view == NULL) {
36 return; 41 return;
37 } 42 }
38 view_update_position(view, ox, oy); 43 view_update_position(view, ox, oy);
39 view->sway_wl_shell_surface->pending_width = width; 44 wl_shell_view->pending_width = width;
40 view->sway_wl_shell_surface->pending_height = height; 45 wl_shell_view->pending_height = height;
41 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); 46 wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height);
42} 47}
43 48
44static void _close(struct sway_view *view) { 49static void _close(struct sway_view *view) {
45 if (!assert_wl_shell(view)) { 50 if (wl_shell_view_from_view(view) == NULL) {
46 return; 51 return;
47 } 52 }
48 53
49 wl_client_destroy(view->wlr_wl_shell_surface->client); 54 wl_client_destroy(view->wlr_wl_shell_surface->client);
50} 55}
51 56
57static void destroy(struct sway_view *view) {
58 struct sway_wl_shell_view *wl_shell_view = wl_shell_view_from_view(view);
59 if (wl_shell_view == NULL) {
60 return;
61 }
62 wl_list_remove(&wl_shell_view->commit.link);
63 wl_list_remove(&wl_shell_view->destroy.link);
64 free(wl_shell_view);
65}
66
52static const struct sway_view_impl view_impl = { 67static const struct sway_view_impl view_impl = {
53 .get_prop = get_prop, 68 .get_prop = get_prop,
54 .configure = configure, 69 .configure = configure,
@@ -56,23 +71,20 @@ static const struct sway_view_impl view_impl = {
56}; 71};
57 72
58static void handle_commit(struct wl_listener *listener, void *data) { 73static void handle_commit(struct wl_listener *listener, void *data) {
59 struct sway_wl_shell_surface *sway_surface = 74 struct sway_wl_shell_view *wl_shell_view =
60 wl_container_of(listener, sway_surface, commit); 75 wl_container_of(listener, wl_shell_view, commit);
61 struct sway_view *view = sway_surface->view; 76 struct sway_view *view = &wl_shell_view->view;
62 // NOTE: We intentionally discard the view's desired width here 77 // NOTE: We intentionally discard the view's desired width here
63 // TODO: Let floating views do whatever 78 // TODO: Let floating views do whatever
64 view_update_size(view, sway_surface->pending_width, 79 view_update_size(view, wl_shell_view->pending_width,
65 sway_surface->pending_height); 80 wl_shell_view->pending_height);
66 view_damage_from(view); 81 view_damage_from(view);
67} 82}
68 83
69static void handle_destroy(struct wl_listener *listener, void *data) { 84static void handle_destroy(struct wl_listener *listener, void *data) {
70 struct sway_wl_shell_surface *sway_surface = 85 struct sway_wl_shell_view *wl_shell_view =
71 wl_container_of(listener, sway_surface, destroy); 86 wl_container_of(listener, wl_shell_view, destroy);
72 wl_list_remove(&sway_surface->commit.link); 87 view_destroy(&wl_shell_view->view);
73 wl_list_remove(&sway_surface->destroy.link);
74 view_destroy(sway_surface->view);
75 free(sway_surface);
76} 88}
77 89
78void handle_wl_shell_surface(struct wl_listener *listener, void *data) { 90void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
@@ -82,42 +94,37 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
82 94
83 if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { 95 if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) {
84 // popups don't get views 96 // popups don't get views
97 wlr_log(L_DEBUG, "New wl_shell popup");
85 return; 98 return;
86 } 99 }
87 100
88 // TODO make transient windows floating 101 // TODO: make transient windows floating
89 102
90 wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'", 103 wlr_log(L_DEBUG, "New wl_shell toplevel title='%s' app_id='%s'",
91 shell_surface->title, shell_surface->class); 104 shell_surface->title, shell_surface->class);
92 wlr_wl_shell_surface_ping(shell_surface); 105 wlr_wl_shell_surface_ping(shell_surface);
93 106
94 struct sway_wl_shell_surface *sway_surface = 107 struct sway_wl_shell_view *wl_shell_view =
95 calloc(1, sizeof(struct sway_wl_shell_surface)); 108 calloc(1, sizeof(struct sway_wl_shell_view));
96 if (!sway_assert(sway_surface, "Failed to allocate surface!")) { 109 if (!sway_assert(wl_shell_view, "Failed to allocate view")) {
97 return; 110 return;
98 } 111 }
99 112
100 struct sway_view *view = view_create(SWAY_VIEW_WL_SHELL, &view_impl); 113 view_init(&wl_shell_view->view, SWAY_VIEW_WL_SHELL, &view_impl);
101 if (!sway_assert(view, "Failed to allocate view")) { 114 wl_shell_view->view.wlr_wl_shell_surface = shell_surface;
102 return;
103 }
104 view->wlr_wl_shell_surface = shell_surface;
105 view->sway_wl_shell_surface = sway_surface;
106 sway_surface->view = view;
107 115
108 // TODO: 116 // TODO:
109 // - Wire up listeners 117 // - Wire up listeners
110 // - Handle popups
111 // - Look up pid and open on appropriate workspace 118 // - Look up pid and open on appropriate workspace
112 // - Set new view to maximized so it behaves nicely 119 // - Set new view to maximized so it behaves nicely
113 // - Criteria 120 // - Criteria
114 121
115 sway_surface->commit.notify = handle_commit; 122 wl_shell_view->commit.notify = handle_commit;
116 wl_signal_add(&shell_surface->surface->events.commit, 123 wl_signal_add(&shell_surface->surface->events.commit,
117 &sway_surface->commit); 124 &wl_shell_view->commit);
118 125
119 sway_surface->destroy.notify = handle_destroy; 126 wl_shell_view->destroy.notify = handle_destroy;
120 wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); 127 wl_signal_add(&shell_surface->events.destroy, &wl_shell_view->destroy);
121 128
122 view_map(view, shell_surface->surface); 129 view_map(&wl_shell_view->view, shell_surface->surface);
123} 130}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 5cdb8f9f..7b9d5fb7 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -11,13 +11,17 @@
11#include "sway/input/input-manager.h" 11#include "sway/input/input-manager.h"
12#include "log.h" 12#include "log.h"
13 13
14static bool assert_xdg(struct sway_view *view) { 14static struct sway_xdg_shell_v6_view *xdg_shell_v6_view_from_view(
15 return sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6, 15 struct sway_view *view) {
16 "Expected xdg shell v6 view!"); 16 if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6,
17 "Expected xdg_shell_v6 view")) {
18 return NULL;
19 }
20 return (struct sway_xdg_shell_v6_view *)view;
17} 21}
18 22
19static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { 23static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
20 if (!assert_xdg(view)) { 24 if (xdg_shell_v6_view_from_view(view) == NULL) {
21 return NULL; 25 return NULL;
22 } 26 }
23 switch (prop) { 27 switch (prop) {
@@ -32,18 +36,20 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
32 36
33static void configure(struct sway_view *view, double ox, double oy, int width, 37static void configure(struct sway_view *view, double ox, double oy, int width,
34 int height) { 38 int height) {
35 if (!assert_xdg(view)) { 39 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
40 xdg_shell_v6_view_from_view(view);
41 if (xdg_shell_v6_view == NULL) {
36 return; 42 return;
37 } 43 }
38 44
39 view_update_position(view, ox, oy); 45 view_update_position(view, ox, oy);
40 view->sway_xdg_surface_v6->pending_width = width; 46 xdg_shell_v6_view->pending_width = width;
41 view->sway_xdg_surface_v6->pending_height = height; 47 xdg_shell_v6_view->pending_height = height;
42 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); 48 wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height);
43} 49}
44 50
45static void set_activated(struct sway_view *view, bool activated) { 51static void set_activated(struct sway_view *view, bool activated) {
46 if (!assert_xdg(view)) { 52 if (xdg_shell_v6_view_from_view(view) == NULL) {
47 return; 53 return;
48 } 54 }
49 struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; 55 struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6;
@@ -53,7 +59,7 @@ static void set_activated(struct sway_view *view, bool activated) {
53} 59}
54 60
55static void _close(struct sway_view *view) { 61static void _close(struct sway_view *view) {
56 if (!assert_xdg(view)) { 62 if (xdg_shell_v6_view_from_view(view) == NULL) {
57 return; 63 return;
58 } 64 }
59 struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; 65 struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6;
@@ -62,6 +68,19 @@ static void _close(struct sway_view *view) {
62 } 68 }
63} 69}
64 70
71static void destroy(struct sway_view *view) {
72 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
73 xdg_shell_v6_view_from_view(view);
74 if (xdg_shell_v6_view == NULL) {
75 return;
76 }
77 wl_list_remove(&xdg_shell_v6_view->commit.link);
78 wl_list_remove(&xdg_shell_v6_view->destroy.link);
79 wl_list_remove(&xdg_shell_v6_view->map.link);
80 wl_list_remove(&xdg_shell_v6_view->unmap.link);
81 free(xdg_shell_v6_view);
82}
83
65static const struct sway_view_impl view_impl = { 84static const struct sway_view_impl view_impl = {
66 .get_prop = get_prop, 85 .get_prop = get_prop,
67 .configure = configure, 86 .configure = configure,
@@ -70,83 +89,74 @@ static const struct sway_view_impl view_impl = {
70}; 89};
71 90
72static void handle_commit(struct wl_listener *listener, void *data) { 91static void handle_commit(struct wl_listener *listener, void *data) {
73 struct sway_xdg_surface_v6 *sway_surface = 92 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
74 wl_container_of(listener, sway_surface, commit); 93 wl_container_of(listener, xdg_shell_v6_view, commit);
75 struct sway_view *view = sway_surface->view; 94 struct sway_view *view = &xdg_shell_v6_view->view;
76 // NOTE: We intentionally discard the view's desired width here 95 // NOTE: We intentionally discard the view's desired width here
77 // TODO: Store this for restoration when moving to floating plane 96 // TODO: Store this for restoration when moving to floating plane
78 // TODO: Let floating views do whatever 97 // TODO: Let floating views do whatever
79 view_update_size(view, sway_surface->pending_width, 98 view_update_size(view, xdg_shell_v6_view->pending_width,
80 sway_surface->pending_height); 99 xdg_shell_v6_view->pending_height);
81 view_damage_from(view); 100 view_damage_from(view);
82} 101}
83 102
84static void handle_unmap(struct wl_listener *listener, void *data) { 103static void handle_unmap(struct wl_listener *listener, void *data) {
85 struct sway_xdg_surface_v6 *sway_surface = 104 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
86 wl_container_of(listener, sway_surface, unmap); 105 wl_container_of(listener, xdg_shell_v6_view, unmap);
87 view_unmap(sway_surface->view); 106 view_unmap(&xdg_shell_v6_view->view);
88} 107}
89 108
90static void handle_map(struct wl_listener *listener, void *data) { 109static void handle_map(struct wl_listener *listener, void *data) {
91 struct sway_xdg_surface_v6 *sway_surface = 110 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
92 wl_container_of(listener, sway_surface, map); 111 wl_container_of(listener, xdg_shell_v6_view, map);
93 struct sway_view *view = sway_surface->view; 112 struct sway_view *view = &xdg_shell_v6_view->view;
94 view_map(view, view->wlr_xdg_surface_v6->surface); 113 view_map(view, view->wlr_xdg_surface_v6->surface);
95} 114}
96 115
97static void handle_destroy(struct wl_listener *listener, void *data) { 116static void handle_destroy(struct wl_listener *listener, void *data) {
98 struct sway_xdg_surface_v6 *sway_xdg_surface = 117 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
99 wl_container_of(listener, sway_xdg_surface, destroy); 118 wl_container_of(listener, xdg_shell_v6_view, destroy);
100 wl_list_remove(&sway_xdg_surface->commit.link); 119 view_destroy(&xdg_shell_v6_view->view);
101 wl_list_remove(&sway_xdg_surface->destroy.link);
102 wl_list_remove(&sway_xdg_surface->map.link);
103 wl_list_remove(&sway_xdg_surface->unmap.link);
104 view_destroy(sway_xdg_surface->view);
105 free(sway_xdg_surface);
106} 120}
107 121
108void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { 122void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
109 struct sway_server *server = wl_container_of( 123 struct sway_server *server = wl_container_of(listener, server,
110 listener, server, xdg_shell_v6_surface); 124 xdg_shell_v6_surface);
111 struct wlr_xdg_surface_v6 *xdg_surface = data; 125 struct wlr_xdg_surface_v6 *xdg_surface = data;
112 126
113 if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) { 127 if (xdg_surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
114 // TODO: popups 128 wlr_log(L_DEBUG, "New xdg_shell_v6 popup");
115 return; 129 return;
116 } 130 }
117 131
118 wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'", 132 wlr_log(L_DEBUG, "New xdg_shell_v6 toplevel title='%s' app_id='%s'",
119 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); 133 xdg_surface->toplevel->title, xdg_surface->toplevel->app_id);
120 wlr_xdg_surface_v6_ping(xdg_surface); 134 wlr_xdg_surface_v6_ping(xdg_surface);
121 wlr_xdg_toplevel_v6_set_maximized(xdg_surface, true); 135 wlr_xdg_toplevel_v6_set_maximized(xdg_surface, true);
122 136
123 struct sway_xdg_surface_v6 *sway_surface = 137 struct sway_xdg_shell_v6_view *xdg_shell_v6_view =
124 calloc(1, sizeof(struct sway_xdg_surface_v6)); 138 calloc(1, sizeof(struct sway_xdg_shell_v6_view));
125 if (!sway_assert(sway_surface, "Failed to allocate surface!")) { 139 if (!sway_assert(xdg_shell_v6_view, "Failed to allocate view")) {
126 return; 140 return;
127 } 141 }
128 142
129 struct sway_view *view = view_create(SWAY_VIEW_XDG_SHELL_V6, &view_impl); 143 view_init(&xdg_shell_v6_view->view, SWAY_VIEW_XDG_SHELL_V6, &view_impl);
130 if (!sway_assert(view, "Failed to allocate view")) { 144 xdg_shell_v6_view->view.wlr_xdg_surface_v6 = xdg_surface;
131 return;
132 }
133 view->wlr_xdg_surface_v6 = xdg_surface;
134 view->sway_xdg_surface_v6 = sway_surface;
135 sway_surface->view = view;
136 145
137 // TODO: 146 // TODO:
138 // - Look up pid and open on appropriate workspace 147 // - Look up pid and open on appropriate workspace
139 // - Criteria 148 // - Criteria
140 149
141 sway_surface->commit.notify = handle_commit; 150 xdg_shell_v6_view->commit.notify = handle_commit;
142 wl_signal_add(&xdg_surface->surface->events.commit, &sway_surface->commit); 151 wl_signal_add(&xdg_surface->surface->events.commit,
152 &xdg_shell_v6_view->commit);
143 153
144 sway_surface->map.notify = handle_map; 154 xdg_shell_v6_view->map.notify = handle_map;
145 wl_signal_add(&xdg_surface->events.map, &sway_surface->map); 155 wl_signal_add(&xdg_surface->events.map, &xdg_shell_v6_view->map);
146 156
147 sway_surface->unmap.notify = handle_unmap; 157 xdg_shell_v6_view->unmap.notify = handle_unmap;
148 wl_signal_add(&xdg_surface->events.unmap, &sway_surface->unmap); 158 wl_signal_add(&xdg_surface->events.unmap, &xdg_shell_v6_view->unmap);
149 159
150 sway_surface->destroy.notify = handle_destroy; 160 xdg_shell_v6_view->destroy.notify = handle_destroy;
151 wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); 161 wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_v6_view->destroy);
152} 162}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index a793928c..384f4236 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -41,13 +41,17 @@ static void create_unmanaged(struct wlr_xwayland_surface *xsurface) {
41} 41}
42 42
43 43
44static bool assert_xwayland(struct sway_view *view) { 44static struct sway_xwayland_view *xwayland_view_from_view(
45 return sway_assert(view->type == SWAY_VIEW_XWAYLAND, 45 struct sway_view *view) {
46 "Expected xwayland view!"); 46 if (!sway_assert(view->type == SWAY_VIEW_XWAYLAND,
47 "Expected xwayland view")) {
48 return NULL;
49 }
50 return (struct sway_xwayland_view *)view;
47} 51}
48 52
49static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { 53static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
50 if (!assert_xwayland(view)) { 54 if (xwayland_view_from_view(view) == NULL) {
51 return NULL; 55 return NULL;
52 } 56 }
53 switch (prop) { 57 switch (prop) {
@@ -62,7 +66,8 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) {
62 66
63static void configure(struct sway_view *view, double ox, double oy, int width, 67static void configure(struct sway_view *view, double ox, double oy, int width,
64 int height) { 68 int height) {
65 if (!assert_xwayland(view)) { 69 struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view);
70 if (xwayland_view == NULL) {
66 return; 71 return;
67 } 72 }
68 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 73 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
@@ -84,14 +89,14 @@ static void configure(struct sway_view *view, double ox, double oy, int width,
84 89
85 view_update_position(view, ox, oy); 90 view_update_position(view, ox, oy);
86 91
87 view->sway_xwayland_surface->pending_width = width; 92 xwayland_view->pending_width = width;
88 view->sway_xwayland_surface->pending_height = height; 93 xwayland_view->pending_height = height;
89 wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, 94 wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y,
90 width, height); 95 width, height);
91} 96}
92 97
93static void set_activated(struct sway_view *view, bool activated) { 98static void set_activated(struct sway_view *view, bool activated) {
94 if (!assert_xwayland(view)) { 99 if (xwayland_view_from_view(view) == NULL) {
95 return; 100 return;
96 } 101 }
97 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; 102 struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface;
@@ -99,12 +104,24 @@ static void set_activated(struct sway_view *view, bool activated) {
99} 104}
100 105
101static void _close(struct sway_view *view) { 106static void _close(struct sway_view *view) {
102 if (!assert_xwayland(view)) { 107 if (xwayland_view_from_view(view) == NULL) {
103 return; 108 return;
104 } 109 }
105 wlr_xwayland_surface_close(view->wlr_xwayland_surface); 110 wlr_xwayland_surface_close(view->wlr_xwayland_surface);
106} 111}
107 112
113static void destroy(struct sway_view *view) {
114 struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view);
115 if (xwayland_view == NULL) {
116 return;
117 }
118 wl_list_remove(&xwayland_view->destroy.link);
119 wl_list_remove(&xwayland_view->request_configure.link);
120 wl_list_remove(&xwayland_view->map.link);
121 wl_list_remove(&xwayland_view->unmap.link);
122 free(xwayland_view);
123}
124
108static const struct sway_view_impl view_impl = { 125static const struct sway_view_impl view_impl = {
109 .get_prop = get_prop, 126 .get_prop = get_prop,
110 .configure = configure, 127 .configure = configure,
@@ -113,50 +130,50 @@ static const struct sway_view_impl view_impl = {
113}; 130};
114 131
115static void handle_commit(struct wl_listener *listener, void *data) { 132static void handle_commit(struct wl_listener *listener, void *data) {
116 struct sway_xwayland_surface *sway_surface = 133 struct sway_xwayland_view *xwayland_view =
117 wl_container_of(listener, sway_surface, commit); 134 wl_container_of(listener, xwayland_view, commit);
118 struct sway_view *view = sway_surface->view; 135 struct sway_view *view = &xwayland_view->view;
119 // NOTE: We intentionally discard the view's desired width here 136 // NOTE: We intentionally discard the view's desired width here
120 // TODO: Let floating views do whatever 137 // TODO: Let floating views do whatever
121 view_update_size(view, sway_surface->pending_width, 138 view_update_size(view, xwayland_view->pending_width,
122 sway_surface->pending_height); 139 xwayland_view->pending_height);
123 view_damage_from(view); 140 view_damage_from(view);
124} 141}
125 142
126static void handle_destroy(struct wl_listener *listener, void *data) { 143static void handle_destroy(struct wl_listener *listener, void *data) {
127 struct sway_xwayland_surface *sway_surface = 144 struct sway_xwayland_view *xwayland_view =
128 wl_container_of(listener, sway_surface, destroy); 145 wl_container_of(listener, xwayland_view, destroy);
129 wl_list_remove(&sway_surface->commit.link); 146 view_destroy(&xwayland_view->view);
130 wl_list_remove(&sway_surface->destroy.link);
131 wl_list_remove(&sway_surface->request_configure.link);
132 wl_list_remove(&sway_surface->map.link);
133 wl_list_remove(&sway_surface->unmap.link);
134 view_destroy(sway_surface->view);
135 free(sway_surface);
136} 147}
137 148
138static void handle_unmap(struct wl_listener *listener, void *data) { 149static void handle_unmap(struct wl_listener *listener, void *data) {
139 struct sway_xwayland_surface *sway_surface = 150 struct sway_xwayland_view *xwayland_view =
140 wl_container_of(listener, sway_surface, unmap); 151 wl_container_of(listener, xwayland_view, unmap);
141 view_unmap(sway_surface->view); 152 wl_list_remove(&xwayland_view->commit.link);
153 view_unmap(&xwayland_view->view);
142} 154}
143 155
144static void handle_map(struct wl_listener *listener, void *data) { 156static void handle_map(struct wl_listener *listener, void *data) {
145 struct sway_xwayland_surface *sway_surface = 157 struct sway_xwayland_view *xwayland_view =
146 wl_container_of(listener, sway_surface, map); 158 wl_container_of(listener, xwayland_view, map);
147 struct wlr_xwayland_surface *xsurface = data; 159 struct wlr_xwayland_surface *xsurface = data;
148 struct sway_view *view = sway_surface->view; 160 struct sway_view *view = &xwayland_view->view;
161
162 // Wire up the commit listener here, because xwayland map/unmap can change
163 // the underlying wlr_surface
164 wl_signal_add(&xsurface->surface->events.commit, &xwayland_view->commit);
165 xwayland_view->commit.notify = handle_commit;
149 166
150 // put it back into the tree 167 // Put it back into the tree
151 wlr_xwayland_surface_set_maximized(xsurface, true); 168 wlr_xwayland_surface_set_maximized(xsurface, true);
152 view_map(view, xsurface->surface); 169 view_map(view, xsurface->surface);
153} 170}
154 171
155static void handle_request_configure(struct wl_listener *listener, void *data) { 172static void handle_request_configure(struct wl_listener *listener, void *data) {
156 struct sway_xwayland_surface *sway_surface = 173 struct sway_xwayland_view *xwayland_view =
157 wl_container_of(listener, sway_surface, request_configure); 174 wl_container_of(listener, xwayland_view, request_configure);
158 struct wlr_xwayland_surface_configure_event *ev = data; 175 struct wlr_xwayland_surface_configure_event *ev = data;
159 struct sway_view *view = sway_surface->view; 176 struct sway_view *view = &xwayland_view->view;
160 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; 177 struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
161 // TODO: floating windows are allowed to move around like this, but make 178 // TODO: floating windows are allowed to move around like this, but make
162 // sure tiling windows always stay in place. 179 // sure tiling windows always stay in place.
@@ -165,8 +182,8 @@ static void handle_request_configure(struct wl_listener *listener, void *data) {
165} 182}
166 183
167void handle_xwayland_surface(struct wl_listener *listener, void *data) { 184void handle_xwayland_surface(struct wl_listener *listener, void *data) {
168 struct sway_server *server = wl_container_of( 185 struct sway_server *server = wl_container_of(listener, server,
169 listener, server, xwayland_surface); 186 xwayland_surface);
170 struct wlr_xwayland_surface *xsurface = data; 187 struct wlr_xwayland_surface *xsurface = data;
171 188
172 if (wlr_xwayland_surface_is_unmanaged(xsurface) || 189 if (wlr_xwayland_surface_is_unmanaged(xsurface) ||
@@ -179,39 +196,31 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
179 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", 196 wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'",
180 xsurface->title, xsurface->class); 197 xsurface->title, xsurface->class);
181 198
182 struct sway_xwayland_surface *sway_surface = 199 struct sway_xwayland_view *xwayland_view =
183 calloc(1, sizeof(struct sway_xwayland_surface)); 200 calloc(1, sizeof(struct sway_xwayland_view));
184 if (!sway_assert(sway_surface, "Failed to allocate surface")) { 201 if (!sway_assert(xwayland_view, "Failed to allocate view")) {
185 return; 202 return;
186 } 203 }
187 204
188 struct sway_view *view = view_create(SWAY_VIEW_XWAYLAND, &view_impl); 205 view_init(&xwayland_view->view, SWAY_VIEW_XWAYLAND, &view_impl);
189 if (!sway_assert(view, "Failed to allocate view")) { 206 xwayland_view->view.wlr_xwayland_surface = xsurface;
190 return;
191 }
192 view->wlr_xwayland_surface = xsurface;
193 view->sway_xwayland_surface = sway_surface;
194 sway_surface->view = view;
195 207
196 // TODO: 208 // TODO:
197 // - Look up pid and open on appropriate workspace 209 // - Look up pid and open on appropriate workspace
198 // - Criteria 210 // - Criteria
199 211
200 wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); 212 wl_signal_add(&xsurface->events.destroy, &xwayland_view->destroy);
201 sway_surface->commit.notify = handle_commit; 213 xwayland_view->destroy.notify = handle_destroy;
202
203 wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy);
204 sway_surface->destroy.notify = handle_destroy;
205 214
206 wl_signal_add(&xsurface->events.request_configure, 215 wl_signal_add(&xsurface->events.request_configure,
207 &sway_surface->request_configure); 216 &xwayland_view->request_configure);
208 sway_surface->request_configure.notify = handle_request_configure; 217 xwayland_view->request_configure.notify = handle_request_configure;
209 218
210 wl_signal_add(&xsurface->events.unmap, &sway_surface->unmap); 219 wl_signal_add(&xsurface->events.unmap, &xwayland_view->unmap);
211 sway_surface->unmap.notify = handle_unmap; 220 xwayland_view->unmap.notify = handle_unmap;
212 221
213 wl_signal_add(&xsurface->events.map, &sway_surface->map); 222 wl_signal_add(&xsurface->events.map, &xwayland_view->map);
214 sway_surface->map.notify = handle_map; 223 xwayland_view->map.notify = handle_map;
215 224
216 handle_map(&sway_surface->map, xsurface); 225 handle_map(&xwayland_view->map, xsurface);
217} 226}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index aa010a40..3927c195 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -7,15 +7,10 @@
7#include "sway/tree/layout.h" 7#include "sway/tree/layout.h"
8#include "sway/tree/view.h" 8#include "sway/tree/view.h"
9 9
10struct sway_view *view_create(enum sway_view_type type, 10void view_init(struct sway_view *view, enum sway_view_type type,
11 const struct sway_view_impl *impl) { 11 const struct sway_view_impl *impl) {
12 struct sway_view *view = calloc(1, sizeof(struct sway_view));
13 if (view == NULL) {
14 return NULL;
15 }
16 view->type = type; 12 view->type = type;
17 view->impl = impl; 13 view->impl = impl;
18 return view;
19} 14}
20 15
21void view_destroy(struct sway_view *view) { 16void view_destroy(struct sway_view *view) {
@@ -28,6 +23,12 @@ void view_destroy(struct sway_view *view) {
28 } 23 }
29 24
30 container_destroy(view->swayc); 25 container_destroy(view->swayc);
26
27 if (view->impl->destroy) {
28 view->impl->destroy(view);
29 } else {
30 free(view);
31 }
31} 32}
32 33
33const char *view_get_title(struct sway_view *view) { 34const char *view_get_title(struct sway_view *view) {