diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-05-24 22:30:44 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-06-01 23:14:58 +1000 |
commit | 1f2e399ade77070a2d0b82856ad9a3eef96b8676 (patch) | |
tree | c469197e140051aea912cb173723c7e55ce1e410 /sway/desktop | |
parent | Send frame done to floating views (diff) | |
download | sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.tar.gz sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.tar.zst sway-1f2e399ade77070a2d0b82856ad9a3eef96b8676.zip |
Implement floating
Diffstat (limited to 'sway/desktop')
-rw-r--r-- | sway/desktop/output.c | 114 | ||||
-rw-r--r-- | sway/desktop/xdg_shell.c | 32 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 32 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 97 |
4 files changed, 233 insertions, 42 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 95479819..1d21e80f 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -754,9 +754,87 @@ static void render_container(struct sway_output *output, | |||
754 | case L_TABBED: | 754 | case L_TABBED: |
755 | render_container_tabbed(output, damage, con, parent_focused); | 755 | render_container_tabbed(output, damage, con, parent_focused); |
756 | break; | 756 | break; |
757 | case L_FLOATING: | 757 | } |
758 | // TODO | 758 | } |
759 | break; | 759 | |
760 | static bool floater_intersects_output(struct sway_container *floater, | ||
761 | struct sway_container *output) { | ||
762 | struct wlr_box box = { | ||
763 | .x = floater->x, | ||
764 | .y = floater->y, | ||
765 | .width = floater->width, | ||
766 | .height = floater->height, | ||
767 | }; | ||
768 | return wlr_output_layout_intersects(root_container.sway_root->output_layout, | ||
769 | output->sway_output->wlr_output, &box); | ||
770 | } | ||
771 | |||
772 | static void container_translate(struct sway_container *con, int x, int y) { | ||
773 | con->x += x; | ||
774 | con->y += y; | ||
775 | if (con->type == C_VIEW) { | ||
776 | con->sway_view->x += x; | ||
777 | con->sway_view->y += y; | ||
778 | } else { | ||
779 | for (int i = 0; i < con->children->length; ++i) { | ||
780 | struct sway_container *child = con->children->items[i]; | ||
781 | container_translate(child, x, y); | ||
782 | } | ||
783 | } | ||
784 | } | ||
785 | |||
786 | static void render_floating_container(struct sway_output *soutput, | ||
787 | pixman_region32_t *damage, struct sway_container *con) { | ||
788 | // We need to translate the floating container's coordinates from layout | ||
789 | // coordinates into output-local coordinates. This needs to happen for all | ||
790 | // children of the floating container too. | ||
791 | struct sway_container *output = container_parent(con, C_OUTPUT); | ||
792 | container_translate(con, -output->x, -output->y); | ||
793 | |||
794 | if (con->type == C_VIEW) { | ||
795 | struct sway_view *view = con->sway_view; | ||
796 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
797 | struct sway_container *focus = seat_get_focus(seat); | ||
798 | struct border_colors *colors; | ||
799 | struct wlr_texture *title_texture; | ||
800 | struct wlr_texture *marks_texture; | ||
801 | |||
802 | if (focus == con) { | ||
803 | colors = &config->border_colors.focused; | ||
804 | title_texture = con->title_focused; | ||
805 | marks_texture = view->marks_focused; | ||
806 | } else { | ||
807 | colors = &config->border_colors.unfocused; | ||
808 | title_texture = con->title_unfocused; | ||
809 | marks_texture = view->marks_unfocused; | ||
810 | } | ||
811 | render_titlebar(soutput, damage, con, con->x, con->y, con->width, | ||
812 | colors, title_texture, marks_texture); | ||
813 | render_view(soutput, damage, con, colors); | ||
814 | } else { | ||
815 | render_container(soutput, damage, con, false); | ||
816 | } | ||
817 | // Undo the translation | ||
818 | container_translate(con, output->x, output->y); | ||
819 | } | ||
820 | |||
821 | static void render_floating(struct sway_output *soutput, | ||
822 | pixman_region32_t *damage) { | ||
823 | for (int i = 0; i < root_container.children->length; ++i) { | ||
824 | struct sway_container *output = root_container.children->items[i]; | ||
825 | for (int j = 0; j < output->children->length; ++j) { | ||
826 | struct sway_container *workspace = output->children->items[j]; | ||
827 | struct sway_workspace *ws = workspace->sway_workspace; | ||
828 | bool ws_is_visible = workspace_is_visible(workspace); | ||
829 | for (int k = 0; k < ws->floating->children->length; ++k) { | ||
830 | struct sway_container *floater = | ||
831 | ws->floating->children->items[k]; | ||
832 | if ((ws_is_visible || floater->is_sticky) | ||
833 | && floater_intersects_output(floater, soutput->swayc)) { | ||
834 | render_floating_container(soutput, damage, floater); | ||
835 | } | ||
836 | } | ||
837 | } | ||
760 | } | 838 | } |
761 | } | 839 | } |
762 | 840 | ||
@@ -794,8 +872,6 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
794 | goto renderer_end; | 872 | goto renderer_end; |
795 | } | 873 | } |
796 | 874 | ||
797 | //wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); | ||
798 | |||
799 | struct sway_container *workspace = output_get_active_workspace(output); | 875 | struct sway_container *workspace = output_get_active_workspace(output); |
800 | 876 | ||
801 | if (workspace->sway_workspace->fullscreen) { | 877 | if (workspace->sway_workspace->fullscreen) { |
@@ -818,7 +894,6 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
818 | } | 894 | } |
819 | } else { | 895 | } else { |
820 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 896 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
821 | wlr_renderer_clear(renderer, clear_color); | ||
822 | 897 | ||
823 | int nrects; | 898 | int nrects; |
824 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); | 899 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); |
@@ -840,6 +915,8 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
840 | &root_container.sway_root->xwayland_unmanaged); | 915 | &root_container.sway_root->xwayland_unmanaged); |
841 | render_layer(output, damage, | 916 | render_layer(output, damage, |
842 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 917 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); |
918 | |||
919 | render_floating(output, damage); | ||
843 | } | 920 | } |
844 | render_layer(output, damage, | 921 | render_layer(output, damage, |
845 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 922 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); |
@@ -916,6 +993,7 @@ static void send_frame_done(struct sway_output *output, struct timespec *when) { | |||
916 | 993 | ||
917 | struct sway_container *workspace = output_get_active_workspace(output); | 994 | struct sway_container *workspace = output_get_active_workspace(output); |
918 | send_frame_done_container(&data, workspace); | 995 | send_frame_done_container(&data, workspace); |
996 | send_frame_done_container(&data, workspace->sway_workspace->floating); | ||
919 | 997 | ||
920 | send_frame_done_unmanaged(&data, | 998 | send_frame_done_unmanaged(&data, |
921 | &root_container.sway_root->xwayland_unmanaged); | 999 | &root_container.sway_root->xwayland_unmanaged); |
@@ -1037,7 +1115,15 @@ static void output_damage_view(struct sway_output *output, | |||
1037 | 1115 | ||
1038 | void output_damage_from_view(struct sway_output *output, | 1116 | void output_damage_from_view(struct sway_output *output, |
1039 | struct sway_view *view) { | 1117 | struct sway_view *view) { |
1040 | output_damage_view(output, view, false); | 1118 | if (container_self_or_parent_floating(view->swayc)) { |
1119 | view->x -= output->swayc->x; | ||
1120 | view->y -= output->swayc->y; | ||
1121 | output_damage_view(output, view, false); | ||
1122 | view->x += output->swayc->x; | ||
1123 | view->y += output->swayc->y; | ||
1124 | } else { | ||
1125 | output_damage_view(output, view, false); | ||
1126 | } | ||
1041 | } | 1127 | } |
1042 | 1128 | ||
1043 | static void output_damage_whole_container_iterator(struct sway_container *con, | 1129 | static void output_damage_whole_container_iterator(struct sway_container *con, |
@@ -1053,13 +1139,17 @@ static void output_damage_whole_container_iterator(struct sway_container *con, | |||
1053 | 1139 | ||
1054 | void output_damage_whole_container(struct sway_output *output, | 1140 | void output_damage_whole_container(struct sway_output *output, |
1055 | struct sway_container *con) { | 1141 | struct sway_container *con) { |
1056 | float scale = output->wlr_output->scale; | ||
1057 | struct wlr_box box = { | 1142 | struct wlr_box box = { |
1058 | .x = con->x * scale, | 1143 | .x = con->x, |
1059 | .y = con->y * scale, | 1144 | .y = con->y, |
1060 | .width = con->width * scale, | 1145 | .width = con->width, |
1061 | .height = con->height * scale, | 1146 | .height = con->height, |
1062 | }; | 1147 | }; |
1148 | if (con->is_floating) { | ||
1149 | box.x -= output->wlr_output->lx; | ||
1150 | box.y -= output->wlr_output->ly; | ||
1151 | } | ||
1152 | scale_box(&box, output->wlr_output->scale); | ||
1063 | wlr_output_damage_add_box(output->damage, &box); | 1153 | wlr_output_damage_add_box(output->damage, &box); |
1064 | 1154 | ||
1065 | if (con->type == C_VIEW) { | 1155 | if (con->type == C_VIEW) { |
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index b2b95fa0..e1a73b20 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c | |||
@@ -98,6 +98,7 @@ static void configure(struct sway_view *view, double ox, double oy, int width, | |||
98 | xdg_shell_view->pending_width = width; | 98 | xdg_shell_view->pending_width = width; |
99 | xdg_shell_view->pending_height = height; | 99 | xdg_shell_view->pending_height = height; |
100 | wlr_xdg_toplevel_set_size(view->wlr_xdg_surface, width, height); | 100 | wlr_xdg_toplevel_set_size(view->wlr_xdg_surface, width, height); |
101 | view_update_position(view, ox, oy); | ||
101 | } | 102 | } |
102 | 103 | ||
103 | static void set_activated(struct sway_view *view, bool activated) { | 104 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -110,6 +111,14 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
110 | } | 111 | } |
111 | } | 112 | } |
112 | 113 | ||
114 | static void set_maximized(struct sway_view *view, bool maximized) { | ||
115 | if (xdg_shell_view_from_view(view) == NULL) { | ||
116 | return; | ||
117 | } | ||
118 | struct wlr_xdg_surface *surface = view->wlr_xdg_surface; | ||
119 | wlr_xdg_toplevel_set_maximized(surface, maximized); | ||
120 | } | ||
121 | |||
113 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { | 122 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { |
114 | if (xdg_shell_view_from_view(view) == NULL) { | 123 | if (xdg_shell_view_from_view(view) == NULL) { |
115 | return; | 124 | return; |
@@ -118,6 +127,11 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
118 | wlr_xdg_toplevel_set_fullscreen(surface, fullscreen); | 127 | wlr_xdg_toplevel_set_fullscreen(surface, fullscreen); |
119 | } | 128 | } |
120 | 129 | ||
130 | static bool wants_floating(struct sway_view *view) { | ||
131 | // TODO | ||
132 | return false; | ||
133 | } | ||
134 | |||
121 | static void for_each_surface(struct sway_view *view, | 135 | static void for_each_surface(struct sway_view *view, |
122 | wlr_surface_iterator_func_t iterator, void *user_data) { | 136 | wlr_surface_iterator_func_t iterator, void *user_data) { |
123 | if (xdg_shell_view_from_view(view) == NULL) { | 137 | if (xdg_shell_view_from_view(view) == NULL) { |
@@ -154,7 +168,9 @@ static const struct sway_view_impl view_impl = { | |||
154 | .get_string_prop = get_string_prop, | 168 | .get_string_prop = get_string_prop, |
155 | .configure = configure, | 169 | .configure = configure, |
156 | .set_activated = set_activated, | 170 | .set_activated = set_activated, |
171 | .set_maximized = set_maximized, | ||
157 | .set_fullscreen = set_fullscreen, | 172 | .set_fullscreen = set_fullscreen, |
173 | .wants_floating = wants_floating, | ||
158 | .for_each_surface = for_each_surface, | 174 | .for_each_surface = for_each_surface, |
159 | .close = _close, | 175 | .close = _close, |
160 | .destroy = destroy, | 176 | .destroy = destroy, |
@@ -164,11 +180,17 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
164 | struct sway_xdg_shell_view *xdg_shell_view = | 180 | struct sway_xdg_shell_view *xdg_shell_view = |
165 | wl_container_of(listener, xdg_shell_view, commit); | 181 | wl_container_of(listener, xdg_shell_view, commit); |
166 | struct sway_view *view = &xdg_shell_view->view; | 182 | struct sway_view *view = &xdg_shell_view->view; |
167 | // NOTE: We intentionally discard the view's desired width here | 183 | struct wlr_box *geometry = &view->wlr_xdg_surface->geometry; |
168 | // TODO: Store this for restoration when moving to floating plane | 184 | if (!view->natural_width && !view->natural_height) { |
169 | // TODO: Let floating views do whatever | 185 | view->natural_width = geometry->width; |
170 | view_update_size(view, xdg_shell_view->pending_width, | 186 | view->natural_height = geometry->height; |
171 | xdg_shell_view->pending_height); | 187 | } |
188 | if (view->swayc && view->swayc->is_floating) { | ||
189 | view_update_size(view, geometry->width, geometry->height); | ||
190 | } else { | ||
191 | view_update_size(view, xdg_shell_view->pending_width, | ||
192 | xdg_shell_view->pending_height); | ||
193 | } | ||
172 | view_update_title(view, false); | 194 | view_update_title(view, false); |
173 | view_damage_from(view); | 195 | view_damage_from(view); |
174 | } | 196 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index d098c797..47e4162a 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -97,6 +97,7 @@ static void configure(struct sway_view *view, double ox, double oy, int width, | |||
97 | xdg_shell_v6_view->pending_width = width; | 97 | xdg_shell_v6_view->pending_width = width; |
98 | xdg_shell_v6_view->pending_height = height; | 98 | xdg_shell_v6_view->pending_height = height; |
99 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); | 99 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); |
100 | view_update_position(view, ox, oy); | ||
100 | } | 101 | } |
101 | 102 | ||
102 | static void set_activated(struct sway_view *view, bool activated) { | 103 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -109,6 +110,14 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
109 | } | 110 | } |
110 | } | 111 | } |
111 | 112 | ||
113 | static void set_maximized(struct sway_view *view, bool maximized) { | ||
114 | if (xdg_shell_v6_view_from_view(view) == NULL) { | ||
115 | return; | ||
116 | } | ||
117 | struct wlr_xdg_surface_v6 *surface = view->wlr_xdg_surface_v6; | ||
118 | wlr_xdg_toplevel_v6_set_maximized(surface, maximized); | ||
119 | } | ||
120 | |||
112 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { | 121 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { |
113 | if (xdg_shell_v6_view_from_view(view) == NULL) { | 122 | if (xdg_shell_v6_view_from_view(view) == NULL) { |
114 | return; | 123 | return; |
@@ -117,6 +126,11 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
117 | wlr_xdg_toplevel_v6_set_fullscreen(surface, fullscreen); | 126 | wlr_xdg_toplevel_v6_set_fullscreen(surface, fullscreen); |
118 | } | 127 | } |
119 | 128 | ||
129 | static bool wants_floating(struct sway_view *view) { | ||
130 | // TODO | ||
131 | return false; | ||
132 | } | ||
133 | |||
120 | static void for_each_surface(struct sway_view *view, | 134 | static void for_each_surface(struct sway_view *view, |
121 | wlr_surface_iterator_func_t iterator, void *user_data) { | 135 | wlr_surface_iterator_func_t iterator, void *user_data) { |
122 | if (xdg_shell_v6_view_from_view(view) == NULL) { | 136 | if (xdg_shell_v6_view_from_view(view) == NULL) { |
@@ -153,7 +167,9 @@ static const struct sway_view_impl view_impl = { | |||
153 | .get_string_prop = get_string_prop, | 167 | .get_string_prop = get_string_prop, |
154 | .configure = configure, | 168 | .configure = configure, |
155 | .set_activated = set_activated, | 169 | .set_activated = set_activated, |
170 | .set_maximized = set_maximized, | ||
156 | .set_fullscreen = set_fullscreen, | 171 | .set_fullscreen = set_fullscreen, |
172 | .wants_floating = wants_floating, | ||
157 | .for_each_surface = for_each_surface, | 173 | .for_each_surface = for_each_surface, |
158 | .close = _close, | 174 | .close = _close, |
159 | .destroy = destroy, | 175 | .destroy = destroy, |
@@ -163,11 +179,17 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
163 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = | 179 | struct sway_xdg_shell_v6_view *xdg_shell_v6_view = |
164 | wl_container_of(listener, xdg_shell_v6_view, commit); | 180 | wl_container_of(listener, xdg_shell_v6_view, commit); |
165 | struct sway_view *view = &xdg_shell_v6_view->view; | 181 | struct sway_view *view = &xdg_shell_v6_view->view; |
166 | // NOTE: We intentionally discard the view's desired width here | 182 | struct wlr_box *geometry = &view->wlr_xdg_surface_v6->geometry; |
167 | // TODO: Store this for restoration when moving to floating plane | 183 | if (!view->natural_width && !view->natural_height) { |
168 | // TODO: Let floating views do whatever | 184 | view->natural_width = geometry->width; |
169 | view_update_size(view, xdg_shell_v6_view->pending_width, | 185 | view->natural_height = geometry->height; |
170 | xdg_shell_v6_view->pending_height); | 186 | } |
187 | if (view->swayc && view->swayc->is_floating) { | ||
188 | view_update_size(view, geometry->width, geometry->height); | ||
189 | } else { | ||
190 | view_update_size(view, xdg_shell_v6_view->pending_width, | ||
191 | xdg_shell_v6_view->pending_height); | ||
192 | } | ||
171 | view_update_title(view, false); | 193 | view_update_title(view, false); |
172 | view_damage_from(view); | 194 | view_damage_from(view); |
173 | } | 195 | } |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 6a99a66a..56cac1bd 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -152,7 +152,9 @@ static uint32_t get_int_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
152 | } | 152 | } |
153 | } | 153 | } |
154 | 154 | ||
155 | static void configure(struct sway_view *view, double ox, double oy, int width, | 155 | // The x and y arguments are output-local for tiled views, and layout |
156 | // coordinates for floating views. | ||
157 | static void configure(struct sway_view *view, double x, double y, int width, | ||
156 | int height) { | 158 | int height) { |
157 | struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); | 159 | struct sway_xwayland_view *xwayland_view = xwayland_view_from_view(view); |
158 | if (xwayland_view == NULL) { | 160 | if (xwayland_view == NULL) { |
@@ -160,25 +162,33 @@ static void configure(struct sway_view *view, double ox, double oy, int width, | |||
160 | } | 162 | } |
161 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 163 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
162 | 164 | ||
163 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 165 | double lx, ly; |
164 | if (!sway_assert(output, "view must be within tree to set position")) { | 166 | if (view->swayc->is_floating) { |
165 | return; | 167 | lx = x; |
166 | } | 168 | ly = y; |
167 | struct sway_container *root = container_parent(output, C_ROOT); | 169 | } else { |
168 | if (!sway_assert(root, "output must be within tree to set position")) { | 170 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
169 | return; | 171 | if (!sway_assert(output, "view must be within tree to set position")) { |
170 | } | 172 | return; |
171 | struct wlr_output_layout *layout = root->sway_root->output_layout; | 173 | } |
172 | struct wlr_output_layout_output *loutput = | 174 | struct sway_container *root = container_parent(output, C_ROOT); |
173 | wlr_output_layout_get(layout, output->sway_output->wlr_output); | 175 | if (!sway_assert(root, "output must be within tree to set position")) { |
174 | if (!sway_assert(loutput, "output must be within layout to set position")) { | 176 | return; |
175 | return; | 177 | } |
178 | struct wlr_output_layout *layout = root->sway_root->output_layout; | ||
179 | struct wlr_output_layout_output *loutput = | ||
180 | wlr_output_layout_get(layout, output->sway_output->wlr_output); | ||
181 | if (!sway_assert(loutput, | ||
182 | "output must be within layout to set position")) { | ||
183 | return; | ||
184 | } | ||
185 | lx = x + loutput->x; | ||
186 | ly = y + loutput->y; | ||
176 | } | 187 | } |
177 | 188 | ||
178 | xwayland_view->pending_width = width; | 189 | xwayland_view->pending_width = width; |
179 | xwayland_view->pending_height = height; | 190 | xwayland_view->pending_height = height; |
180 | wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, | 191 | wlr_xwayland_surface_configure(xsurface, lx, ly, width, height); |
181 | width, height); | ||
182 | } | 192 | } |
183 | 193 | ||
184 | static void set_activated(struct sway_view *view, bool activated) { | 194 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -189,6 +199,14 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
189 | wlr_xwayland_surface_activate(surface, activated); | 199 | wlr_xwayland_surface_activate(surface, activated); |
190 | } | 200 | } |
191 | 201 | ||
202 | static void set_maximized(struct sway_view *view, bool maximized) { | ||
203 | if (xwayland_view_from_view(view) == NULL) { | ||
204 | return; | ||
205 | } | ||
206 | struct wlr_xwayland_surface *surface = view->wlr_xwayland_surface; | ||
207 | wlr_xwayland_surface_set_maximized(surface, maximized); | ||
208 | } | ||
209 | |||
192 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { | 210 | static void set_fullscreen(struct sway_view *view, bool fullscreen) { |
193 | if (xwayland_view_from_view(view) == NULL) { | 211 | if (xwayland_view_from_view(view) == NULL) { |
194 | return; | 212 | return; |
@@ -197,6 +215,35 @@ static void set_fullscreen(struct sway_view *view, bool fullscreen) { | |||
197 | wlr_xwayland_surface_set_fullscreen(surface, fullscreen); | 215 | wlr_xwayland_surface_set_fullscreen(surface, fullscreen); |
198 | } | 216 | } |
199 | 217 | ||
218 | static bool wants_floating(struct sway_view *view) { | ||
219 | // TODO: | ||
220 | // We want to return true if the window type contains any of these: | ||
221 | // NET_WM_WINDOW_TYPE_DIALOG | ||
222 | // NET_WM_WINDOW_TYPE_UTILITY | ||
223 | // NET_WM_WINDOW_TYPE_TOOLBAR | ||
224 | // NET_WM_WINDOW_TYPE_SPLASH | ||
225 | // | ||
226 | // We also want to return true if the NET_WM_STATE is MODAL. | ||
227 | // wlroots doesn't appear to provide all this information at the moment. | ||
228 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
229 | uint32_t *atom = xsurface->window_type; | ||
230 | for (size_t i = 0; i < xsurface->window_type_len; ++i) { | ||
231 | wlr_log(L_DEBUG, "xwayland window type %i", *atom); | ||
232 | // TODO: Come up with a better way of doing this | ||
233 | switch (*atom) { | ||
234 | case 36: // NET_WM_WINDOW_TYPE_UTILITY | ||
235 | case 44: // NET_WM_WINDOW_TYPE_SPLASH | ||
236 | case 276: // ? PGP passphrase dialog | ||
237 | case 337: // ? Firefox open file dialog | ||
238 | case 338: // ? Firefox open file dialog | ||
239 | return true; | ||
240 | } | ||
241 | ++atom; | ||
242 | } | ||
243 | |||
244 | return false; | ||
245 | } | ||
246 | |||
200 | static void _close(struct sway_view *view) { | 247 | static void _close(struct sway_view *view) { |
201 | if (xwayland_view_from_view(view) == NULL) { | 248 | if (xwayland_view_from_view(view) == NULL) { |
202 | return; | 249 | return; |
@@ -225,7 +272,9 @@ static const struct sway_view_impl view_impl = { | |||
225 | .get_int_prop = get_int_prop, | 272 | .get_int_prop = get_int_prop, |
226 | .configure = configure, | 273 | .configure = configure, |
227 | .set_activated = set_activated, | 274 | .set_activated = set_activated, |
275 | .set_maximized = set_maximized, | ||
228 | .set_fullscreen = set_fullscreen, | 276 | .set_fullscreen = set_fullscreen, |
277 | .wants_floating = wants_floating, | ||
229 | .close = _close, | 278 | .close = _close, |
230 | .destroy = destroy, | 279 | .destroy = destroy, |
231 | }; | 280 | }; |
@@ -234,10 +283,18 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
234 | struct sway_xwayland_view *xwayland_view = | 283 | struct sway_xwayland_view *xwayland_view = |
235 | wl_container_of(listener, xwayland_view, commit); | 284 | wl_container_of(listener, xwayland_view, commit); |
236 | struct sway_view *view = &xwayland_view->view; | 285 | struct sway_view *view = &xwayland_view->view; |
237 | // NOTE: We intentionally discard the view's desired width here | 286 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
238 | // TODO: Let floating views do whatever | 287 | if (!view->natural_width && !view->natural_height) { |
239 | view_update_size(view, xwayland_view->pending_width, | 288 | view->natural_width = xsurface->width; |
240 | xwayland_view->pending_height); | 289 | view->natural_height = xsurface->height; |
290 | } | ||
291 | if (view->swayc && view->swayc->is_floating) { | ||
292 | view_update_size(view, xsurface->width, xsurface->height); | ||
293 | view_update_position(view, xsurface->x, xsurface->y); | ||
294 | } else { | ||
295 | view_update_size(view, xwayland_view->pending_width, | ||
296 | xwayland_view->pending_height); | ||
297 | } | ||
241 | view_damage_from(view); | 298 | view_damage_from(view); |
242 | } | 299 | } |
243 | 300 | ||