diff options
author | Tony Crisci <tony@dubstepdish.com> | 2018-04-02 19:22:10 -0400 |
---|---|---|
committer | Tony Crisci <tony@dubstepdish.com> | 2018-04-02 19:22:10 -0400 |
commit | a89096278b3dee599d75b7e91810a354b90a0ecb (patch) | |
tree | 69bb7208e42acab112048192f3a93557c6658186 | |
parent | Merge branch 'wlroots' into split-containers (diff) | |
parent | Merge pull request #1691 from emersion/view-redesign (diff) | |
download | sway-a89096278b3dee599d75b7e91810a354b90a0ecb.tar.gz sway-a89096278b3dee599d75b7e91810a354b90a0ecb.tar.zst sway-a89096278b3dee599d75b7e91810a354b90a0ecb.zip |
Merge branch 'wlroots' into split-containers
-rw-r--r-- | include/sway/output.h | 1 | ||||
-rw-r--r-- | include/sway/tree/container.h | 5 | ||||
-rw-r--r-- | include/sway/tree/layout.h | 2 | ||||
-rw-r--r-- | include/sway/tree/view.h | 59 | ||||
-rw-r--r-- | protocols/desktop-shell.xml | 138 | ||||
-rw-r--r-- | protocols/gamma-control.xml | 57 | ||||
-rw-r--r-- | protocols/server-decoration.xml | 94 | ||||
-rw-r--r-- | protocols/swaylock.xml | 18 | ||||
-rw-r--r-- | protocols/xdg-shell.xml | 430 | ||||
-rw-r--r-- | sway/desktop/output.c | 87 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 61 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 67 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 136 | ||||
-rw-r--r-- | sway/input/cursor.c | 11 | ||||
-rw-r--r-- | sway/tree/layout.c | 11 | ||||
-rw-r--r-- | sway/tree/output.c | 1 | ||||
-rw-r--r-- | sway/tree/view.c | 188 |
17 files changed, 356 insertions, 1010 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index b343ecff..98d0f83f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -24,6 +24,7 @@ struct sway_output { | |||
24 | struct wl_listener destroy; | 24 | struct wl_listener destroy; |
25 | struct wl_listener mode; | 25 | struct wl_listener mode; |
26 | struct wl_listener transform; | 26 | struct wl_listener transform; |
27 | struct wl_listener scale; | ||
27 | 28 | ||
28 | struct wl_listener damage_destroy; | 29 | struct wl_listener damage_destroy; |
29 | struct wl_listener damage_frame; | 30 | struct wl_listener damage_frame; |
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index fa22ea75..464f80c4 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h | |||
@@ -70,9 +70,10 @@ struct sway_container { | |||
70 | enum sway_container_layout prev_layout; | 70 | enum sway_container_layout prev_layout; |
71 | enum sway_container_layout workspace_layout; | 71 | enum sway_container_layout workspace_layout; |
72 | 72 | ||
73 | // TODO convert to layout coordinates | 73 | // For C_ROOT, this has no meaning |
74 | // For C_OUTPUT, this is the output position in layout coordinates | ||
75 | // For other types, this is the position in output-local coordinates | ||
74 | double x, y; | 76 | double x, y; |
75 | |||
76 | // does not include borders or gaps. | 77 | // does not include borders or gaps. |
77 | double width, height; | 78 | double width, height; |
78 | 79 | ||
diff --git a/include/sway/tree/layout.h b/include/sway/tree/layout.h index fbc3d6af..8badb244 100644 --- a/include/sway/tree/layout.h +++ b/include/sway/tree/layout.h | |||
@@ -20,7 +20,7 @@ struct sway_root { | |||
20 | 20 | ||
21 | struct wl_listener output_layout_change; | 21 | struct wl_listener output_layout_change; |
22 | 22 | ||
23 | struct wl_list unmanaged_views; // sway_view::unmanaged_view_link | 23 | struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link |
24 | 24 | ||
25 | struct { | 25 | struct { |
26 | struct wl_signal new_container; | 26 | struct wl_signal new_container; |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 3965d2b7..4b84205e 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <wlr/types/wlr_surface.h> | 4 | #include <wlr/types/wlr_surface.h> |
5 | #include <wlr/types/wlr_xdg_shell_v6.h> | 5 | #include <wlr/types/wlr_xdg_shell_v6.h> |
6 | #include <wlr/xwayland.h> | 6 | #include <wlr/xwayland.h> |
7 | #include "sway/input/input-manager.h" | ||
8 | #include "sway/input/seat.h" | ||
7 | 9 | ||
8 | struct sway_container; | 10 | struct sway_container; |
9 | struct sway_view; | 11 | struct sway_view; |
@@ -37,6 +39,13 @@ struct sway_xwayland_surface { | |||
37 | int pending_width, pending_height; | 39 | int pending_width, pending_height; |
38 | }; | 40 | }; |
39 | 41 | ||
42 | struct sway_xwayland_unmanaged { | ||
43 | struct wlr_xwayland_surface *wlr_xwayland_surface; | ||
44 | struct wl_list link; | ||
45 | |||
46 | struct wl_listener destroy; | ||
47 | }; | ||
48 | |||
40 | struct sway_wl_shell_surface { | 49 | struct sway_wl_shell_surface { |
41 | struct sway_view *view; | 50 | struct sway_view *view; |
42 | 51 | ||
@@ -64,10 +73,21 @@ enum sway_view_prop { | |||
64 | VIEW_PROP_INSTANCE, | 73 | VIEW_PROP_INSTANCE, |
65 | }; | 74 | }; |
66 | 75 | ||
76 | struct sway_view_impl { | ||
77 | const char *(*get_prop)(struct sway_view *view, | ||
78 | enum sway_view_prop prop); | ||
79 | void (*configure)(struct sway_view *view, double ox, double oy, int width, | ||
80 | int height); | ||
81 | void (*set_activated)(struct sway_view *view, bool activated); | ||
82 | void (*close)(struct sway_view *view); | ||
83 | }; | ||
84 | |||
67 | struct sway_view { | 85 | struct sway_view { |
68 | enum sway_view_type type; | 86 | enum sway_view_type type; |
69 | struct sway_container *swayc; | 87 | const struct sway_view_impl *impl; |
70 | struct wlr_surface *surface; | 88 | |
89 | struct sway_container *swayc; // NULL for unmanaged views | ||
90 | struct wlr_surface *surface; // NULL for unmapped views | ||
71 | int width, height; | 91 | int width, height; |
72 | 92 | ||
73 | union { | 93 | union { |
@@ -82,21 +102,15 @@ struct sway_view { | |||
82 | struct sway_wl_shell_surface *sway_wl_shell_surface; | 102 | struct sway_wl_shell_surface *sway_wl_shell_surface; |
83 | }; | 103 | }; |
84 | 104 | ||
85 | struct { | ||
86 | const char *(*get_prop)(struct sway_view *view, | ||
87 | enum sway_view_prop prop); | ||
88 | void (*set_size)(struct sway_view *view, | ||
89 | int width, int height); | ||
90 | void (*set_position)(struct sway_view *view, | ||
91 | double ox, double oy); | ||
92 | void (*set_activated)(struct sway_view *view, bool activated); | ||
93 | void (*close)(struct sway_view *view); | ||
94 | } iface; | ||
95 | |||
96 | // only used for unmanaged views (shell specific) | 105 | // only used for unmanaged views (shell specific) |
97 | struct wl_list unmanaged_view_link; // sway_root::unmanaged views | 106 | struct wl_list unmanaged_view_link; // sway_root::unmanaged_views |
98 | }; | 107 | }; |
99 | 108 | ||
109 | struct sway_view *view_create(enum sway_view_type type, | ||
110 | const struct sway_view_impl *impl); | ||
111 | |||
112 | void view_destroy(struct sway_view *view); | ||
113 | |||
100 | const char *view_get_title(struct sway_view *view); | 114 | const char *view_get_title(struct sway_view *view); |
101 | 115 | ||
102 | const char *view_get_app_id(struct sway_view *view); | 116 | const char *view_get_app_id(struct sway_view *view); |
@@ -105,18 +119,25 @@ const char *view_get_class(struct sway_view *view); | |||
105 | 119 | ||
106 | const char *view_get_instance(struct sway_view *view); | 120 | const char *view_get_instance(struct sway_view *view); |
107 | 121 | ||
108 | void view_set_size(struct sway_view *view, int width, int height); | 122 | void view_configure(struct sway_view *view, double ox, double oy, int width, |
109 | 123 | int height); | |
110 | void view_set_position(struct sway_view *view, double ox, double oy); | ||
111 | 124 | ||
112 | void view_set_activated(struct sway_view *view, bool activated); | 125 | void view_set_activated(struct sway_view *view, bool activated); |
113 | 126 | ||
114 | void view_close(struct sway_view *view); | 127 | void view_close(struct sway_view *view); |
115 | 128 | ||
116 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before); | ||
117 | |||
118 | void view_damage_whole(struct sway_view *view); | 129 | void view_damage_whole(struct sway_view *view); |
119 | 130 | ||
120 | void view_damage_from(struct sway_view *view); | 131 | void view_damage_from(struct sway_view *view); |
121 | 132 | ||
133 | // view implementation | ||
134 | |||
135 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); | ||
136 | |||
137 | void view_unmap(struct sway_view *view); | ||
138 | |||
139 | void view_update_position(struct sway_view *view, double ox, double oy); | ||
140 | |||
141 | void view_update_size(struct sway_view *view, int width, int height); | ||
142 | |||
122 | #endif | 143 | #endif |
diff --git a/protocols/desktop-shell.xml b/protocols/desktop-shell.xml deleted file mode 100644 index 581f0c5d..00000000 --- a/protocols/desktop-shell.xml +++ /dev/null | |||
@@ -1,138 +0,0 @@ | |||
1 | <protocol name="desktop"> | ||
2 | |||
3 | <interface name="desktop_shell" version="3"> | ||
4 | <description summary="create desktop widgets and helpers"> | ||
5 | Traditional user interfaces can rely on this interface to define the | ||
6 | foundations of typical desktops. Currently it's possible to set up | ||
7 | background, panels and locking surfaces. | ||
8 | </description> | ||
9 | |||
10 | <request name="set_background"> | ||
11 | <arg name="output" type="object" interface="wl_output"/> | ||
12 | <arg name="surface" type="object" interface="wl_surface"/> | ||
13 | </request> | ||
14 | |||
15 | <request name="set_panel"> | ||
16 | <arg name="output" type="object" interface="wl_output"/> | ||
17 | <arg name="surface" type="object" interface="wl_surface"/> | ||
18 | </request> | ||
19 | |||
20 | <request name="set_lock_surface"> | ||
21 | <arg name="surface" type="object" interface="wl_surface"/> | ||
22 | </request> | ||
23 | |||
24 | <request name="unlock"/> | ||
25 | |||
26 | <request name="set_grab_surface"> | ||
27 | <description summary="set grab surface"> | ||
28 | The surface set by this request will receive a fake | ||
29 | pointer.enter event during grabs at position 0, 0 and is | ||
30 | expected to set an appropriate cursor image as described by | ||
31 | the grab_cursor event sent just before the enter event. | ||
32 | </description> | ||
33 | <arg name="surface" type="object" interface="wl_surface"/> | ||
34 | </request> | ||
35 | |||
36 | <!-- We'll fold most of wl_shell into this interface and then | ||
37 | they'll share the configure event. --> | ||
38 | <event name="configure"> | ||
39 | <arg name="edges" type="uint"/> | ||
40 | <arg name="surface" type="object" interface="wl_surface"/> | ||
41 | <arg name="width" type="int"/> | ||
42 | <arg name="height" type="int"/> | ||
43 | </event> | ||
44 | |||
45 | <event name="prepare_lock_surface"> | ||
46 | <description summary="tell the client to create, set the lock surface"> | ||
47 | Tell the client we want it to create and set the lock surface, which is | ||
48 | a GUI asking the user to unlock the screen. The lock surface is | ||
49 | announced with 'set_lock_surface'. Whether or not the client actually | ||
50 | implements locking, it MUST send 'unlock' request to let the normal | ||
51 | desktop resume. | ||
52 | </description> | ||
53 | </event> | ||
54 | |||
55 | <event name="grab_cursor"> | ||
56 | <description summary="tell client what cursor to show during a grab"> | ||
57 | This event will be sent immediately before a fake enter event on the | ||
58 | grab surface. | ||
59 | </description> | ||
60 | <arg name="cursor" type="uint"/> | ||
61 | </event> | ||
62 | |||
63 | <enum name="cursor"> | ||
64 | <entry name="none" value="0"/> | ||
65 | |||
66 | <entry name="resize_top" value="1"/> | ||
67 | <entry name="resize_bottom" value="2"/> | ||
68 | |||
69 | <entry name="arrow" value="3"/> | ||
70 | |||
71 | <entry name="resize_left" value="4"/> | ||
72 | <entry name="resize_top_left" value="5"/> | ||
73 | <entry name="resize_bottom_left" value="6"/> | ||
74 | |||
75 | <entry name="move" value="7"/> | ||
76 | |||
77 | <entry name="resize_right" value="8"/> | ||
78 | <entry name="resize_top_right" value="9"/> | ||
79 | <entry name="resize_bottom_right" value="10"/> | ||
80 | |||
81 | <entry name="busy" value="11"/> | ||
82 | </enum> | ||
83 | |||
84 | <!-- Version 2 additions --> | ||
85 | |||
86 | <request name="desktop_ready" since="2"> | ||
87 | <description summary="desktop is ready to be shown"> | ||
88 | Tell the server, that enough desktop elements have been drawn | ||
89 | to make the desktop look ready for use. During start-up, the | ||
90 | server can wait for this request with a black screen before | ||
91 | starting to fade in the desktop, for instance. If the client | ||
92 | parts of a desktop take a long time to initialize, we avoid | ||
93 | showing temporary garbage. | ||
94 | </description> | ||
95 | </request> | ||
96 | |||
97 | <!-- Version 3 additions --> | ||
98 | |||
99 | <enum name="panel_position"> | ||
100 | <entry name="top" value="0"/> | ||
101 | <entry name="bottom" value="1"/> | ||
102 | <entry name="left" value="2"/> | ||
103 | <entry name="right" value="3"/> | ||
104 | </enum> | ||
105 | |||
106 | <enum name="error"> | ||
107 | <entry name="invalid_argument" value="0" | ||
108 | summary="an invalid argument was provided in a request"/> | ||
109 | </enum> | ||
110 | |||
111 | <request name="set_panel_position" since="3"> | ||
112 | <description summary="set panel position"> | ||
113 | Tell the shell which side of the screen the panel is | ||
114 | located. This is so that new windows do not overlap the panel | ||
115 | and maximized windows maximize properly. | ||
116 | </description> | ||
117 | <arg name="position" type="uint"/> | ||
118 | </request> | ||
119 | |||
120 | </interface> | ||
121 | |||
122 | <interface name="screensaver" version="1"> | ||
123 | <description summary="interface for implementing screensavers"> | ||
124 | Only one client can bind this interface at a time. | ||
125 | </description> | ||
126 | |||
127 | <request name="set_surface"> | ||
128 | <description summary="set the surface type as a screensaver"> | ||
129 | A screensaver surface is normally hidden, and only visible after an | ||
130 | idle timeout. | ||
131 | </description> | ||
132 | |||
133 | <arg name="surface" type="object" interface="wl_surface"/> | ||
134 | <arg name="output" type="object" interface="wl_output"/> | ||
135 | </request> | ||
136 | |||
137 | </interface> | ||
138 | </protocol> | ||
diff --git a/protocols/gamma-control.xml b/protocols/gamma-control.xml deleted file mode 100644 index e6e33265..00000000 --- a/protocols/gamma-control.xml +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <protocol name="gamma_control"> | ||
3 | |||
4 | <copyright> | ||
5 | Copyright © 2015 Giulio camuffo | ||
6 | |||
7 | Permission to use, copy, modify, distribute, and sell this | ||
8 | software and its documentation for any purpose is hereby granted | ||
9 | without fee, provided that the above copyright notice appear in | ||
10 | all copies and that both that copyright notice and this permission | ||
11 | notice appear in supporting documentation, and that the name of | ||
12 | the copyright holders not be used in advertising or publicity | ||
13 | pertaining to distribution of the software without specific, | ||
14 | written prior permission. The copyright holders make no | ||
15 | representations about the suitability of this software for any | ||
16 | purpose. It is provided "as is" without express or implied | ||
17 | warranty. | ||
18 | |||
19 | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | ||
20 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
21 | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
22 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
23 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | ||
24 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
25 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||
26 | THIS SOFTWARE. | ||
27 | </copyright> | ||
28 | |||
29 | <interface name="gamma_control_manager" version="1"> | ||
30 | <request name="destroy" type="destructor"/> | ||
31 | |||
32 | <request name="get_gamma_control"> | ||
33 | <arg name="id" type="new_id" interface="gamma_control"/> | ||
34 | <arg name="output" type="object" interface="wl_output"/> | ||
35 | </request> | ||
36 | </interface> | ||
37 | |||
38 | <interface name="gamma_control" version="1"> | ||
39 | <enum name="error"> | ||
40 | <entry name="invalid_gamma" value="0"/> | ||
41 | </enum> | ||
42 | |||
43 | <request name="destroy" type="destructor"/> | ||
44 | |||
45 | <request name="set_gamma"> | ||
46 | <arg name="red" type="array"/> | ||
47 | <arg name="green" type="array"/> | ||
48 | <arg name="blue" type="array"/> | ||
49 | </request> | ||
50 | |||
51 | <request name="reset_gamma"/> | ||
52 | |||
53 | <event name="gamma_size"> | ||
54 | <arg name="size" type="uint"/> | ||
55 | </event> | ||
56 | </interface> | ||
57 | </protocol> | ||
diff --git a/protocols/server-decoration.xml b/protocols/server-decoration.xml deleted file mode 100644 index 8bc106c7..00000000 --- a/protocols/server-decoration.xml +++ /dev/null | |||
@@ -1,94 +0,0 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <protocol name="server_decoration"> | ||
3 | <copyright><![CDATA[ | ||
4 | Copyright (C) 2015 Martin Gräßlin | ||
5 | |||
6 | This program is free software: you can redistribute it and/or modify | ||
7 | it under the terms of the GNU Lesser General Public License as published by | ||
8 | the Free Software Foundation, either version 2.1 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | This program is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | GNU Lesser General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Lesser General Public License | ||
17 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | ]]></copyright> | ||
19 | <interface name="org_kde_kwin_server_decoration_manager" version="1"> | ||
20 | <description summary="Server side window decoration manager"> | ||
21 | This interface allows to coordinate whether the server should create | ||
22 | a server-side window decoration around a wl_surface representing a | ||
23 | shell surface (wl_shell_surface or similar). By announcing support | ||
24 | for this interface the server indicates that it supports server | ||
25 | side decorations. | ||
26 | </description> | ||
27 | <request name="create"> | ||
28 | <description summary="Create a server-side decoration object for a given surface"> | ||
29 | When a client creates a server-side decoration object it indicates | ||
30 | that it supports the protocol. The client is supposed to tell the | ||
31 | server whether it wants server-side decorations or will provide | ||
32 | client-side decorations. | ||
33 | |||
34 | If the client does not create a server-side decoration object for | ||
35 | a surface the server interprets this as lack of support for this | ||
36 | protocol and considers it as client-side decorated. Nevertheless a | ||
37 | client-side decorated surface should use this protocol to indicate | ||
38 | to the server that it does not want a server-side deco. | ||
39 | </description> | ||
40 | <arg name="id" type="new_id" interface="org_kde_kwin_server_decoration"/> | ||
41 | <arg name="surface" type="object" interface="wl_surface"/> | ||
42 | </request> | ||
43 | <enum name="mode"> | ||
44 | <description summary="Possible values to use in request_mode and the event mode."/> | ||
45 | <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/> | ||
46 | <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/> | ||
47 | <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/> | ||
48 | </enum> | ||
49 | <event name="default_mode"> | ||
50 | <description summary="The default mode used on the server"> | ||
51 | This event is emitted directly after binding the interface. It contains | ||
52 | the default mode for the decoration. When a new server decoration object | ||
53 | is created this new object will be in the default mode until the first | ||
54 | request_mode is requested. | ||
55 | |||
56 | The server may change the default mode at any time. | ||
57 | </description> | ||
58 | <arg name="mode" type="uint" summary="The default decoration mode applied to newly created server decorations."/> | ||
59 | </event> | ||
60 | </interface> | ||
61 | <interface name="org_kde_kwin_server_decoration" version="1"> | ||
62 | <request name="release" type="destructor"> | ||
63 | <description summary="release the server decoration object"/> | ||
64 | </request> | ||
65 | <enum name="mode"> | ||
66 | <description summary="Possible values to use in request_mode and the event mode."/> | ||
67 | <entry name="None" value="0" summary="Undecorated: The surface is not decorated at all, neither server nor client-side. An example is a popup surface which should not be decorated."/> | ||
68 | <entry name="Client" value="1" summary="Client-side decoration: The decoration is part of the surface and the client."/> | ||
69 | <entry name="Server" value="2" summary="Server-side decoration: The server embeds the surface into a decoration frame."/> | ||
70 | </enum> | ||
71 | <request name="request_mode"> | ||
72 | <description summary="The decoration mode the surface wants to use."/> | ||
73 | <arg name="mode" type="uint" summary="The mode this surface wants to use."/> | ||
74 | </request> | ||
75 | <event name="mode"> | ||
76 | <description summary="The new decoration mode applied by the server"> | ||
77 | This event is emitted directly after the decoration is created and | ||
78 | represents the base decoration policy by the server. E.g. a server | ||
79 | which wants all surfaces to be client-side decorated will send Client, | ||
80 | a server which wants server-side decoration will send Server. | ||
81 | |||
82 | The client can request a different mode through the decoration request. | ||
83 | The server will acknowledge this by another event with the same mode. So | ||
84 | even if a server prefers server-side decoration it's possible to force a | ||
85 | client-side decoration. | ||
86 | |||
87 | The server may emit this event at any time. In this case the client can | ||
88 | again request a different mode. It's the responsibility of the server to | ||
89 | prevent a feedback loop. | ||
90 | </description> | ||
91 | <arg name="mode" type="uint" summary="The decoration mode applied to the surface by the server."/> | ||
92 | </event> | ||
93 | </interface> | ||
94 | </protocol> | ||
diff --git a/protocols/swaylock.xml b/protocols/swaylock.xml deleted file mode 100644 index c7a102dd..00000000 --- a/protocols/swaylock.xml +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | <protocol name="lock"> | ||
2 | |||
3 | <interface name="lock" version="1"> | ||
4 | <description summary="create lock screen UIs"> | ||
5 | The Weston desktop-shell protocol's locking functionality depends more | ||
6 | on the behavior of the compositor than of a screen locking client, so | ||
7 | another protocol is necessary. | ||
8 | </description> | ||
9 | |||
10 | <request name="set_lock_surface"> | ||
11 | <arg name="output" type="object" interface="wl_output"/> | ||
12 | <arg name="surface" type="object" interface="wl_surface"/> | ||
13 | </request> | ||
14 | |||
15 | <request name="unlock"/> | ||
16 | |||
17 | </interface> | ||
18 | </protocol> | ||
diff --git a/protocols/xdg-shell.xml b/protocols/xdg-shell.xml deleted file mode 100644 index 7bf4ae3a..00000000 --- a/protocols/xdg-shell.xml +++ /dev/null | |||
@@ -1,430 +0,0 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <protocol name="xdg_shell"> | ||
3 | |||
4 | <copyright> | ||
5 | Copyright © 2008-2013 Kristian Høgsberg | ||
6 | Copyright © 2013 Rafael Antognolli | ||
7 | Copyright © 2013 Jasper St. Pierre | ||
8 | Copyright © 2010-2013 Intel Corporation | ||
9 | |||
10 | Permission to use, copy, modify, distribute, and sell this | ||
11 | software and its documentation for any purpose is hereby granted | ||
12 | without fee, provided that the above copyright notice appear in | ||
13 | all copies and that both that copyright notice and this permission | ||
14 | notice appear in supporting documentation, and that the name of | ||
15 | the copyright holders not be used in advertising or publicity | ||
16 | pertaining to distribution of the software without specific, | ||
17 | written prior permission. The copyright holders make no | ||
18 | representations about the suitability of this software for any | ||
19 | purpose. It is provided "as is" without express or implied | ||
20 | warranty. | ||
21 | |||
22 | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | ||
23 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
24 | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
25 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
26 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | ||
27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
28 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||
29 | THIS SOFTWARE. | ||
30 | </copyright> | ||
31 | |||
32 | <interface name="xdg_shell" version="1"> | ||
33 | <description summary="create desktop-style surfaces"> | ||
34 | This interface is implemented by servers that provide | ||
35 | desktop-style user interfaces. | ||
36 | |||
37 | It allows clients to associate a xdg_surface with | ||
38 | a basic surface. | ||
39 | </description> | ||
40 | |||
41 | <enum name="version"> | ||
42 | <description summary="latest protocol version"> | ||
43 | The 'current' member of this enum gives the version of the | ||
44 | protocol. Implementations can compare this to the version | ||
45 | they implement using static_assert to ensure the protocol and | ||
46 | implementation versions match. | ||
47 | </description> | ||
48 | <entry name="current" value="4" summary="Always the latest version"/> | ||
49 | </enum> | ||
50 | |||
51 | <enum name="error"> | ||
52 | <entry name="role" value="0" summary="given wl_surface has another role"/> | ||
53 | </enum> | ||
54 | |||
55 | <request name="use_unstable_version"> | ||
56 | <description summary="enable use of this unstable version"> | ||
57 | Negotiate the unstable version of the interface. This | ||
58 | mechanism is in place to ensure client and server agree on the | ||
59 | unstable versions of the protocol that they speak or exit | ||
60 | cleanly if they don't agree. This request will go away once | ||
61 | the xdg-shell protocol is stable. | ||
62 | </description> | ||
63 | <arg name="version" type="int"/> | ||
64 | </request> | ||
65 | |||
66 | <request name="get_xdg_surface"> | ||
67 | <description summary="create a shell surface from a surface"> | ||
68 | Create a shell surface for an existing surface. | ||
69 | |||
70 | This request gives the surface the role of xdg_surface. If the | ||
71 | surface already has another role, it raises a protocol error. | ||
72 | |||
73 | Only one shell or popup surface can be associated with a given | ||
74 | surface. | ||
75 | </description> | ||
76 | <arg name="id" type="new_id" interface="xdg_surface"/> | ||
77 | <arg name="surface" type="object" interface="wl_surface"/> | ||
78 | </request> | ||
79 | |||
80 | <request name="get_xdg_popup"> | ||
81 | <description summary="create a shell surface from a surface"> | ||
82 | Create a popup surface for an existing surface. | ||
83 | |||
84 | This request gives the surface the role of xdg_popup. If the | ||
85 | surface already has another role, it raises a protocol error. | ||
86 | |||
87 | Only one shell or popup surface can be associated with a given | ||
88 | surface. | ||
89 | </description> | ||
90 | <arg name="id" type="new_id" interface="xdg_popup"/> | ||
91 | <arg name="surface" type="object" interface="wl_surface"/> | ||
92 | <arg name="parent" type="object" interface="wl_surface"/> | ||
93 | <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> | ||
94 | <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> | ||
95 | <arg name="x" type="int"/> | ||
96 | <arg name="y" type="int"/> | ||
97 | <arg name="flags" type="uint"/> | ||
98 | </request> | ||
99 | |||
100 | <event name="ping"> | ||
101 | <description summary="check if the client is alive"> | ||
102 | The ping event asks the client if it's still alive. Pass the | ||
103 | serial specified in the event back to the compositor by sending | ||
104 | a "pong" request back with the specified serial. | ||
105 | |||
106 | Compositors can use this to determine if the client is still | ||
107 | alive. It's unspecified what will happen if the client doesn't | ||
108 | respond to the ping request, or in what timeframe. Clients should | ||
109 | try to respond in a reasonable amount of time. | ||
110 | </description> | ||
111 | <arg name="serial" type="uint" summary="pass this to the callback"/> | ||
112 | </event> | ||
113 | |||
114 | <request name="pong"> | ||
115 | <description summary="respond to a ping event"> | ||
116 | A client must respond to a ping event with a pong request or | ||
117 | the client may be deemed unresponsive. | ||
118 | </description> | ||
119 | <arg name="serial" type="uint" summary="serial of the ping event"/> | ||
120 | </request> | ||
121 | </interface> | ||
122 | |||
123 | <interface name="xdg_surface" version="1"> | ||
124 | |||
125 | <description summary="desktop-style metadata interface"> | ||
126 | An interface that may be implemented by a wl_surface, for | ||
127 | implementations that provide a desktop-style user interface. | ||
128 | |||
129 | It provides requests to treat surfaces like windows, allowing to set | ||
130 | properties like maximized, fullscreen, minimized, and to move and resize | ||
131 | them, and associate metadata like title and app id. | ||
132 | |||
133 | On the server side the object is automatically destroyed when | ||
134 | the related wl_surface is destroyed. On client side, | ||
135 | xdg_surface.destroy() must be called before destroying | ||
136 | the wl_surface object. | ||
137 | </description> | ||
138 | |||
139 | <request name="destroy" type="destructor"> | ||
140 | <description summary="remove xdg_surface interface"> | ||
141 | The xdg_surface interface is removed from the wl_surface object | ||
142 | that was turned into a xdg_surface with | ||
143 | xdg_shell.get_xdg_surface request. The xdg_surface properties, | ||
144 | like maximized and fullscreen, are lost. The wl_surface loses | ||
145 | its role as a xdg_surface. The wl_surface is unmapped. | ||
146 | </description> | ||
147 | </request> | ||
148 | |||
149 | <request name="set_parent"> | ||
150 | <description summary="surface is a child of another surface"> | ||
151 | Child surfaces are stacked above their parents, and will be | ||
152 | unmapped if the parent is unmapped too. They should not appear | ||
153 | on task bars and alt+tab. | ||
154 | </description> | ||
155 | <arg name="parent" type="object" interface="wl_surface" allow-null="true"/> | ||
156 | </request> | ||
157 | |||
158 | <request name="set_title"> | ||
159 | <description summary="set surface title"> | ||
160 | Set a short title for the surface. | ||
161 | |||
162 | This string may be used to identify the surface in a task bar, | ||
163 | window list, or other user interface elements provided by the | ||
164 | compositor. | ||
165 | |||
166 | The string must be encoded in UTF-8. | ||
167 | </description> | ||
168 | <arg name="title" type="string"/> | ||
169 | </request> | ||
170 | |||
171 | <request name="set_app_id"> | ||
172 | <description summary="set surface class"> | ||
173 | Set an id for the surface. | ||
174 | |||
175 | The app id identifies the general class of applications to which | ||
176 | the surface belongs. | ||
177 | |||
178 | It should be the ID that appears in the new desktop entry | ||
179 | specification, the interface name. | ||
180 | </description> | ||
181 | <arg name="app_id" type="string"/> | ||
182 | </request> | ||
183 | |||
184 | <request name="show_window_menu"> | ||
185 | <description summary="show the window menu"> | ||
186 | Clients implementing client-side decorations might want to show | ||
187 | a context menu when right-clicking on the decorations, giving the | ||
188 | user a menu that they can use to maximize or minimize the window. | ||
189 | |||
190 | This request asks the compositor to pop up such a window menu at | ||
191 | the given position, relative to the parent surface. There are | ||
192 | no guarantees as to what the window menu contains. | ||
193 | |||
194 | Your surface must have focus on the seat passed in to pop up the | ||
195 | window menu. | ||
196 | </description> | ||
197 | |||
198 | <arg name="seat" type="object" interface="wl_seat" summary="the seat to pop the window up on"/> | ||
199 | <arg name="serial" type="uint" summary="serial of the event to pop up the window for"/> | ||
200 | <arg name="x" type="int" summary="the x position to pop up the window menu at"/> | ||
201 | <arg name="y" type="int" summary="the y position to pop up the window menu at"/> | ||
202 | </request> | ||
203 | |||
204 | <request name="move"> | ||
205 | <description summary="start an interactive move"> | ||
206 | Start a pointer-driven move of the surface. | ||
207 | |||
208 | This request must be used in response to a button press event. | ||
209 | The server may ignore move requests depending on the state of | ||
210 | the surface (e.g. fullscreen or maximized). | ||
211 | </description> | ||
212 | <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> | ||
213 | <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> | ||
214 | </request> | ||
215 | |||
216 | <enum name="resize_edge"> | ||
217 | <description summary="edge values for resizing"> | ||
218 | These values are used to indicate which edge of a surface | ||
219 | is being dragged in a resize operation. The server may | ||
220 | use this information to adapt its behavior, e.g. choose | ||
221 | an appropriate cursor image. | ||
222 | </description> | ||
223 | <entry name="none" value="0"/> | ||
224 | <entry name="top" value="1"/> | ||
225 | <entry name="bottom" value="2"/> | ||
226 | <entry name="left" value="4"/> | ||
227 | <entry name="top_left" value="5"/> | ||
228 | <entry name="bottom_left" value="6"/> | ||
229 | <entry name="right" value="8"/> | ||
230 | <entry name="top_right" value="9"/> | ||
231 | <entry name="bottom_right" value="10"/> | ||
232 | </enum> | ||
233 | |||
234 | <request name="resize"> | ||
235 | <description summary="start an interactive resize"> | ||
236 | Start a pointer-driven resizing of the surface. | ||
237 | |||
238 | This request must be used in response to a button press event. | ||
239 | The server may ignore resize requests depending on the state of | ||
240 | the surface (e.g. fullscreen or maximized). | ||
241 | </description> | ||
242 | <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat whose pointer is used"/> | ||
243 | <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> | ||
244 | <arg name="edges" type="uint" summary="which edge or corner is being dragged"/> | ||
245 | </request> | ||
246 | |||
247 | <enum name="state"> | ||
248 | <description summary="types of state on the surface"> | ||
249 | The different state values used on the surface. This is designed for | ||
250 | state values like maximized, fullscreen. It is paired with the | ||
251 | configure event to ensure that both the client and the compositor | ||
252 | setting the state can be synchronized. | ||
253 | |||
254 | States set in this way are double-buffered. They will get applied on | ||
255 | the next commit. | ||
256 | |||
257 | Desktop environments may extend this enum by taking up a range of | ||
258 | values and documenting the range they chose in this description. | ||
259 | They are not required to document the values for the range that they | ||
260 | chose. Ideally, any good extensions from a desktop environment should | ||
261 | make its way into standardization into this enum. | ||
262 | |||
263 | The current reserved ranges are: | ||
264 | |||
265 | 0x0000 - 0x0FFF: xdg-shell core values, documented below. | ||
266 | 0x1000 - 0x1FFF: GNOME | ||
267 | </description> | ||
268 | <entry name="maximized" value="1"> | ||
269 | <description summary="the surface is maximized"> | ||
270 | The surface is maximized. The window geometry specified in the configure | ||
271 | event must be obeyed by the client. | ||
272 | </description> | ||
273 | </entry> | ||
274 | <entry name="fullscreen" value="2"> | ||
275 | <description summary="the surface is fullscreen"> | ||
276 | The surface is fullscreen. The window geometry specified in the configure | ||
277 | event must be obeyed by the client. | ||
278 | </description> | ||
279 | </entry> | ||
280 | <entry name="resizing" value="3"> | ||
281 | <description summary="the surface is being resized"> | ||
282 | The surface is being resized. The window geometry specified in the | ||
283 | configure event is a maximum; the client cannot resize beyond it. | ||
284 | Clients that have aspect ratio or cell sizing configuration can use | ||
285 | a smaller size, however. | ||
286 | </description> | ||
287 | </entry> | ||
288 | <entry name="activated" value="4"> | ||
289 | <description summary="the client window is active"> | ||
290 | Client window decorations should be painted as if the window is | ||
291 | active. Do not assume this means that the window actually has | ||
292 | keyboard or pointer focus. | ||
293 | </description> | ||
294 | </entry> | ||
295 | </enum> | ||
296 | |||
297 | <event name="configure"> | ||
298 | <description summary="suggest a surface change"> | ||
299 | The configure event asks the client to resize its surface. | ||
300 | |||
301 | The width and height arguments specify a hint to the window | ||
302 | about how its surface should be resized in window geometry | ||
303 | coordinates. The states listed in the event specify how the | ||
304 | width/height arguments should be interpreted. | ||
305 | |||
306 | A client should arrange a new surface, and then send a | ||
307 | ack_configure request with the serial sent in this configure | ||
308 | event before attaching a new surface. | ||
309 | |||
310 | If the client receives multiple configure events before it | ||
311 | can respond to one, it is free to discard all but the last | ||
312 | event it received. | ||
313 | </description> | ||
314 | |||
315 | <arg name="width" type="int"/> | ||
316 | <arg name="height" type="int"/> | ||
317 | <arg name="states" type="array"/> | ||
318 | <arg name="serial" type="uint"/> | ||
319 | </event> | ||
320 | |||
321 | <request name="ack_configure"> | ||
322 | <description summary="ack a configure event"> | ||
323 | When a configure event is received, a client should then ack it | ||
324 | using the ack_configure request to ensure that the compositor | ||
325 | knows the client has seen the event. | ||
326 | |||
327 | By this point, the state is confirmed, and the next attach should | ||
328 | contain the buffer drawn for the configure event you are acking. | ||
329 | </description> | ||
330 | <arg name="serial" type="uint" summary="a serial to configure for"/> | ||
331 | </request> | ||
332 | |||
333 | <request name="set_window_geometry"> | ||
334 | <description summary="set the new window geometry"> | ||
335 | The window geometry of a window is its "visible bounds" from the | ||
336 | user's perspective. Client-side decorations often have invisible | ||
337 | portions like drop-shadows which should be ignored for the | ||
338 | purposes of aligning, placing and constraining windows. | ||
339 | |||
340 | The default value is the full bounds of the surface, including any | ||
341 | subsurfaces. Once the window geometry of the surface is set once, | ||
342 | it is not possible to unset it, and it will remain the same until | ||
343 | set_window_geometry is called again, even if a new subsurface or | ||
344 | buffer is attached. | ||
345 | |||
346 | If responding to a configure event, the window geometry in here | ||
347 | must respect the sizing negotiations specified by the states in | ||
348 | the configure event. | ||
349 | </description> | ||
350 | <arg name="x" type="int"/> | ||
351 | <arg name="y" type="int"/> | ||
352 | <arg name="width" type="int"/> | ||
353 | <arg name="height" type="int"/> | ||
354 | </request> | ||
355 | |||
356 | <request name="set_maximized" /> | ||
357 | <request name="unset_maximized" /> | ||
358 | |||
359 | <request name="set_fullscreen"> | ||
360 | <description summary="set the window as fullscreen on a monitor"> | ||
361 | Make the surface fullscreen. | ||
362 | |||
363 | You can specify an output that you would prefer to be fullscreen. | ||
364 | If this value is NULL, it's up to the compositor to choose which | ||
365 | display will be used to map this surface. | ||
366 | </description> | ||
367 | <arg name="output" type="object" interface="wl_output" allow-null="true"/> | ||
368 | </request> | ||
369 | <request name="unset_fullscreen" /> | ||
370 | |||
371 | <request name="set_minimized" /> | ||
372 | |||
373 | <event name="close"> | ||
374 | <description summary="surface wants to be closed"> | ||
375 | The close event is sent by the compositor when the user | ||
376 | wants the surface to be closed. This should be equivalent to | ||
377 | the user clicking the close button in client-side decorations, | ||
378 | if your application has any... | ||
379 | |||
380 | This is only a request that the user intends to close your | ||
381 | window. The client may choose to ignore this request, or show | ||
382 | a dialog to ask the user to save their data... | ||
383 | </description> | ||
384 | </event> | ||
385 | </interface> | ||
386 | |||
387 | <interface name="xdg_popup" version="1"> | ||
388 | <description summary="desktop-style metadata interface"> | ||
389 | An interface that may be implemented by a wl_surface, for | ||
390 | implementations that provide a desktop-style popups/menus. A popup | ||
391 | surface is a transient surface with an added pointer grab. | ||
392 | |||
393 | An existing implicit grab will be changed to owner-events mode, | ||
394 | and the popup grab will continue after the implicit grab ends | ||
395 | (i.e. releasing the mouse button does not cause the popup to be | ||
396 | unmapped). | ||
397 | |||
398 | The popup grab continues until the window is destroyed or a mouse | ||
399 | button is pressed in any other clients window. A click in any of | ||
400 | the clients surfaces is reported as normal, however, clicks in | ||
401 | other clients surfaces will be discarded and trigger the callback. | ||
402 | |||
403 | The x and y arguments specify the locations of the upper left | ||
404 | corner of the surface relative to the upper left corner of the | ||
405 | parent surface, in surface local coordinates. | ||
406 | |||
407 | xdg_popup surfaces are always transient for another surface. | ||
408 | </description> | ||
409 | |||
410 | <request name="destroy" type="destructor"> | ||
411 | <description summary="remove xdg_surface interface"> | ||
412 | The xdg_surface interface is removed from the wl_surface object | ||
413 | that was turned into a xdg_surface with | ||
414 | xdg_shell.get_xdg_surface request. The xdg_surface properties, | ||
415 | like maximized and fullscreen, are lost. The wl_surface loses | ||
416 | its role as a xdg_surface. The wl_surface is unmapped. | ||
417 | </description> | ||
418 | </request> | ||
419 | |||
420 | <event name="popup_done"> | ||
421 | <description summary="popup interaction is done"> | ||
422 | The popup_done event is sent out when a popup grab is broken, | ||
423 | that is, when the users clicks a surface that doesn't belong | ||
424 | to the client owning the popup surface. | ||
425 | </description> | ||
426 | <arg name="serial" type="uint" summary="serial of the implicit grab on the pointer"/> | ||
427 | </event> | ||
428 | |||
429 | </interface> | ||
430 | </protocol> | ||
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 5e8a081c..10ed1f6d 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -39,6 +39,32 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh, | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /** | ||
43 | * Checks whether a surface at (lx, ly) intersects an output. If `box` is not | ||
44 | * NULL, it populates it with the surface box in the output, in output-local | ||
45 | * coordinates. | ||
46 | */ | ||
47 | static bool surface_intersect_output(struct wlr_surface *surface, | ||
48 | struct wlr_output_layout *output_layout, struct wlr_output *wlr_output, | ||
49 | double lx, double ly, float rotation, struct wlr_box *box) { | ||
50 | double ox = lx, oy = ly; | ||
51 | wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); | ||
52 | |||
53 | if (box != NULL) { | ||
54 | box->x = ox * wlr_output->scale; | ||
55 | box->y = oy * wlr_output->scale; | ||
56 | box->width = surface->current->width * wlr_output->scale; | ||
57 | box->height = surface->current->height * wlr_output->scale; | ||
58 | } | ||
59 | |||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx, .y = ly, | ||
62 | .width = surface->current->width, .height = surface->current->height, | ||
63 | }; | ||
64 | wlr_box_rotated_bounds(&layout_box, rotation, &layout_box); | ||
65 | return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box); | ||
66 | } | ||
67 | |||
42 | static void render_surface(struct wlr_surface *surface, | 68 | static void render_surface(struct wlr_surface *surface, |
43 | struct wlr_output *wlr_output, struct timespec *when, | 69 | struct wlr_output *wlr_output, struct timespec *when, |
44 | double lx, double ly, float rotation) { | 70 | double lx, double ly, float rotation) { |
@@ -48,29 +74,21 @@ static void render_surface(struct wlr_surface *surface, | |||
48 | if (!wlr_surface_has_buffer(surface)) { | 74 | if (!wlr_surface_has_buffer(surface)) { |
49 | return; | 75 | return; |
50 | } | 76 | } |
77 | |||
51 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 78 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; |
52 | int width = surface->current->width; | 79 | |
53 | int height = surface->current->height; | 80 | struct wlr_box box; |
54 | int render_width = width * wlr_output->scale; | 81 | bool intersects = surface_intersect_output(surface, layout, wlr_output, |
55 | int render_height = height * wlr_output->scale; | 82 | lx, ly, rotation, &box); |
56 | int owidth, oheight; | 83 | if (intersects) { |
57 | wlr_output_effective_resolution(wlr_output, &owidth, &oheight); | ||
58 | |||
59 | // FIXME: view coords are inconsistently assumed to be in output or layout coords | ||
60 | struct wlr_box layout_box = { | ||
61 | .x = lx + wlr_output->lx, .y = ly + wlr_output->ly, | ||
62 | .width = render_width, .height = render_height, | ||
63 | }; | ||
64 | if (wlr_output_layout_intersects(layout, wlr_output, &layout_box)) { | ||
65 | struct wlr_box render_box = { | ||
66 | .x = lx, .y = ly, | ||
67 | .width = render_width, .height = render_height | ||
68 | }; | ||
69 | float matrix[9]; | 84 | float matrix[9]; |
70 | wlr_matrix_project_box(matrix, &render_box, surface->current->transform, | 85 | enum wl_output_transform transform = |
71 | 0, wlr_output->transform_matrix); | 86 | wlr_output_transform_invert(surface->current->transform); |
72 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, | 87 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
73 | 1.0f); // TODO: configurable alpha | 88 | wlr_output->transform_matrix); |
89 | |||
90 | // TODO: configurable alpha | ||
91 | wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); | ||
74 | 92 | ||
75 | wlr_surface_send_frame_done(surface, when); | 93 | wlr_surface_send_frame_done(surface, when); |
76 | } | 94 | } |
@@ -80,9 +98,8 @@ static void render_surface(struct wlr_surface *surface, | |||
80 | struct wlr_surface_state *state = subsurface->surface->current; | 98 | struct wlr_surface_state *state = subsurface->surface->current; |
81 | double sx = state->subsurface_position.x; | 99 | double sx = state->subsurface_position.x; |
82 | double sy = state->subsurface_position.y; | 100 | double sy = state->subsurface_position.y; |
83 | double sw = state->buffer_width / state->scale; | 101 | rotate_child_position(&sx, &sy, state->width, state->height, |
84 | double sh = state->buffer_height / state->scale; | 102 | surface->current->width, surface->current->height, rotation); |
85 | rotate_child_position(&sx, &sy, sw, sh, width, height, rotation); | ||
86 | 103 | ||
87 | render_surface(subsurface->surface, wlr_output, when, | 104 | render_surface(subsurface->surface, wlr_output, when, |
88 | lx + sx, ly + sy, rotation); | 105 | lx + sx, ly + sy, rotation); |
@@ -243,15 +260,15 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
243 | container_descendants(workspace, C_VIEW, render_view, &rdata); | 260 | container_descendants(workspace, C_VIEW, render_view, &rdata); |
244 | 261 | ||
245 | // render unmanaged views on top | 262 | // render unmanaged views on top |
246 | struct sway_view *view; | 263 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
247 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, | 264 | struct sway_xwayland_unmanaged *sway_surface; |
248 | unmanaged_view_link) { | 265 | wl_list_for_each(sway_surface, unmanaged, link) { |
249 | if (view->type != SWAY_XWAYLAND_VIEW) { | 266 | struct wlr_xwayland_surface *xsurface = |
267 | sway_surface->wlr_xwayland_surface; | ||
268 | if (xsurface->surface == NULL) { | ||
250 | continue; | 269 | continue; |
251 | } | 270 | } |
252 | 271 | ||
253 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
254 | |||
255 | const struct wlr_box view_box = { | 272 | const struct wlr_box view_box = { |
256 | .x = xsurface->x, | 273 | .x = xsurface->x, |
257 | .y = xsurface->y, | 274 | .y = xsurface->y, |
@@ -263,7 +280,7 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
263 | continue; | 280 | continue; |
264 | } | 281 | } |
265 | 282 | ||
266 | render_surface(view->surface, wlr_output, &output->last_frame, | 283 | render_surface(xsurface->surface, wlr_output, &output->last_frame, |
267 | view_box.x - output_box->x, view_box.y - output_box->y, 0); | 284 | view_box.x - output_box->x, view_box.y - output_box->y, 0); |
268 | } | 285 | } |
269 | 286 | ||
@@ -341,6 +358,12 @@ static void handle_transform(struct wl_listener *listener, void *data) { | |||
341 | arrange_windows(output->swayc, -1, -1); | 358 | arrange_windows(output->swayc, -1, -1); |
342 | } | 359 | } |
343 | 360 | ||
361 | static void handle_scale(struct wl_listener *listener, void *data) { | ||
362 | struct sway_output *output = wl_container_of(listener, output, scale); | ||
363 | arrange_layers(output); | ||
364 | arrange_windows(output->swayc, -1, -1); | ||
365 | } | ||
366 | |||
344 | void handle_new_output(struct wl_listener *listener, void *data) { | 367 | void handle_new_output(struct wl_listener *listener, void *data) { |
345 | struct sway_server *server = wl_container_of(listener, server, new_output); | 368 | struct sway_server *server = wl_container_of(listener, server, new_output); |
346 | struct wlr_output *wlr_output = data; | 369 | struct wlr_output *wlr_output = data; |
@@ -381,6 +404,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
381 | output->mode.notify = handle_mode; | 404 | output->mode.notify = handle_mode; |
382 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 405 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
383 | output->transform.notify = handle_transform; | 406 | output->transform.notify = handle_transform; |
407 | wl_signal_add(&wlr_output->events.scale, &output->scale); | ||
408 | output->scale.notify = handle_scale; | ||
384 | 409 | ||
385 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | 410 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); |
386 | output->damage_frame.notify = damage_handle_frame; | 411 | output->damage_frame.notify = damage_handle_frame; |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index c44fcf27..6528a397 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -30,28 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | static void set_size(struct sway_view *view, int width, int height) { | 33 | static void configure(struct sway_view *view, double ox, double oy, int width, |
34 | int height) { | ||
34 | if (!assert_wl_shell(view)) { | 35 | if (!assert_wl_shell(view)) { |
35 | return; | 36 | return; |
36 | } | 37 | } |
38 | view_update_position(view, ox, oy); | ||
37 | view->sway_wl_shell_surface->pending_width = width; | 39 | view->sway_wl_shell_surface->pending_width = width; |
38 | view->sway_wl_shell_surface->pending_height = height; | 40 | view->sway_wl_shell_surface->pending_height = height; |
39 | wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); | 41 | wlr_wl_shell_surface_configure(view->wlr_wl_shell_surface, 0, width, height); |
40 | } | 42 | } |
41 | 43 | ||
42 | static void set_position(struct sway_view *view, double ox, double oy) { | 44 | static void _close(struct sway_view *view) { |
43 | if (!assert_wl_shell(view)) { | ||
44 | return; | ||
45 | } | ||
46 | view->swayc->x = ox; | ||
47 | view->swayc->y = oy; | ||
48 | } | ||
49 | |||
50 | static void set_activated(struct sway_view *view, bool activated) { | ||
51 | // no way to activate wl_shell | ||
52 | } | ||
53 | |||
54 | static void close(struct sway_view *view) { | ||
55 | if (!assert_wl_shell(view)) { | 45 | if (!assert_wl_shell(view)) { |
56 | return; | 46 | return; |
57 | } | 47 | } |
@@ -59,14 +49,20 @@ static void close(struct sway_view *view) { | |||
59 | wl_client_destroy(view->wlr_wl_shell_surface->client); | 49 | wl_client_destroy(view->wlr_wl_shell_surface->client); |
60 | } | 50 | } |
61 | 51 | ||
52 | static const struct sway_view_impl view_impl = { | ||
53 | .get_prop = get_prop, | ||
54 | .configure = configure, | ||
55 | .close = _close, | ||
56 | }; | ||
57 | |||
62 | static void handle_commit(struct wl_listener *listener, void *data) { | 58 | static void handle_commit(struct wl_listener *listener, void *data) { |
63 | struct sway_wl_shell_surface *sway_surface = | 59 | struct sway_wl_shell_surface *sway_surface = |
64 | wl_container_of(listener, sway_surface, commit); | 60 | wl_container_of(listener, sway_surface, commit); |
65 | struct sway_view *view = sway_surface->view; | 61 | struct sway_view *view = sway_surface->view; |
66 | // NOTE: We intentionally discard the view's desired width here | 62 | // NOTE: We intentionally discard the view's desired width here |
67 | // TODO: Let floating views do whatever | 63 | // TODO: Let floating views do whatever |
68 | view->width = sway_surface->pending_width; | 64 | view_update_size(view, sway_surface->pending_width, |
69 | view->height = sway_surface->pending_height; | 65 | sway_surface->pending_height); |
70 | view_damage_from(view); | 66 | view_damage_from(view); |
71 | } | 67 | } |
72 | 68 | ||
@@ -75,15 +71,13 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
75 | wl_container_of(listener, sway_surface, destroy); | 71 | wl_container_of(listener, sway_surface, destroy); |
76 | wl_list_remove(&sway_surface->commit.link); | 72 | wl_list_remove(&sway_surface->commit.link); |
77 | wl_list_remove(&sway_surface->destroy.link); | 73 | wl_list_remove(&sway_surface->destroy.link); |
78 | struct sway_container *parent = container_view_destroy(sway_surface->view->swayc); | 74 | view_destroy(sway_surface->view); |
79 | free(sway_surface->view); | ||
80 | free(sway_surface); | 75 | free(sway_surface); |
81 | arrange_windows(parent, -1, -1); | ||
82 | } | 76 | } |
83 | 77 | ||
84 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | 78 | void handle_wl_shell_surface(struct wl_listener *listener, void *data) { |
85 | struct sway_server *server = wl_container_of( | 79 | struct sway_server *server = wl_container_of(listener, server, |
86 | listener, server, wl_shell_surface); | 80 | wl_shell_surface); |
87 | struct wlr_wl_shell_surface *shell_surface = data; | 81 | struct wlr_wl_shell_surface *shell_surface = data; |
88 | 82 | ||
89 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { | 83 | if (shell_surface->state == WLR_WL_SHELL_SURFACE_STATE_POPUP) { |
@@ -103,20 +97,13 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
103 | return; | 97 | return; |
104 | } | 98 | } |
105 | 99 | ||
106 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 100 | struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl); |
107 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 101 | if (!sway_assert(view, "Failed to allocate view")) { |
108 | return; | 102 | return; |
109 | } | 103 | } |
110 | sway_view->type = SWAY_WL_SHELL_VIEW; | 104 | view->wlr_wl_shell_surface = shell_surface; |
111 | sway_view->iface.get_prop = get_prop; | 105 | view->sway_wl_shell_surface = sway_surface; |
112 | sway_view->iface.set_size = set_size; | 106 | sway_surface->view = view; |
113 | sway_view->iface.set_position = set_position; | ||
114 | sway_view->iface.set_activated = set_activated; | ||
115 | sway_view->iface.close = close; | ||
116 | sway_view->wlr_wl_shell_surface = shell_surface; | ||
117 | sway_view->sway_wl_shell_surface = sway_surface; | ||
118 | sway_view->surface = shell_surface->surface; | ||
119 | sway_surface->view = sway_view; | ||
120 | 107 | ||
121 | // TODO: | 108 | // TODO: |
122 | // - Wire up listeners | 109 | // - Wire up listeners |
@@ -132,11 +119,5 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { | |||
132 | sway_surface->destroy.notify = handle_destroy; | 119 | sway_surface->destroy.notify = handle_destroy; |
133 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); | 120 | wl_signal_add(&shell_surface->events.destroy, &sway_surface->destroy); |
134 | 121 | ||
135 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 122 | view_map(view, shell_surface->surface); |
136 | struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); | ||
137 | struct sway_container *cont = container_view_create(focus, sway_view); | ||
138 | sway_view->swayc = cont; | ||
139 | |||
140 | arrange_windows(cont->parent, -1, -1); | ||
141 | input_manager_set_focus(input_manager, cont); | ||
142 | } | 123 | } |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index cffe83fb..49305b39 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -30,23 +30,18 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | static void set_size(struct sway_view *view, int width, int height) { | 33 | static void configure(struct sway_view *view, double ox, double oy, int width, |
34 | int height) { | ||
34 | if (!assert_xdg(view)) { | 35 | if (!assert_xdg(view)) { |
35 | return; | 36 | return; |
36 | } | 37 | } |
38 | |||
39 | view_update_position(view, ox, oy); | ||
37 | view->sway_xdg_surface_v6->pending_width = width; | 40 | view->sway_xdg_surface_v6->pending_width = width; |
38 | view->sway_xdg_surface_v6->pending_height = height; | 41 | view->sway_xdg_surface_v6->pending_height = height; |
39 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); | 42 | wlr_xdg_toplevel_v6_set_size(view->wlr_xdg_surface_v6, width, height); |
40 | } | 43 | } |
41 | 44 | ||
42 | static void set_position(struct sway_view *view, double ox, double oy) { | ||
43 | if (!assert_xdg(view)) { | ||
44 | return; | ||
45 | } | ||
46 | view->swayc->x = ox; | ||
47 | view->swayc->y = oy; | ||
48 | } | ||
49 | |||
50 | static void set_activated(struct sway_view *view, bool activated) { | 45 | static void set_activated(struct sway_view *view, bool activated) { |
51 | if (!assert_xdg(view)) { | 46 | if (!assert_xdg(view)) { |
52 | return; | 47 | return; |
@@ -57,7 +52,7 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
57 | } | 52 | } |
58 | } | 53 | } |
59 | 54 | ||
60 | static void close(struct sway_view *view) { | 55 | static void _close(struct sway_view *view) { |
61 | if (!assert_xdg(view)) { | 56 | if (!assert_xdg(view)) { |
62 | return; | 57 | return; |
63 | } | 58 | } |
@@ -67,6 +62,13 @@ static void close(struct sway_view *view) { | |||
67 | } | 62 | } |
68 | } | 63 | } |
69 | 64 | ||
65 | static const struct sway_view_impl view_impl = { | ||
66 | .get_prop = get_prop, | ||
67 | .configure = configure, | ||
68 | .set_activated = set_activated, | ||
69 | .close = _close, | ||
70 | }; | ||
71 | |||
70 | static void handle_commit(struct wl_listener *listener, void *data) { | 72 | static void handle_commit(struct wl_listener *listener, void *data) { |
71 | struct sway_xdg_surface_v6 *sway_surface = | 73 | struct sway_xdg_surface_v6 *sway_surface = |
72 | wl_container_of(listener, sway_surface, commit); | 74 | wl_container_of(listener, sway_surface, commit); |
@@ -74,37 +76,22 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
74 | // NOTE: We intentionally discard the view's desired width here | 76 | // NOTE: We intentionally discard the view's desired width here |
75 | // TODO: Store this for restoration when moving to floating plane | 77 | // TODO: Store this for restoration when moving to floating plane |
76 | // TODO: Let floating views do whatever | 78 | // TODO: Let floating views do whatever |
77 | view->width = sway_surface->pending_width; | 79 | view_update_size(view, sway_surface->pending_width, |
78 | view->height = sway_surface->pending_height; | 80 | sway_surface->pending_height); |
79 | view_damage_from(view); | 81 | view_damage_from(view); |
80 | } | 82 | } |
81 | 83 | ||
82 | static void handle_unmap(struct wl_listener *listener, void *data) { | 84 | static void handle_unmap(struct wl_listener *listener, void *data) { |
83 | struct sway_xdg_surface_v6 *sway_surface = | 85 | struct sway_xdg_surface_v6 *sway_surface = |
84 | wl_container_of(listener, sway_surface, unmap); | 86 | wl_container_of(listener, sway_surface, unmap); |
85 | view_damage_whole(sway_surface->view); | 87 | view_unmap(sway_surface->view); |
86 | container_view_destroy(sway_surface->view->swayc); | ||
87 | sway_surface->view->swayc = NULL; | ||
88 | sway_surface->view->surface = NULL; | ||
89 | } | 88 | } |
90 | 89 | ||
91 | static void handle_map(struct wl_listener *listener, void *data) { | 90 | static void handle_map(struct wl_listener *listener, void *data) { |
92 | struct sway_xdg_surface_v6 *sway_surface = | 91 | struct sway_xdg_surface_v6 *sway_surface = |
93 | wl_container_of(listener, sway_surface, map); | 92 | wl_container_of(listener, sway_surface, map); |
94 | struct sway_view *view = sway_surface->view; | 93 | struct sway_view *view = sway_surface->view; |
95 | 94 | view_map(view, view->wlr_xdg_surface_v6->surface); | |
96 | sway_surface->view->surface = view->wlr_xdg_surface_v6->surface; | ||
97 | |||
98 | container_view_destroy(view->swayc); | ||
99 | |||
100 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
101 | struct sway_container *focus = seat_get_focus_inactive(seat, &root_container); | ||
102 | struct sway_container *cont = container_view_create(focus, view); | ||
103 | view->swayc = cont; | ||
104 | arrange_windows(cont->parent, -1, -1); | ||
105 | input_manager_set_focus(input_manager, cont); | ||
106 | |||
107 | view_damage_whole(sway_surface->view); | ||
108 | } | 95 | } |
109 | 96 | ||
110 | static void handle_destroy(struct wl_listener *listener, void *data) { | 97 | static void handle_destroy(struct wl_listener *listener, void *data) { |
@@ -112,8 +99,9 @@ static void handle_destroy(struct wl_listener *listener, void *data) { | |||
112 | wl_container_of(listener, sway_xdg_surface, destroy); | 99 | wl_container_of(listener, sway_xdg_surface, destroy); |
113 | wl_list_remove(&sway_xdg_surface->commit.link); | 100 | wl_list_remove(&sway_xdg_surface->commit.link); |
114 | wl_list_remove(&sway_xdg_surface->destroy.link); | 101 | wl_list_remove(&sway_xdg_surface->destroy.link); |
115 | container_view_destroy(sway_xdg_surface->view->swayc); | 102 | wl_list_remove(&sway_xdg_surface->map.link); |
116 | free(sway_xdg_surface->view); | 103 | wl_list_remove(&sway_xdg_surface->unmap.link); |
104 | view_destroy(sway_xdg_surface->view); | ||
117 | free(sway_xdg_surface); | 105 | free(sway_xdg_surface); |
118 | } | 106 | } |
119 | 107 | ||
@@ -138,23 +126,16 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { | |||
138 | return; | 126 | return; |
139 | } | 127 | } |
140 | 128 | ||
141 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 129 | struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl); |
142 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 130 | if (!sway_assert(view, "Failed to allocate view")) { |
143 | return; | 131 | return; |
144 | } | 132 | } |
145 | sway_view->type = SWAY_XDG_SHELL_V6_VIEW; | 133 | view->wlr_xdg_surface_v6 = xdg_surface; |
146 | sway_view->iface.get_prop = get_prop; | 134 | view->sway_xdg_surface_v6 = sway_surface; |
147 | sway_view->iface.set_size = set_size; | 135 | sway_surface->view = view; |
148 | sway_view->iface.set_position = set_position; | ||
149 | sway_view->iface.set_activated = set_activated; | ||
150 | sway_view->iface.close = close; | ||
151 | sway_view->wlr_xdg_surface_v6 = xdg_surface; | ||
152 | sway_view->sway_xdg_surface_v6 = sway_surface; | ||
153 | sway_surface->view = sway_view; | ||
154 | 136 | ||
155 | // TODO: | 137 | // TODO: |
156 | // - Look up pid and open on appropriate workspace | 138 | // - Look up pid and open on appropriate workspace |
157 | // - Set new view to maximized so it behaves nicely | ||
158 | // - Criteria | 139 | // - Criteria |
159 | 140 | ||
160 | sway_surface->commit.notify = handle_commit; | 141 | sway_surface->commit.notify = handle_commit; |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index 17f827d9..bfef68cf 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -14,6 +14,33 @@ | |||
14 | #include "sway/input/input-manager.h" | 14 | #include "sway/input/input-manager.h" |
15 | #include "log.h" | 15 | #include "log.h" |
16 | 16 | ||
17 | static void unmanaged_handle_destroy(struct wl_listener *listener, void *data) { | ||
18 | struct sway_xwayland_unmanaged *sway_surface = | ||
19 | wl_container_of(listener, sway_surface, destroy); | ||
20 | wl_list_remove(&sway_surface->destroy.link); | ||
21 | wl_list_remove(&sway_surface->link); | ||
22 | free(sway_surface); | ||
23 | } | ||
24 | |||
25 | static void create_unmanaged(struct wlr_xwayland_surface *xsurface) { | ||
26 | struct sway_xwayland_unmanaged *sway_surface = | ||
27 | calloc(1, sizeof(struct sway_xwayland_unmanaged)); | ||
28 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { | ||
29 | return; | ||
30 | } | ||
31 | |||
32 | sway_surface->wlr_xwayland_surface = xsurface; | ||
33 | |||
34 | wl_signal_add(&xsurface->events.destroy, &sway_surface->destroy); | ||
35 | sway_surface->destroy.notify = unmanaged_handle_destroy; | ||
36 | |||
37 | wl_list_insert(&root_container.sway_root->xwayland_unmanaged, | ||
38 | &sway_surface->link); | ||
39 | |||
40 | // TODO: damage tracking | ||
41 | } | ||
42 | |||
43 | |||
17 | static bool assert_xwayland(struct sway_view *view) { | 44 | static bool assert_xwayland(struct sway_view *view) { |
18 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, | 45 | return sway_assert(view->type == SWAY_XWAYLAND_VIEW, |
19 | "Expected xwayland view!"); | 46 | "Expected xwayland view!"); |
@@ -33,22 +60,13 @@ static const char *get_prop(struct sway_view *view, enum sway_view_prop prop) { | |||
33 | } | 60 | } |
34 | } | 61 | } |
35 | 62 | ||
36 | static void set_size(struct sway_view *view, int width, int height) { | 63 | static void configure(struct sway_view *view, double ox, double oy, int width, |
64 | int height) { | ||
37 | if (!assert_xwayland(view)) { | 65 | if (!assert_xwayland(view)) { |
38 | return; | 66 | return; |
39 | } | 67 | } |
40 | view->sway_xwayland_surface->pending_width = width; | ||
41 | view->sway_xwayland_surface->pending_height = height; | ||
42 | |||
43 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | 68 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; |
44 | wlr_xwayland_surface_configure(xsurface, xsurface->x, xsurface->y, | ||
45 | width, height); | ||
46 | } | ||
47 | 69 | ||
48 | static void set_position(struct sway_view *view, double ox, double oy) { | ||
49 | if (!assert_xwayland(view)) { | ||
50 | return; | ||
51 | } | ||
52 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | 70 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); |
53 | if (!sway_assert(output, "view must be within tree to set position")) { | 71 | if (!sway_assert(output, "view must be within tree to set position")) { |
54 | return; | 72 | return; |
@@ -64,13 +82,12 @@ static void set_position(struct sway_view *view, double ox, double oy) { | |||
64 | return; | 82 | return; |
65 | } | 83 | } |
66 | 84 | ||
67 | view->swayc->x = ox; | 85 | view_update_position(view, ox, oy); |
68 | view->swayc->y = oy; | ||
69 | 86 | ||
70 | wlr_xwayland_surface_configure(view->wlr_xwayland_surface, | 87 | view->sway_xwayland_surface->pending_width = width; |
71 | ox + loutput->x, oy + loutput->y, | 88 | view->sway_xwayland_surface->pending_height = height; |
72 | view->wlr_xwayland_surface->width, | 89 | wlr_xwayland_surface_configure(xsurface, ox + loutput->x, oy + loutput->y, |
73 | view->wlr_xwayland_surface->height); | 90 | width, height); |
74 | } | 91 | } |
75 | 92 | ||
76 | static void set_activated(struct sway_view *view, bool activated) { | 93 | static void set_activated(struct sway_view *view, bool activated) { |
@@ -81,77 +98,58 @@ static void set_activated(struct sway_view *view, bool activated) { | |||
81 | wlr_xwayland_surface_activate(surface, activated); | 98 | wlr_xwayland_surface_activate(surface, activated); |
82 | } | 99 | } |
83 | 100 | ||
84 | static void close_view(struct sway_view *view) { | 101 | static void _close(struct sway_view *view) { |
85 | if (!assert_xwayland(view)) { | 102 | if (!assert_xwayland(view)) { |
86 | return; | 103 | return; |
87 | } | 104 | } |
88 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); | 105 | wlr_xwayland_surface_close(view->wlr_xwayland_surface); |
89 | } | 106 | } |
90 | 107 | ||
108 | static const struct sway_view_impl view_impl = { | ||
109 | .get_prop = get_prop, | ||
110 | .configure = configure, | ||
111 | .set_activated = set_activated, | ||
112 | .close = _close, | ||
113 | }; | ||
114 | |||
91 | static void handle_commit(struct wl_listener *listener, void *data) { | 115 | static void handle_commit(struct wl_listener *listener, void *data) { |
92 | struct sway_xwayland_surface *sway_surface = | 116 | struct sway_xwayland_surface *sway_surface = |
93 | wl_container_of(listener, sway_surface, commit); | 117 | wl_container_of(listener, sway_surface, commit); |
94 | struct sway_view *view = sway_surface->view; | 118 | struct sway_view *view = sway_surface->view; |
95 | // NOTE: We intentionally discard the view's desired width here | 119 | // NOTE: We intentionally discard the view's desired width here |
96 | // TODO: Let floating views do whatever | 120 | // TODO: Let floating views do whatever |
97 | view->width = sway_surface->pending_width; | 121 | view_update_size(view, sway_surface->pending_width, |
98 | view->height = sway_surface->pending_height; | 122 | sway_surface->pending_height); |
99 | view_damage_from(view); | 123 | view_damage_from(view); |
100 | } | 124 | } |
101 | 125 | ||
102 | static void handle_destroy(struct wl_listener *listener, void *data) { | 126 | static void handle_destroy(struct wl_listener *listener, void *data) { |
103 | struct sway_xwayland_surface *sway_surface = | 127 | struct sway_xwayland_surface *sway_surface = |
104 | wl_container_of(listener, sway_surface, destroy); | 128 | wl_container_of(listener, sway_surface, destroy); |
105 | |||
106 | wl_list_remove(&sway_surface->commit.link); | 129 | wl_list_remove(&sway_surface->commit.link); |
107 | wl_list_remove(&sway_surface->destroy.link); | 130 | wl_list_remove(&sway_surface->destroy.link); |
108 | wl_list_remove(&sway_surface->request_configure.link); | 131 | wl_list_remove(&sway_surface->request_configure.link); |
109 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | 132 | wl_list_remove(&sway_surface->map.link); |
110 | container_view_destroy(sway_surface->view->swayc); | 133 | wl_list_remove(&sway_surface->unmap.link); |
111 | sway_surface->view->swayc = NULL; | 134 | view_destroy(sway_surface->view); |
112 | sway_surface->view->surface = NULL; | 135 | free(sway_surface); |
113 | } | 136 | } |
114 | 137 | ||
115 | static void handle_unmap(struct wl_listener *listener, void *data) { | 138 | static void handle_unmap(struct wl_listener *listener, void *data) { |
116 | struct sway_xwayland_surface *sway_surface = | 139 | struct sway_xwayland_surface *sway_surface = |
117 | wl_container_of(listener, sway_surface, unmap); | 140 | wl_container_of(listener, sway_surface, unmap); |
118 | view_damage_whole(sway_surface->view); | 141 | view_unmap(sway_surface->view); |
119 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
120 | wl_list_init(&sway_surface->view->unmanaged_view_link); | ||
121 | container_view_destroy(sway_surface->view->swayc); | ||
122 | sway_surface->view->swayc = NULL; | ||
123 | sway_surface->view->surface = NULL; | ||
124 | } | 142 | } |
125 | 143 | ||
126 | static void handle_map(struct wl_listener *listener, void *data) { | 144 | static void handle_map(struct wl_listener *listener, void *data) { |
127 | struct sway_xwayland_surface *sway_surface = | 145 | struct sway_xwayland_surface *sway_surface = |
128 | wl_container_of(listener, sway_surface, map); | 146 | wl_container_of(listener, sway_surface, map); |
129 | struct wlr_xwayland_surface *xsurface = data; | 147 | struct wlr_xwayland_surface *xsurface = data; |
130 | 148 | struct sway_view *view = sway_surface->view; | |
131 | sway_surface->view->surface = xsurface->surface; | ||
132 | 149 | ||
133 | // put it back into the tree | 150 | // put it back into the tree |
134 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | 151 | wlr_xwayland_surface_set_maximized(xsurface, true); |
135 | xsurface->override_redirect) { | 152 | view_map(view, xsurface->surface); |
136 | wl_list_remove(&sway_surface->view->unmanaged_view_link); | ||
137 | wl_list_insert(&root_container.sway_root->unmanaged_views, | ||
138 | &sway_surface->view->unmanaged_view_link); | ||
139 | } else { | ||
140 | struct sway_view *view = sway_surface->view; | ||
141 | container_view_destroy(view->swayc); | ||
142 | |||
143 | wlr_xwayland_surface_set_maximized(xsurface, true); | ||
144 | |||
145 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
146 | struct sway_container *focus = seat_get_focus_inactive(seat, | ||
147 | &root_container); | ||
148 | struct sway_container *cont = container_view_create(focus, view); | ||
149 | view->swayc = cont; | ||
150 | arrange_windows(cont->parent, -1, -1); | ||
151 | input_manager_set_focus(input_manager, cont); | ||
152 | } | ||
153 | |||
154 | view_damage_whole(sway_surface->view); | ||
155 | } | 153 | } |
156 | 154 | ||
157 | static void handle_request_configure(struct wl_listener *listener, void *data) { | 155 | static void handle_request_configure(struct wl_listener *listener, void *data) { |
@@ -171,34 +169,32 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | |||
171 | listener, server, xwayland_surface); | 169 | listener, server, xwayland_surface); |
172 | struct wlr_xwayland_surface *xsurface = data; | 170 | struct wlr_xwayland_surface *xsurface = data; |
173 | 171 | ||
172 | if (wlr_xwayland_surface_is_unmanaged(xsurface) || | ||
173 | xsurface->override_redirect) { | ||
174 | wlr_log(L_DEBUG, "New xwayland unmanaged surface"); | ||
175 | create_unmanaged(xsurface); | ||
176 | return; | ||
177 | } | ||
178 | |||
174 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", | 179 | wlr_log(L_DEBUG, "New xwayland surface title='%s' class='%s'", |
175 | xsurface->title, xsurface->class); | 180 | xsurface->title, xsurface->class); |
176 | 181 | ||
177 | struct sway_xwayland_surface *sway_surface = | 182 | struct sway_xwayland_surface *sway_surface = |
178 | calloc(1, sizeof(struct sway_xwayland_surface)); | 183 | calloc(1, sizeof(struct sway_xwayland_surface)); |
179 | if (!sway_assert(sway_surface, "Failed to allocate surface!")) { | 184 | if (!sway_assert(sway_surface, "Failed to allocate surface")) { |
180 | return; | 185 | return; |
181 | } | 186 | } |
182 | 187 | ||
183 | struct sway_view *sway_view = calloc(1, sizeof(struct sway_view)); | 188 | struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); |
184 | if (!sway_assert(sway_view, "Failed to allocate view!")) { | 189 | if (!sway_assert(view, "Failed to allocate view")) { |
185 | return; | 190 | return; |
186 | } | 191 | } |
187 | sway_view->type = SWAY_XWAYLAND_VIEW; | 192 | view->wlr_xwayland_surface = xsurface; |
188 | sway_view->iface.get_prop = get_prop; | 193 | view->sway_xwayland_surface = sway_surface; |
189 | sway_view->iface.set_size = set_size; | 194 | sway_surface->view = view; |
190 | sway_view->iface.set_position = set_position; | ||
191 | sway_view->iface.set_activated = set_activated; | ||
192 | sway_view->iface.close = close_view; | ||
193 | sway_view->wlr_xwayland_surface = xsurface; | ||
194 | sway_view->sway_xwayland_surface = sway_surface; | ||
195 | sway_surface->view = sway_view; | ||
196 | |||
197 | wl_list_init(&sway_view->unmanaged_view_link); | ||
198 | 195 | ||
199 | // TODO: | 196 | // TODO: |
200 | // - Look up pid and open on appropriate workspace | 197 | // - Look up pid and open on appropriate workspace |
201 | // - Set new view to maximized so it behaves nicely | ||
202 | // - Criteria | 198 | // - Criteria |
203 | 199 | ||
204 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); | 200 | wl_signal_add(&xsurface->surface->events.commit, &sway_surface->commit); |
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 7d05e942..97b4473c 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -47,14 +47,15 @@ static struct wlr_surface *layer_surface_at(struct sway_output *output, | |||
47 | static struct sway_container *container_at_cursor(struct sway_cursor *cursor, | 47 | static struct sway_container *container_at_cursor(struct sway_cursor *cursor, |
48 | struct wlr_surface **surface, double *sx, double *sy) { | 48 | struct wlr_surface **surface, double *sx, double *sy) { |
49 | // check for unmanaged views first | 49 | // check for unmanaged views first |
50 | struct wl_list *unmanaged = &root_container.sway_root->unmanaged_views; | 50 | struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged; |
51 | struct sway_view *view; | 51 | struct sway_xwayland_unmanaged *sway_surface; |
52 | wl_list_for_each_reverse(view, unmanaged, unmanaged_view_link) { | 52 | wl_list_for_each_reverse(sway_surface, unmanaged, link) { |
53 | if (view->type != SWAY_XWAYLAND_VIEW) { | 53 | struct wlr_xwayland_surface *xsurface = |
54 | sway_surface->wlr_xwayland_surface; | ||
55 | if (xsurface->surface == NULL) { | ||
54 | continue; | 56 | continue; |
55 | } | 57 | } |
56 | 58 | ||
57 | struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface; | ||
58 | struct wlr_box box = { | 59 | struct wlr_box box = { |
59 | .x = xsurface->x, | 60 | .x = xsurface->x, |
60 | .y = xsurface->y, | 61 | .y = xsurface->y, |
diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 88463e3b..95a84d12 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c | |||
@@ -58,7 +58,7 @@ void layout_init(void) { | |||
58 | 58 | ||
59 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); | 59 | root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); |
60 | root_container.sway_root->output_layout = wlr_output_layout_create(); | 60 | root_container.sway_root->output_layout = wlr_output_layout_create(); |
61 | wl_list_init(&root_container.sway_root->unmanaged_views); | 61 | wl_list_init(&root_container.sway_root->xwayland_unmanaged); |
62 | wl_signal_init(&root_container.sway_root->events.new_container); | 62 | wl_signal_init(&root_container.sway_root->events.new_container); |
63 | 63 | ||
64 | root_container.sway_root->output_layout_change.notify = | 64 | root_container.sway_root->output_layout_change.notify = |
@@ -288,7 +288,7 @@ void arrange_windows(struct sway_container *container, | |||
288 | { | 288 | { |
289 | container->width = width; | 289 | container->width = width; |
290 | container->height = height; | 290 | container->height = height; |
291 | view_set_size(container->sway_view, | 291 | view_configure(container->sway_view, container->x, container->y, |
292 | container->width, container->height); | 292 | container->width, container->height); |
293 | wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", | 293 | wlr_log(L_DEBUG, "Set view to %.f x %.f @ %.f, %.f", |
294 | container->width, container->height, | 294 | container->width, container->height, |
@@ -349,8 +349,10 @@ static void apply_horiz_layout(struct sway_container *container, | |||
349 | wlr_log(L_DEBUG, | 349 | wlr_log(L_DEBUG, |
350 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 350 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
351 | child, child->type, width, scale); | 351 | child, child->type, width, scale); |
352 | |||
352 | if (child->type == C_VIEW) { | 353 | if (child->type == C_VIEW) { |
353 | view_set_position(child->sway_view, child_x, y); | 354 | view_configure(child->sway_view, child_x, y, child->width, |
355 | child->height); | ||
354 | } else { | 356 | } else { |
355 | child->x = child_x; | 357 | child->x = child_x; |
356 | child->y = y; | 358 | child->y = y; |
@@ -406,7 +408,8 @@ void apply_vert_layout(struct sway_container *container, | |||
406 | "Calculating arrangement for %p:%d (will scale %f by %f)", | 408 | "Calculating arrangement for %p:%d (will scale %f by %f)", |
407 | child, child->type, height, scale); | 409 | child, child->type, height, scale); |
408 | if (child->type == C_VIEW) { | 410 | if (child->type == C_VIEW) { |
409 | view_set_position(child->sway_view, x, child_y); | 411 | view_configure(child->sway_view, x, child_y, child->width, |
412 | child->height); | ||
410 | } else { | 413 | } else { |
411 | child->x = x; | 414 | child->x = x; |
412 | child->y = child_y; | 415 | child->y = child_y; |
diff --git a/sway/tree/output.c b/sway/tree/output.c index 2331dc2b..0509db23 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c | |||
@@ -30,6 +30,7 @@ struct sway_container *container_output_destroy(struct sway_container *output) { | |||
30 | wl_list_remove(&output->sway_output->destroy.link); | 30 | wl_list_remove(&output->sway_output->destroy.link); |
31 | wl_list_remove(&output->sway_output->mode.link); | 31 | wl_list_remove(&output->sway_output->mode.link); |
32 | wl_list_remove(&output->sway_output->transform.link); | 32 | wl_list_remove(&output->sway_output->transform.link); |
33 | wl_list_remove(&output->sway_output->scale.link); | ||
33 | 34 | ||
34 | wl_list_remove(&output->sway_output->damage_destroy.link); | 35 | wl_list_remove(&output->sway_output->damage_destroy.link); |
35 | wl_list_remove(&output->sway_output->damage_frame.link); | 36 | wl_list_remove(&output->sway_output->damage_frame.link); |
diff --git a/sway/tree/view.c b/sway/tree/view.c index b7d1a41b..09c804e4 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <stdlib.h> | ||
1 | #include <wayland-server.h> | 2 | #include <wayland-server.h> |
2 | #include <wlr/types/wlr_output_layout.h> | 3 | #include <wlr/types/wlr_output_layout.h> |
3 | #include "log.h" | 4 | #include "log.h" |
@@ -6,82 +7,117 @@ | |||
6 | #include "sway/tree/layout.h" | 7 | #include "sway/tree/layout.h" |
7 | #include "sway/tree/view.h" | 8 | #include "sway/tree/view.h" |
8 | 9 | ||
10 | struct sway_view *view_create(enum sway_view_type type, | ||
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; | ||
17 | view->impl = impl; | ||
18 | return view; | ||
19 | } | ||
20 | |||
21 | void view_destroy(struct sway_view *view) { | ||
22 | if (view == NULL) { | ||
23 | return; | ||
24 | } | ||
25 | |||
26 | if (view->surface != NULL) { | ||
27 | view_unmap(view); | ||
28 | } | ||
29 | |||
30 | container_view_destroy(view->swayc); | ||
31 | free(view); | ||
32 | } | ||
33 | |||
9 | const char *view_get_title(struct sway_view *view) { | 34 | const char *view_get_title(struct sway_view *view) { |
10 | if (view->iface.get_prop) { | 35 | if (view->impl->get_prop) { |
11 | return view->iface.get_prop(view, VIEW_PROP_TITLE); | 36 | return view->impl->get_prop(view, VIEW_PROP_TITLE); |
12 | } | 37 | } |
13 | return NULL; | 38 | return NULL; |
14 | } | 39 | } |
15 | 40 | ||
16 | const char *view_get_app_id(struct sway_view *view) { | 41 | const char *view_get_app_id(struct sway_view *view) { |
17 | if (view->iface.get_prop) { | 42 | if (view->impl->get_prop) { |
18 | return view->iface.get_prop(view, VIEW_PROP_APP_ID); | 43 | return view->impl->get_prop(view, VIEW_PROP_APP_ID); |
19 | } | 44 | } |
20 | return NULL; | 45 | return NULL; |
21 | } | 46 | } |
22 | 47 | ||
23 | const char *view_get_class(struct sway_view *view) { | 48 | const char *view_get_class(struct sway_view *view) { |
24 | if (view->iface.get_prop) { | 49 | if (view->impl->get_prop) { |
25 | return view->iface.get_prop(view, VIEW_PROP_CLASS); | 50 | return view->impl->get_prop(view, VIEW_PROP_CLASS); |
26 | } | 51 | } |
27 | return NULL; | 52 | return NULL; |
28 | } | 53 | } |
29 | 54 | ||
30 | const char *view_get_instance(struct sway_view *view) { | 55 | const char *view_get_instance(struct sway_view *view) { |
31 | if (view->iface.get_prop) { | 56 | if (view->impl->get_prop) { |
32 | return view->iface.get_prop(view, VIEW_PROP_INSTANCE); | 57 | return view->impl->get_prop(view, VIEW_PROP_INSTANCE); |
33 | } | 58 | } |
34 | return NULL; | 59 | return NULL; |
35 | } | 60 | } |
36 | 61 | ||
37 | void view_set_size(struct sway_view *view, int width, int height) { | 62 | void view_configure(struct sway_view *view, double ox, double oy, int width, |
38 | if (view->iface.set_size) { | 63 | int height) { |
39 | struct wlr_box box = { | 64 | if (view->impl->configure) { |
40 | .x = view->swayc->x, | 65 | view->impl->configure(view, ox, oy, width, height); |
41 | .y = view->swayc->y, | ||
42 | .width = view->width, | ||
43 | .height = view->height, | ||
44 | }; | ||
45 | view->iface.set_size(view, width, height); | ||
46 | view_update_outputs(view, &box); | ||
47 | } | 66 | } |
48 | } | 67 | } |
49 | 68 | ||
50 | // TODO make view coordinates in layout coordinates | 69 | void view_set_activated(struct sway_view *view, bool activated) { |
51 | void view_set_position(struct sway_view *view, double ox, double oy) { | 70 | if (view->impl->set_activated) { |
52 | if (view->iface.set_position) { | 71 | view->impl->set_activated(view, activated); |
53 | struct wlr_box box = { | ||
54 | .x = view->swayc->x, | ||
55 | .y = view->swayc->y, | ||
56 | .width = view->width, | ||
57 | .height = view->height, | ||
58 | }; | ||
59 | view->iface.set_position(view, ox, oy); | ||
60 | view_update_outputs(view, &box); | ||
61 | } | 72 | } |
62 | } | 73 | } |
63 | 74 | ||
64 | void view_set_activated(struct sway_view *view, bool activated) { | 75 | void view_close(struct sway_view *view) { |
65 | if (view->iface.set_activated) { | 76 | if (view->impl->close) { |
66 | view->iface.set_activated(view, activated); | 77 | view->impl->close(view); |
67 | } | 78 | } |
68 | } | 79 | } |
69 | 80 | ||
70 | void view_close(struct sway_view *view) { | 81 | struct sway_container *container_view_destroy(struct sway_container *view) { |
71 | if (view->iface.close) { | 82 | if (!view) { |
72 | view->iface.close(view); | 83 | return NULL; |
73 | } | 84 | } |
85 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | ||
86 | struct sway_container *parent = container_destroy(view); | ||
87 | arrange_windows(parent, -1, -1); | ||
88 | return parent; | ||
89 | } | ||
90 | |||
91 | void view_damage_whole(struct sway_view *view) { | ||
92 | for (int i = 0; i < root_container.children->length; ++i) { | ||
93 | struct sway_container *cont = root_container.children->items[i]; | ||
94 | if (cont->type == C_OUTPUT) { | ||
95 | output_damage_whole_view(cont->sway_output, view); | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | void view_damage_from(struct sway_view *view) { | ||
101 | // TODO | ||
102 | view_damage_whole(view); | ||
103 | } | ||
104 | |||
105 | static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { | ||
106 | struct sway_container *output = container_parent(view->swayc, C_OUTPUT); | ||
107 | |||
108 | box->x = output->x + view->swayc->x; | ||
109 | box->y = output->y + view->swayc->y; | ||
110 | box->width = view->width; | ||
111 | box->height = view->height; | ||
74 | } | 112 | } |
75 | 113 | ||
76 | void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | 114 | static void view_update_outputs(struct sway_view *view, |
115 | const struct wlr_box *before) { | ||
116 | struct wlr_box box; | ||
117 | view_get_layout_box(view, &box); | ||
118 | |||
77 | struct wlr_output_layout *output_layout = | 119 | struct wlr_output_layout *output_layout = |
78 | root_container.sway_root->output_layout; | 120 | root_container.sway_root->output_layout; |
79 | struct wlr_box box = { | ||
80 | .x = view->swayc->x, | ||
81 | .y = view->swayc->y, | ||
82 | .width = view->width, | ||
83 | .height = view->height, | ||
84 | }; | ||
85 | struct wlr_output_layout_output *layout_output; | 121 | struct wlr_output_layout_output *layout_output; |
86 | wl_list_for_each(layout_output, &output_layout->outputs, link) { | 122 | wl_list_for_each(layout_output, &output_layout->outputs, link) { |
87 | bool intersected = before != NULL && wlr_output_layout_intersects( | 123 | bool intersected = before != NULL && wlr_output_layout_intersects( |
@@ -97,27 +133,63 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) { | |||
97 | } | 133 | } |
98 | } | 134 | } |
99 | 135 | ||
100 | struct sway_container *container_view_destroy(struct sway_container *view) { | 136 | void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { |
101 | if (!view) { | 137 | if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { |
102 | return NULL; | 138 | return; |
103 | } | 139 | } |
104 | wlr_log(L_DEBUG, "Destroying view '%s'", view->name); | 140 | |
105 | struct sway_container *parent = container_destroy(view); | 141 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
106 | arrange_windows(parent, -1, -1); | 142 | struct sway_container *focus = seat_get_focus_inactive(seat, |
107 | return parent; | 143 | &root_container); |
144 | struct sway_container *cont = container_view_create(focus, view); | ||
145 | |||
146 | view->surface = wlr_surface; | ||
147 | view->swayc = cont; | ||
148 | |||
149 | arrange_windows(cont->parent, -1, -1); | ||
150 | input_manager_set_focus(input_manager, cont); | ||
151 | |||
152 | view_damage_whole(view); | ||
153 | view_update_outputs(view, NULL); | ||
108 | } | 154 | } |
109 | 155 | ||
110 | void view_damage_whole(struct sway_view *view) { | 156 | void view_unmap(struct sway_view *view) { |
111 | struct sway_container *cont = NULL; | 157 | if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { |
112 | for (int i = 0; i < root_container.children->length; ++i) { | 158 | return; |
113 | cont = root_container.children->items[i]; | ||
114 | if (cont->type == C_OUTPUT) { | ||
115 | output_damage_whole_view(cont->sway_output, view); | ||
116 | } | ||
117 | } | 159 | } |
160 | |||
161 | view_damage_whole(view); | ||
162 | |||
163 | container_view_destroy(view->swayc); | ||
164 | |||
165 | view->swayc = NULL; | ||
166 | view->surface = NULL; | ||
118 | } | 167 | } |
119 | 168 | ||
120 | void view_damage_from(struct sway_view *view) { | 169 | void view_update_position(struct sway_view *view, double ox, double oy) { |
121 | // TODO | 170 | if (view->swayc->x == ox && view->swayc->y == oy) { |
171 | return; | ||
172 | } | ||
173 | |||
174 | struct wlr_box box; | ||
175 | view_get_layout_box(view, &box); | ||
176 | view_damage_whole(view); | ||
177 | view->swayc->x = ox; | ||
178 | view->swayc->y = oy; | ||
179 | view_update_outputs(view, &box); | ||
180 | view_damage_whole(view); | ||
181 | } | ||
182 | |||
183 | void view_update_size(struct sway_view *view, int width, int height) { | ||
184 | if (view->width == width && view->height == height) { | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | struct wlr_box box; | ||
189 | view_get_layout_box(view, &box); | ||
190 | view_damage_whole(view); | ||
191 | view->width = width; | ||
192 | view->height = height; | ||
193 | view_update_outputs(view, &box); | ||
122 | view_damage_whole(view); | 194 | view_damage_whole(view); |
123 | } | 195 | } |