diff options
author | Tony Crisci <tony@dubstepdish.com> | 2018-04-05 12:32:42 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-05 12:32:42 -0400 |
commit | b3a1cf10735572bf0a13e66bbc6c2a1d452c5385 (patch) | |
tree | d3fb74ee77369ad52edeba7bac1f3ada907d3099 | |
parent | Error handling in swaylock daemonize() (diff) | |
parent | Implement shell views (diff) | |
download | sway-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.h | 104 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 79 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 110 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 123 | ||||
-rw-r--r-- | sway/tree/view.c | 13 |
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 | ||
10 | struct sway_container; | 10 | struct sway_container; |
11 | struct sway_view; | ||
12 | 11 | ||
13 | struct sway_xdg_surface_v6 { | 12 | enum 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 | |||
18 | enum sway_view_prop { | ||
19 | VIEW_PROP_TITLE, | ||
20 | VIEW_PROP_APP_ID, | ||
21 | VIEW_PROP_CLASS, | ||
22 | VIEW_PROP_INSTANCE, | ||
23 | }; | ||
24 | |||
25 | struct 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 | |||
35 | struct 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 | |||
50 | struct 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 | ||
27 | struct sway_xwayland_surface { | 64 | struct 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 | ||
49 | struct sway_wl_shell_surface { | 86 | struct 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 | ||
61 | enum sway_view_type { | ||
62 | SWAY_VIEW_WL_SHELL, | ||
63 | SWAY_VIEW_XDG_SHELL_V6, | ||
64 | SWAY_VIEW_XWAYLAND, | ||
65 | }; | ||
66 | |||
67 | enum sway_view_prop { | ||
68 | VIEW_PROP_TITLE, | ||
69 | VIEW_PROP_APP_ID, | ||
70 | VIEW_PROP_CLASS, | ||
71 | VIEW_PROP_INSTANCE, | ||
72 | }; | ||
73 | |||
74 | struct 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 | |||
83 | struct 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 | |||
104 | struct sway_view *view_create(enum sway_view_type type, | ||
105 | const struct sway_view_impl *impl); | ||
106 | |||
107 | void view_destroy(struct sway_view *view); | ||
108 | |||
109 | const char *view_get_title(struct sway_view *view); | 98 | const char *view_get_title(struct sway_view *view); |
110 | 99 | ||
111 | const char *view_get_app_id(struct sway_view *view); | 100 | const 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 | ||
119 | void view_init(struct sway_view *view, enum sway_view_type type, | ||
120 | const struct sway_view_impl *impl); | ||
121 | |||
122 | void view_destroy(struct sway_view *view); | ||
123 | |||
130 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); | 124 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); |
131 | 125 | ||
132 | void view_unmap(struct sway_view *view); | 126 | void 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 | ||
14 | static bool assert_wl_shell(struct sway_view *view) { | 14 | static 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 | ||
19 | static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | 23 | static 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 | ||
33 | static void configure(struct sway_view *view, double ox, double oy, int width, | 37 | static 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 | ||
44 | static void _close(struct sway_view *view) { | 49 | static 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 | ||
57 | static 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 | |||
52 | static const struct sway_view_impl view_impl = { | 67 | static 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 | ||
58 | static void handle_commit(struct wl_listener *listener, void *data) { | 73 | static 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 | ||
69 | static void handle_destroy(struct wl_listener *listener, void *data) { | 84 | static 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 | ||
78 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | 90 | void 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 | ||
14 | static bool assert_xdg(struct sway_view *view) { | 14 | static 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 | ||
19 | static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | 23 | static 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 | ||
33 | static void configure(struct sway_view *view, double ox, double oy, int width, | 37 | static 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 | ||
45 | static void set_activated(struct sway_view *view, bool activated) { | 51 | static 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 | ||
55 | static void _close(struct sway_view *view) { | 61 | static 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 | ||
71 | static 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 | |||
65 | static const struct sway_view_impl view_impl = { | 84 | static 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 | ||
72 | static void handle_commit(struct wl_listener *listener, void *data) { | 91 | static 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 | ||
84 | static void handle_unmap(struct wl_listener *listener, void *data) { | 103 | static 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 | ||
90 | static void handle_map(struct wl_listener *listener, void *data) { | 109 | static 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 | ||
97 | static void handle_destroy(struct wl_listener *listener, void *data) { | 116 | static 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 | ||
108 | void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | 122 | void 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 | ||
44 | static bool assert_xwayland(struct sway_view *view) { | 44 | static 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 | ||
49 | static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | 53 | static 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 | ||
63 | static void configure(struct sway_view *view, double ox, double oy, int width, | 67 | static 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 | ||
93 | static void set_activated(struct sway_view *view, bool activated) { | 98 | static 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 | ||
101 | static void _close(struct sway_view *view) { | 106 | static 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 | ||
113 | static 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 | |||
108 | static const struct sway_view_impl view_impl = { | 125 | static 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 | ||
115 | static void handle_commit(struct wl_listener *listener, void *data) { | 132 | static 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 | ||
126 | static void handle_destroy(struct wl_listener *listener, void *data) { | 143 | static 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 | ||
138 | static void handle_unmap(struct wl_listener *listener, void *data) { | 149 | static 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 | ||
144 | static void handle_map(struct wl_listener *listener, void *data) { | 156 | static 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 | ||
155 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 172 | static 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 | ||
167 | void handle_xwayland_surface(struct wl_listener *listener, void *data) { | 184 | void 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 | ||
10 | struct sway_view *view_create(enum sway_view_type type, | 10 | void 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 | ||
21 | void view_destroy(struct sway_view *view) { | 16 | void 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 | ||
33 | const char *view_get_title(struct sway_view *view) { | 34 | const char *view_get_title(struct sway_view *view) { |