diff options
-rw-r--r-- | include/sway/output.h | 4 | ||||
-rw-r--r-- | sway/desktop/output.c | 59 | ||||
-rw-r--r-- | swaylock/main.c | 18 |
3 files changed, 80 insertions, 1 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index 19fc5e99..e6fe55c6 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -54,4 +54,8 @@ void output_damage_whole_container(struct sway_output *output, | |||
54 | struct sway_container *output_by_name(const char *name); | 54 | struct sway_container *output_by_name(const char *name); |
55 | 55 | ||
56 | void output_enable(struct sway_output *output); | 56 | void output_enable(struct sway_output *output); |
57 | |||
58 | bool output_has_opaque_lockscreen(struct sway_output *output, | ||
59 | struct sway_seat *seat); | ||
60 | |||
57 | #endif | 61 | #endif |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 1211cc07..e5a42db0 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -915,6 +915,42 @@ static struct sway_container *output_get_active_workspace( | |||
915 | return workspace; | 915 | return workspace; |
916 | } | 916 | } |
917 | 917 | ||
918 | bool output_has_opaque_lockscreen(struct sway_output *output, | ||
919 | struct sway_seat *seat) { | ||
920 | if (!seat->exclusive_client) { | ||
921 | return false; | ||
922 | } | ||
923 | |||
924 | struct wlr_layer_surface *wlr_layer_surface; | ||
925 | wl_list_for_each(wlr_layer_surface, &server.layer_shell->surfaces, link) { | ||
926 | if (wlr_layer_surface->output != output->wlr_output) { | ||
927 | continue; | ||
928 | } | ||
929 | struct wlr_surface *wlr_surface = wlr_layer_surface->surface; | ||
930 | if (wlr_surface->resource->client != seat->exclusive_client) { | ||
931 | continue; | ||
932 | } | ||
933 | struct sway_layer_surface *sway_layer_surface = | ||
934 | layer_from_wlr_layer_surface(wlr_layer_surface); | ||
935 | pixman_box32_t output_box = { | ||
936 | .x2 = output->swayc->current.swayc_width, | ||
937 | .y2 = output->swayc->current.swayc_height, | ||
938 | }; | ||
939 | pixman_region32_t surface_opaque_box; | ||
940 | pixman_region32_init(&surface_opaque_box); | ||
941 | pixman_region32_copy(&surface_opaque_box, &wlr_surface->current.opaque); | ||
942 | pixman_region32_translate(&surface_opaque_box, | ||
943 | sway_layer_surface->geo.x, sway_layer_surface->geo.y); | ||
944 | bool contains = pixman_region32_contains_rectangle( | ||
945 | &wlr_surface->current.opaque, &output_box); | ||
946 | pixman_region32_fini(&surface_opaque_box); | ||
947 | if (contains) { | ||
948 | return true; | ||
949 | } | ||
950 | } | ||
951 | return false; | ||
952 | } | ||
953 | |||
918 | static void render_output(struct sway_output *output, struct timespec *when, | 954 | static void render_output(struct sway_output *output, struct timespec *when, |
919 | pixman_region32_t *damage) { | 955 | pixman_region32_t *damage) { |
920 | struct wlr_output *wlr_output = output->wlr_output; | 956 | struct wlr_output *wlr_output = output->wlr_output; |
@@ -948,8 +984,21 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
948 | 984 | ||
949 | struct sway_container *workspace = output_get_active_workspace(output); | 985 | struct sway_container *workspace = output_get_active_workspace(output); |
950 | struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; | 986 | struct sway_view *fullscreen_view = workspace->current.ws_fullscreen; |
987 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
951 | 988 | ||
952 | if (fullscreen_view) { | 989 | if (output_has_opaque_lockscreen(output, seat)) { |
990 | struct wlr_layer_surface *wlr_layer_surface = seat->focused_layer; | ||
991 | struct sway_layer_surface *sway_layer_surface = | ||
992 | layer_from_wlr_layer_surface(seat->focused_layer); | ||
993 | struct render_data data = { | ||
994 | .output = output, | ||
995 | .damage = damage, | ||
996 | .alpha = 1.0f, | ||
997 | }; | ||
998 | surface_for_each_surface(wlr_layer_surface->surface, | ||
999 | sway_layer_surface->geo.x, sway_layer_surface->geo.y, | ||
1000 | &data.root_geo, render_surface_iterator, &data); | ||
1001 | } else if (fullscreen_view) { | ||
953 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | 1002 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; |
954 | 1003 | ||
955 | int nrects; | 1004 | int nrects; |
@@ -1019,11 +1068,16 @@ struct send_frame_done_data { | |||
1019 | struct root_geometry root_geo; | 1068 | struct root_geometry root_geo; |
1020 | struct sway_output *output; | 1069 | struct sway_output *output; |
1021 | struct timespec *when; | 1070 | struct timespec *when; |
1071 | struct wl_client *exclusive_client; | ||
1022 | }; | 1072 | }; |
1023 | 1073 | ||
1024 | static void send_frame_done_iterator(struct wlr_surface *surface, | 1074 | static void send_frame_done_iterator(struct wlr_surface *surface, |
1025 | int sx, int sy, void *_data) { | 1075 | int sx, int sy, void *_data) { |
1026 | struct send_frame_done_data *data = _data; | 1076 | struct send_frame_done_data *data = _data; |
1077 | if (data->exclusive_client && | ||
1078 | data->exclusive_client != surface->resource->client) { | ||
1079 | return; | ||
1080 | } | ||
1027 | 1081 | ||
1028 | bool intersects = get_surface_box(&data->root_geo, data->output, surface, | 1082 | bool intersects = get_surface_box(&data->root_geo, data->output, surface, |
1029 | sx, sy, NULL); | 1083 | sx, sy, NULL); |
@@ -1072,9 +1126,12 @@ static void send_frame_done_container(struct send_frame_done_data *data, | |||
1072 | } | 1126 | } |
1073 | 1127 | ||
1074 | static void send_frame_done(struct sway_output *output, struct timespec *when) { | 1128 | static void send_frame_done(struct sway_output *output, struct timespec *when) { |
1129 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
1075 | struct send_frame_done_data data = { | 1130 | struct send_frame_done_data data = { |
1076 | .output = output, | 1131 | .output = output, |
1077 | .when = when, | 1132 | .when = when, |
1133 | .exclusive_client = output_has_opaque_lockscreen(output, seat) ? | ||
1134 | seat->exclusive_client : NULL, | ||
1078 | }; | 1135 | }; |
1079 | 1136 | ||
1080 | struct sway_container *workspace = output_get_active_workspace(output); | 1137 | struct sway_container *workspace = output_get_active_workspace(output); |
diff --git a/swaylock/main.c b/swaylock/main.c index f31ed679..1c0cef2b 100644 --- a/swaylock/main.c +++ b/swaylock/main.c | |||
@@ -84,6 +84,13 @@ static const struct zwlr_layer_surface_v1_listener layer_surface_listener; | |||
84 | static cairo_surface_t *select_image(struct swaylock_state *state, | 84 | static cairo_surface_t *select_image(struct swaylock_state *state, |
85 | struct swaylock_surface *surface); | 85 | struct swaylock_surface *surface); |
86 | 86 | ||
87 | static bool surface_is_opaque(struct swaylock_surface *surface) { | ||
88 | if (surface->image) { | ||
89 | return cairo_surface_get_content(surface->image) == CAIRO_CONTENT_COLOR; | ||
90 | } | ||
91 | return (surface->state->args.color & 0xff) == 0xff; | ||
92 | } | ||
93 | |||
87 | static void create_layer_surface(struct swaylock_surface *surface) { | 94 | static void create_layer_surface(struct swaylock_surface *surface) { |
88 | struct swaylock_state *state = surface->state; | 95 | struct swaylock_state *state = surface->state; |
89 | 96 | ||
@@ -108,6 +115,17 @@ static void create_layer_surface(struct swaylock_surface *surface) { | |||
108 | surface->layer_surface, true); | 115 | surface->layer_surface, true); |
109 | zwlr_layer_surface_v1_add_listener(surface->layer_surface, | 116 | zwlr_layer_surface_v1_add_listener(surface->layer_surface, |
110 | &layer_surface_listener, surface); | 117 | &layer_surface_listener, surface); |
118 | |||
119 | if (surface_is_opaque(surface) && | ||
120 | surface->state->args.mode != BACKGROUND_MODE_CENTER && | ||
121 | surface->state->args.mode != BACKGROUND_MODE_FIT) { | ||
122 | struct wl_region *region = | ||
123 | wl_compositor_create_region(surface->state->compositor); | ||
124 | wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); | ||
125 | wl_surface_set_opaque_region(surface->surface, region); | ||
126 | wl_region_destroy(region); | ||
127 | } | ||
128 | |||
111 | wl_surface_commit(surface->surface); | 129 | wl_surface_commit(surface->surface); |
112 | } | 130 | } |
113 | 131 | ||