aboutsummaryrefslogtreecommitdiffstats
path: root/sway
diff options
context:
space:
mode:
authorLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-04 22:36:09 -0400
committerLibravatar Tony Crisci <tony@dubstepdish.com>2018-04-04 22:36:09 -0400
commit65f254f3fbc83d006d4ec29170ec8a8695345d6c (patch)
tree3044fb62120ca23499d31275076af50db09a9850 /sway
parentfix focus child (diff)
parentMerge pull request #1732 from emersion/view-children (diff)
downloadsway-65f254f3fbc83d006d4ec29170ec8a8695345d6c.tar.gz
sway-65f254f3fbc83d006d4ec29170ec8a8695345d6c.tar.zst
sway-65f254f3fbc83d006d4ec29170ec8a8695345d6c.zip
Merge branch 'wlroots' into fix-focus-inactive
Diffstat (limited to 'sway')
-rw-r--r--sway/commands.c1
-rw-r--r--sway/commands/opacity.c39
-rw-r--r--sway/desktop/output.c41
-rw-r--r--sway/desktop/wl_shell.c4
-rw-r--r--sway/desktop/xdg_shell_v6.c4
-rw-r--r--sway/desktop/xwayland.c4
-rw-r--r--sway/input/cursor.c6
-rw-r--r--sway/input/input-manager.c35
-rw-r--r--sway/input/seat.c75
-rw-r--r--sway/meson.build1
-rw-r--r--sway/sway.5.txt4
-rw-r--r--sway/tree/container.c70
12 files changed, 208 insertions, 76 deletions
diff --git a/sway/commands.c b/sway/commands.c
index 8156a08e..2786a879 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -163,6 +163,7 @@ static struct cmd_handler command_handlers[] = {
163 { "kill", cmd_kill }, 163 { "kill", cmd_kill },
164 { "layout", cmd_layout }, 164 { "layout", cmd_layout },
165 { "move", cmd_move }, 165 { "move", cmd_move },
166 { "opacity", cmd_opacity },
166 { "reload", cmd_reload }, 167 { "reload", cmd_reload },
167 { "split", cmd_split }, 168 { "split", cmd_split },
168 { "splith", cmd_splith }, 169 { "splith", cmd_splith },
diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c
new file mode 100644
index 00000000..b8cd1f09
--- /dev/null
+++ b/sway/commands/opacity.c
@@ -0,0 +1,39 @@
1#include <assert.h>
2#include <stdlib.h>
3#include "sway/commands.h"
4#include "sway/tree/view.h"
5#include "log.h"
6
7static bool parse_opacity(const char *opacity, float *val) {
8 char *err;
9 *val = strtof(opacity, &err);
10 if (*val < 0 || *val > 1 || *err) {
11 return false;
12 }
13 return true;
14}
15
16struct cmd_results *cmd_opacity(int argc, char **argv) {
17 struct cmd_results *error = NULL;
18 if ((error = checkarg(argc, "layout", EXPECTED_EQUAL_TO, 1))) {
19 return error;
20 }
21
22 struct sway_container *con =
23 config->handler_context.current_container;
24
25 float opacity = 0.0f;
26
27 if (!parse_opacity(argv[0], &opacity)) {
28 return cmd_results_new(CMD_INVALID, "opacity <value>",
29 "Invalid value (expected 0..1): %s", argv[0]);
30 }
31
32 con->alpha = opacity;
33
34 if (con->type == C_VIEW) {
35 view_damage_whole(con->sway_view);
36 }
37
38 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
39}
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 8a4fb4a2..0e8a9485 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -75,7 +75,7 @@ static bool surface_intersect_output(struct wlr_surface *surface,
75 75
76static void render_surface(struct wlr_surface *surface, 76static void render_surface(struct wlr_surface *surface,
77 struct wlr_output *wlr_output, struct timespec *when, 77 struct wlr_output *wlr_output, struct timespec *when,
78 double ox, double oy, float rotation) { 78 double ox, double oy, float rotation, float alpha) {
79 struct wlr_renderer *renderer = 79 struct wlr_renderer *renderer =
80 wlr_backend_get_renderer(wlr_output->backend); 80 wlr_backend_get_renderer(wlr_output->backend);
81 81
@@ -95,8 +95,8 @@ static void render_surface(struct wlr_surface *surface,
95 wlr_matrix_project_box(matrix, &box, transform, rotation, 95 wlr_matrix_project_box(matrix, &box, transform, rotation,
96 wlr_output->transform_matrix); 96 wlr_output->transform_matrix);
97 97
98 // TODO: configurable alpha 98 wlr_render_texture_with_matrix(renderer, surface->texture,
99 wlr_render_texture_with_matrix(renderer, surface->texture, matrix, 1.0f); 99 matrix, alpha);
100 100
101 wlr_surface_send_frame_done(surface, when); 101 wlr_surface_send_frame_done(surface, when);
102 } 102 }
@@ -110,13 +110,13 @@ static void render_surface(struct wlr_surface *surface,
110 surface->current->width, surface->current->height, rotation); 110 surface->current->width, surface->current->height, rotation);
111 111
112 render_surface(subsurface->surface, wlr_output, when, 112 render_surface(subsurface->surface, wlr_output, when,
113 ox + sx, oy + sy, rotation); 113 ox + sx, oy + sy, rotation, alpha);
114 } 114 }
115} 115}
116 116
117static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface, 117static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface,
118 struct wlr_output *wlr_output, struct timespec *when, double base_x, 118 struct wlr_output *wlr_output, struct timespec *when, double base_x,
119 double base_y, float rotation) { 119 double base_y, float rotation, float alpha) {
120 double width = surface->surface->current->width; 120 double width = surface->surface->current->width;
121 double height = surface->surface->current->height; 121 double height = surface->surface->current->height;
122 122
@@ -136,19 +136,19 @@ static void render_xdg_v6_popups(struct wlr_xdg_surface_v6 *surface,
136 width, height, rotation); 136 width, height, rotation);
137 137
138 render_surface(popup->surface, wlr_output, when, 138 render_surface(popup->surface, wlr_output, when,
139 base_x + popup_sx, base_y + popup_sy, rotation); 139 base_x + popup_sx, base_y + popup_sy, rotation, alpha);
140 render_xdg_v6_popups(popup, wlr_output, when, 140 render_xdg_v6_popups(popup, wlr_output, when,
141 base_x + popup_sx, base_y + popup_sy, rotation); 141 base_x + popup_sx, base_y + popup_sy, rotation, alpha);
142 } 142 }
143} 143}
144 144
145static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, 145static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
146 struct wlr_output *wlr_output, struct timespec *when, 146 struct wlr_output *wlr_output, struct timespec *when,
147 double lx, double ly, float rotation, 147 double lx, double ly, float rotation, float alpha,
148 bool is_child) { 148 bool is_child) {
149 if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) { 149 if (is_child || surface->state != WLR_WL_SHELL_SURFACE_STATE_POPUP) {
150 render_surface(surface->surface, wlr_output, when, 150 render_surface(surface->surface, wlr_output, when,
151 lx, ly, rotation); 151 lx, ly, rotation, alpha);
152 152
153 double width = surface->surface->current->width; 153 double width = surface->surface->current->width;
154 double height = surface->surface->current->height; 154 double height = surface->surface->current->height;
@@ -164,7 +164,7 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface,
164 width, height, rotation); 164 width, height, rotation);
165 165
166 render_wl_shell_surface(popup, wlr_output, when, 166 render_wl_shell_surface(popup, wlr_output, when,
167 lx + popup_x, ly + popup_y, rotation, true); 167 lx + popup_x, ly + popup_y, rotation, alpha, true);
168 } 168 }
169 } 169 }
170} 170}
@@ -181,29 +181,28 @@ static void render_view(struct sway_container *view, void *data) {
181 struct wlr_output *wlr_output = output->wlr_output; 181 struct wlr_output *wlr_output = output->wlr_output;
182 struct sway_view *sway_view = view->sway_view; 182 struct sway_view *sway_view = view->sway_view;
183 struct wlr_surface *surface = sway_view->surface; 183 struct wlr_surface *surface = sway_view->surface;
184 float alpha = sway_view->swayc->alpha;
184 185
185 if (!surface) { 186 if (!surface) {
186 return; 187 return;
187 } 188 }
188 189
189 switch (sway_view->type) { 190 switch (sway_view->type) {
190 case SWAY_XDG_SHELL_V6_VIEW: { 191 case SWAY_VIEW_XDG_SHELL_V6: {
191 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; 192 int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x;
192 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; 193 int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y;
193 render_surface(surface, wlr_output, when, 194 render_surface(surface, wlr_output, when,
194 view->x - window_offset_x, view->y - window_offset_y, 0); 195 view->x - window_offset_x, view->y - window_offset_y, 0, alpha);
195 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, 196 render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output,
196 when, view->x - window_offset_x, view->y - window_offset_y, 0); 197 when, view->x - window_offset_x, view->y - window_offset_y, 0, alpha);
197 break; 198 break;
198 } 199 }
199 case SWAY_WL_SHELL_VIEW: 200 case SWAY_VIEW_WL_SHELL:
200 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, 201 render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output,
201 when, view->x, view->y, 0, false); 202 when, view->x, view->y, 0, alpha, false);
202 break; 203 break;
203 case SWAY_XWAYLAND_VIEW: 204 case SWAY_VIEW_XWAYLAND:
204 render_surface(surface, wlr_output, when, view->x, view->y, 0); 205 render_surface(surface, wlr_output, when, view->x, view->y, 0, alpha);
205 break;
206 default:
207 break; 206 break;
208 } 207 }
209} 208}
@@ -214,7 +213,7 @@ static void render_layer(struct sway_output *output, struct timespec *when,
214 wl_list_for_each(sway_layer, layer, link) { 213 wl_list_for_each(sway_layer, layer, link) {
215 struct wlr_layer_surface *layer = sway_layer->layer_surface; 214 struct wlr_layer_surface *layer = sway_layer->layer_surface;
216 render_surface(layer->surface, output->wlr_output, when, 215 render_surface(layer->surface, output->wlr_output, when,
217 sway_layer->geo.x, sway_layer->geo.y, 0); 216 sway_layer->geo.x, sway_layer->geo.y, 0, 1.0f);
218 wlr_surface_send_frame_done(layer->surface, when); 217 wlr_surface_send_frame_done(layer->surface, when);
219 } 218 }
220} 219}
@@ -288,7 +287,7 @@ static void render_output(struct sway_output *output, struct timespec *when,
288 } 287 }
289 288
290 render_surface(xsurface->surface, wlr_output, &output->last_frame, 289 render_surface(xsurface->surface, wlr_output, &output->last_frame,
291 view_box.x - output_box->x, view_box.y - output_box->y, 0); 290 view_box.x - output_box->x, view_box.y - output_box->y, 0, 1.0f);
292 } 291 }
293 292
294 // TODO: Consider revising this when fullscreen windows are supported 293 // TODO: Consider revising this when fullscreen windows are supported
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c
index 6528a397..a470674d 100644
--- a/sway/desktop/wl_shell.c
+++ b/sway/desktop/wl_shell.c
@@ -12,7 +12,7 @@
12#include "log.h" 12#include "log.h"
13 13
14static bool assert_wl_shell(struct sway_view *view) { 14static bool assert_wl_shell(struct sway_view *view) {
15 return sway_assert(view->type == SWAY_WL_SHELL_VIEW, 15 return sway_assert(view->type == SWAY_VIEW_WL_SHELL,
16 "Expecting wl_shell view!"); 16 "Expecting wl_shell view!");
17} 17}
18 18
@@ -97,7 +97,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
97 return; 97 return;
98 } 98 }
99 99
100 struct sway_view *view = view_create(SWAY_WL_SHELL_VIEW, &view_impl); 100 struct sway_view *view = view_create(SWAY_VIEW_WL_SHELL, &view_impl);
101 if (!sway_assert(view, "Failed to allocate view")) { 101 if (!sway_assert(view, "Failed to allocate view")) {
102 return; 102 return;
103 } 103 }
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index 49305b39..5cdb8f9f 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -12,7 +12,7 @@
12#include "log.h" 12#include "log.h"
13 13
14static bool assert_xdg(struct sway_view *view) { 14static bool assert_xdg(struct sway_view *view) {
15 return sway_assert(view->type == SWAY_XDG_SHELL_V6_VIEW, 15 return sway_assert(view->type == SWAY_VIEW_XDG_SHELL_V6,
16 "Expected xdg shell v6 view!"); 16 "Expected xdg shell v6 view!");
17} 17}
18 18
@@ -126,7 +126,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
126 return; 126 return;
127 } 127 }
128 128
129 struct sway_view *view = view_create(SWAY_XDG_SHELL_V6_VIEW, &view_impl); 129 struct sway_view *view = view_create(SWAY_VIEW_XDG_SHELL_V6, &view_impl);
130 if (!sway_assert(view, "Failed to allocate view")) { 130 if (!sway_assert(view, "Failed to allocate view")) {
131 return; 131 return;
132 } 132 }
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index bfef68cf..a793928c 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -42,7 +42,7 @@ static void create_unmanaged(struct wlr_xwayland_surface *xsurface) {
42 42
43 43
44static bool assert_xwayland(struct sway_view *view) { 44static bool assert_xwayland(struct sway_view *view) {
45 return sway_assert(view->type == SWAY_XWAYLAND_VIEW, 45 return sway_assert(view->type == SWAY_VIEW_XWAYLAND,
46 "Expected xwayland view!"); 46 "Expected xwayland view!");
47} 47}
48 48
@@ -185,7 +185,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
185 return; 185 return;
186 } 186 }
187 187
188 struct sway_view *view = view_create(SWAY_XWAYLAND_VIEW, &view_impl); 188 struct sway_view *view = view_create(SWAY_VIEW_XWAYLAND, &view_impl);
189 if (!sway_assert(view, "Failed to allocate view")) { 189 if (!sway_assert(view, "Failed to allocate view")) {
190 return; 190 return;
191 } 191 }
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 9229e92d..195ddce9 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -146,8 +146,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
146 146
147 // send pointer enter/leave 147 // send pointer enter/leave
148 if (surface != NULL) { 148 if (surface != NULL) {
149 wlr_seat_pointer_notify_enter(seat, surface, sx, sy); 149 if (seat_is_input_allowed(cursor->seat, surface)) {
150 wlr_seat_pointer_notify_motion(seat, time, sx, sy); 150 wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
151 wlr_seat_pointer_notify_motion(seat, time, sx, sy);
152 }
151 } else { 153 } else {
152 wlr_seat_pointer_clear_focus(seat); 154 wlr_seat_pointer_clear_focus(seat);
153 } 155 }
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index c3507f65..f71a06e4 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -7,6 +7,7 @@
7#include <libinput.h> 7#include <libinput.h>
8#include <math.h> 8#include <math.h>
9#include <wlr/backend/libinput.h> 9#include <wlr/backend/libinput.h>
10#include <wlr/types/wlr_input_inhibitor.h>
10#include "sway/config.h" 11#include "sway/config.h"
11#include "sway/input/input-manager.h" 12#include "sway/input/input-manager.h"
12#include "sway/input/seat.h" 13#include "sway/input/seat.h"
@@ -263,6 +264,32 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
263 input_device->device_destroy.notify = handle_device_destroy; 264 input_device->device_destroy.notify = handle_device_destroy;
264} 265}
265 266
267static void handle_inhibit_activate(struct wl_listener *listener, void *data) {
268 struct sway_input_manager *input_manager = wl_container_of(
269 listener, input_manager, inhibit_activate);
270 struct sway_seat *seat;
271 wl_list_for_each(seat, &input_manager->seats, link) {
272 seat_set_exclusive_client(seat, input_manager->inhibit->active_client);
273 }
274}
275
276static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) {
277 struct sway_input_manager *input_manager = wl_container_of(
278 listener, input_manager, inhibit_deactivate);
279 struct sway_seat *seat;
280 wl_list_for_each(seat, &input_manager->seats, link) {
281 seat_set_exclusive_client(seat, NULL);
282 struct sway_container *previous = seat_get_focus(seat);
283 if (previous) {
284 wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous,
285 container_type_to_str(previous->type), previous->name);
286 // Hack to get seat to re-focus the return value of get_focus
287 seat_set_focus(seat, previous->parent);
288 seat_set_focus(seat, previous);
289 }
290 }
291}
292
266struct sway_input_manager *input_manager_create( 293struct sway_input_manager *input_manager_create(
267 struct sway_server *server) { 294 struct sway_server *server) {
268 struct sway_input_manager *input = 295 struct sway_input_manager *input =
@@ -281,6 +308,14 @@ struct sway_input_manager *input_manager_create(
281 input->new_input.notify = handle_new_input; 308 input->new_input.notify = handle_new_input;
282 wl_signal_add(&server->backend->events.new_input, &input->new_input); 309 wl_signal_add(&server->backend->events.new_input, &input->new_input);
283 310
311 input->inhibit = wlr_input_inhibit_manager_create(server->wl_display);
312 input->inhibit_activate.notify = handle_inhibit_activate;
313 wl_signal_add(&input->inhibit->events.activate,
314 &input->inhibit_activate);
315 input->inhibit_deactivate.notify = handle_inhibit_deactivate;
316 wl_signal_add(&input->inhibit->events.deactivate,
317 &input->inhibit_deactivate);
318
284 return input; 319 return input;
285} 320}
286 321
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 50134aae..e3df6955 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,5 +1,7 @@
1#define _XOPEN_SOURCE 700 1#define _XOPEN_SOURCE 700
2#define _POSIX_C_SOURCE 199309L
2#include <assert.h> 3#include <assert.h>
4#include <time.h>
3#include <wlr/types/wlr_cursor.h> 5#include <wlr/types/wlr_cursor.h>
4#include <wlr/types/wlr_output_layout.h> 6#include <wlr/types/wlr_output_layout.h>
5#include <wlr/types/wlr_xcursor_manager.h> 7#include <wlr/types/wlr_xcursor_manager.h>
@@ -9,6 +11,7 @@
9#include "sway/input/input-manager.h" 11#include "sway/input/input-manager.h"
10#include "sway/input/keyboard.h" 12#include "sway/input/keyboard.h"
11#include "sway/ipc-server.h" 13#include "sway/ipc-server.h"
14#include "sway/layers.h"
12#include "sway/output.h" 15#include "sway/output.h"
13#include "sway/tree/container.h" 16#include "sway/tree/container.h"
14#include "sway/tree/view.h" 17#include "sway/tree/view.h"
@@ -63,7 +66,7 @@ static void seat_send_focus(struct sway_seat *seat,
63 return; 66 return;
64 } 67 }
65 struct sway_view *view = con->sway_view; 68 struct sway_view *view = con->sway_view;
66 if (view->type == SWAY_XWAYLAND_VIEW) { 69 if (view->type == SWAY_VIEW_XWAYLAND) {
67 struct wlr_xwayland *xwayland = 70 struct wlr_xwayland *xwayland =
68 seat->input->server->xwayland; 71 seat->input->server->xwayland;
69 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 72 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
@@ -350,6 +353,12 @@ void seat_configure_xcursor(struct sway_seat *seat) {
350 seat->cursor->cursor->y); 353 seat->cursor->cursor->y);
351} 354}
352 355
356bool seat_is_input_allowed(struct sway_seat *seat,
357 struct wlr_surface *surface) {
358 struct wl_client *client = wl_resource_get_client(surface->resource);
359 return !seat->exclusive_client || seat->exclusive_client == client;
360}
361
353void seat_set_focus_warp(struct sway_seat *seat, 362void seat_set_focus_warp(struct sway_seat *seat,
354 struct sway_container *container, bool warp) { 363 struct sway_container *container, bool warp) {
355 if (seat->focused_layer) { 364 if (seat->focused_layer) {
@@ -371,6 +380,12 @@ void seat_set_focus_warp(struct sway_seat *seat,
371 wl_list_remove(&seat_con->link); 380 wl_list_remove(&seat_con->link);
372 wl_list_insert(&seat->focus_stack, &seat_con->link); 381 wl_list_insert(&seat->focus_stack, &seat_con->link);
373 382
383 if (container->type == C_VIEW && !seat_is_input_allowed(
384 seat, container->sway_view->surface)) {
385 wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited");
386 return;
387 }
388
374 if (container->type == C_VIEW) { 389 if (container->type == C_VIEW) {
375 seat_send_focus(seat, container); 390 seat_send_focus(seat, container);
376 } 391 }
@@ -424,11 +439,18 @@ void seat_set_focus(struct sway_seat *seat,
424 439
425void seat_set_focus_layer(struct sway_seat *seat, 440void seat_set_focus_layer(struct sway_seat *seat,
426 struct wlr_layer_surface *layer) { 441 struct wlr_layer_surface *layer) {
427 if (!layer) { 442 if (!layer && seat->focused_layer) {
428 seat->focused_layer = NULL; 443 seat->focused_layer = NULL;
444 struct sway_container *previous = seat_get_focus(seat);
445 if (previous) {
446 wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous,
447 container_type_to_str(previous->type), previous->name);
448 // Hack to get seat to re-focus the return value of get_focus
449 seat_set_focus(seat, previous->parent);
450 seat_set_focus(seat, previous);
451 }
429 return; 452 return;
430 } 453 } else if (!layer || seat->focused_layer == layer) {
431 if (seat->focused_layer == layer) {
432 return; 454 return;
433 } 455 }
434 if (seat->has_focus) { 456 if (seat->has_focus) {
@@ -453,6 +475,51 @@ void seat_set_focus_layer(struct sway_seat *seat,
453 } 475 }
454} 476}
455 477
478void seat_set_exclusive_client(struct sway_seat *seat,
479 struct wl_client *client) {
480 if (!client) {
481 seat->exclusive_client = client;
482 // Triggers a refocus of the topmost surface layer if necessary
483 // TODO: Make layer surface focus per-output based on cursor position
484 for (int i = 0; i < root_container.children->length; ++i) {
485 struct sway_container *output = root_container.children->items[i];
486 if (!sway_assert(output->type == C_OUTPUT,
487 "root container has non-output child")) {
488 continue;
489 }
490 arrange_layers(output->sway_output);
491 }
492 return;
493 }
494 if (seat->focused_layer) {
495 if (wl_resource_get_client(seat->focused_layer->resource) != client) {
496 seat_set_focus_layer(seat, NULL);
497 }
498 }
499 if (seat->has_focus) {
500 struct sway_container *focus = seat_get_focus(seat);
501 if (focus->type == C_VIEW && wl_resource_get_client(
502 focus->sway_view->surface->resource) != client) {
503 seat_set_focus(seat, NULL);
504 }
505 }
506 if (seat->wlr_seat->pointer_state.focused_client) {
507 if (seat->wlr_seat->pointer_state.focused_client->client != client) {
508 wlr_seat_pointer_clear_focus(seat->wlr_seat);
509 }
510 }
511 struct timespec now;
512 clock_gettime(CLOCK_MONOTONIC, &now);
513 struct wlr_touch_point *point;
514 wl_list_for_each(point, &seat->wlr_seat->touch_state.touch_points, link) {
515 if (point->client->client != client) {
516 wlr_seat_touch_point_clear_focus(seat->wlr_seat,
517 now.tv_nsec / 1000, point->touch_id);
518 }
519 }
520 seat->exclusive_client = client;
521}
522
456struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, 523struct sway_container *seat_get_focus_inactive(struct sway_seat *seat,
457 struct sway_container *container) { 524 struct sway_container *container) {
458 return seat_get_focus_by_type(seat, container, C_TYPES); 525 return seat_get_focus_by_type(seat, container, C_TYPES);
diff --git a/sway/meson.build b/sway/meson.build
index 91aab0a0..f210c195 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -15,6 +15,7 @@ sway_sources = files(
15 'commands/focus.c', 15 'commands/focus.c',
16 'commands/focus_follows_mouse.c', 16 'commands/focus_follows_mouse.c',
17 'commands/kill.c', 17 'commands/kill.c',
18 'commands/opacity.c',
18 'commands/include.c', 19 'commands/include.c',
19 'commands/input.c', 20 'commands/input.c',
20 'commands/layout.c', 21 'commands/layout.c',
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index 900e499a..59c3295a 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -413,6 +413,10 @@ The default colors are:
413 However, any mark that starts with an underscore will not be drawn even if the 413 However, any mark that starts with an underscore will not be drawn even if the
414 option is on. The default option is _on_. 414 option is on. The default option is _on_.
415 415
416**opacity** <value>::
417 Set the opacity of the window between 0 (completely transparent) and 1
418 (completely opaque).
419
416**unmark** <identifier>:: 420**unmark** <identifier>::
417 **Unmark** will remove _identifier_ from the list of current marks on a window. If 421 **Unmark** will remove _identifier_ from the list of current marks on a window. If
418 no _identifier_ is specified, then **unmark** will remove all marks. 422 no _identifier_ is specified, then **unmark** will remove all marks.
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 92c00f83..8fc9e3e8 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -78,6 +78,8 @@ struct sway_container *container_create(enum sway_container_type type) {
78 c->layout = L_NONE; 78 c->layout = L_NONE;
79 c->workspace_layout = L_NONE; 79 c->workspace_layout = L_NONE;
80 c->type = type; 80 c->type = type;
81 c->alpha = 1.0f;
82
81 if (type != C_VIEW) { 83 if (type != C_VIEW) {
82 c->children = create_list(); 84 c->children = create_list();
83 } 85 }
@@ -416,51 +418,33 @@ struct sway_container *container_at(struct sway_container *parent,
416 double view_sx = ox - swayc->x; 418 double view_sx = ox - swayc->x;
417 double view_sy = oy - swayc->y; 419 double view_sy = oy - swayc->y;
418 420
421 double _sx, _sy;
422 struct wlr_surface *_surface;
419 switch (sview->type) { 423 switch (sview->type) {
420 case SWAY_WL_SHELL_VIEW: 424 case SWAY_VIEW_XWAYLAND:
421 break; 425 _surface = wlr_surface_surface_at(sview->surface,
422 case SWAY_XDG_SHELL_V6_VIEW: 426 view_sx, view_sy, &_sx, &_sy);
423 // the top left corner of the sway container is the 427 break;
424 // coordinate of the top left corner of the window geometry 428 case SWAY_VIEW_WL_SHELL:
425 view_sx += sview->wlr_xdg_surface_v6->geometry.x; 429 _surface = wlr_wl_shell_surface_surface_at(
426 view_sy += sview->wlr_xdg_surface_v6->geometry.y; 430 sview->wlr_wl_shell_surface,
427 431 view_sx, view_sy, &_sx, &_sy);
428 // check for popups 432 break;
429 double popup_sx, popup_sy; 433 case SWAY_VIEW_XDG_SHELL_V6:
430 struct wlr_xdg_surface_v6 *popup = 434 // the top left corner of the sway container is the
431 wlr_xdg_surface_v6_popup_at(sview->wlr_xdg_surface_v6, 435 // coordinate of the top left corner of the window geometry
432 view_sx, view_sy, &popup_sx, &popup_sy); 436 view_sx += sview->wlr_xdg_surface_v6->geometry.x;
433 437 view_sy += sview->wlr_xdg_surface_v6->geometry.y;
434 if (popup) { 438
435 *sx = view_sx - popup_sx; 439 _surface = wlr_xdg_surface_v6_surface_at(
436 *sy = view_sy - popup_sy; 440 sview->wlr_xdg_surface_v6,
437 *surface = popup->surface; 441 view_sx, view_sy, &_sx, &_sy);
438 return swayc; 442 break;
439 }
440 break;
441 case SWAY_XWAYLAND_VIEW:
442 break;
443 default:
444 break;
445 }
446
447 // check for subsurfaces
448 double sub_x, sub_y;
449 struct wlr_subsurface *subsurface =
450 wlr_surface_subsurface_at(sview->surface,
451 view_sx, view_sy, &sub_x, &sub_y);
452 if (subsurface) {
453 *sx = view_sx - sub_x;
454 *sy = view_sy - sub_y;
455 *surface = subsurface->surface;
456 return swayc;
457 } 443 }
458 444 if (_surface) {
459 if (wlr_surface_point_accepts_input( 445 *sx = _sx;
460 sview->surface, view_sx, view_sy)) { 446 *sy = _sy;
461 *sx = view_sx; 447 *surface = _surface;
462 *sy = view_sy;
463 *surface = swayc->sway_view->surface;
464 return swayc; 448 return swayc;
465 } 449 }
466 } else { 450 } else {