|
27 | 27 | #include "common/msg.h" |
28 | 28 | #include "input/input.h" |
29 | 29 | #include "input/keycodes.h" |
| 30 | +#include "misc/hash.h" |
| 31 | +#include "misc/io_utils.h" |
| 32 | +#include "misc/path_utils.h" |
30 | 33 | #include "options/m_config.h" |
| 34 | +#include "options/path.h" |
31 | 35 | #include "osdep/io.h" |
32 | 36 | #include "osdep/poll_wrapper.h" |
33 | 37 | #include "osdep/timer.h" |
34 | 38 | #include "present_sync.h" |
| 39 | +#include "stream/stream.h" |
35 | 40 | #include "video/out/gpu/video.h" |
36 | 41 | #include "wayland_common.h" |
37 | 42 | #include "win_state.h" |
|
60 | 65 | #include "color-representation-v1.h" |
61 | 66 | #endif |
62 | 67 |
|
| 68 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 69 | +#include "xdg-session-management-v1.h" |
| 70 | +#endif |
| 71 | + |
63 | 72 | #ifndef CLOCK_MONOTONIC_RAW |
64 | 73 | #define CLOCK_MONOTONIC_RAW 4 |
65 | 74 | #endif |
@@ -332,6 +341,10 @@ static void set_surface_scaling(struct vo_wayland_state *wl); |
332 | 341 | static void update_output_scaling(struct vo_wayland_state *wl); |
333 | 342 | static void update_output_geometry(struct vo_wayland_state *wl); |
334 | 343 | static void destroy_offer(struct vo_wayland_data_offer *o); |
| 344 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 345 | +static char *read_session_id(void *talloc_ctx, struct vo_wayland_state *wl); |
| 346 | +static void write_session_id(void *talloc_ctx, struct vo_wayland_state *wl, const char *id); |
| 347 | +#endif |
335 | 348 |
|
336 | 349 | /* Wayland listener boilerplate */ |
337 | 350 | static void pointer_handle_enter(void *data, struct wl_pointer *pointer, |
@@ -2718,6 +2731,33 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_feedback_listen |
2718 | 2731 | .tranche_flags = tranche_flags, |
2719 | 2732 | }; |
2720 | 2733 |
|
| 2734 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 2735 | +static void xdg_session_created(void *data, struct xdg_session_v1 *xdg_session_v1, const char *session_id) |
| 2736 | +{ |
| 2737 | + struct vo_wayland_state *wl = data; |
| 2738 | + void *tmp = talloc_new(NULL); |
| 2739 | + write_session_id(tmp, wl, session_id); |
| 2740 | + talloc_free(tmp); |
| 2741 | +} |
| 2742 | + |
| 2743 | +static void xdg_session_restored(void *data, struct xdg_session_v1 *xdg_session_v1) |
| 2744 | +{ |
| 2745 | + // nothing |
| 2746 | +} |
| 2747 | + |
| 2748 | +static void xdg_session_replaced(void *data, struct xdg_session_v1 *xdg_session_v1) |
| 2749 | +{ |
| 2750 | + struct vo_wayland_state *wl = data; |
| 2751 | + MP_WARN(wl, "Session has been replaced!\n"); |
| 2752 | +} |
| 2753 | + |
| 2754 | +static const struct xdg_session_v1_listener xdg_session_listener = { |
| 2755 | + .created = xdg_session_created, |
| 2756 | + .restored = xdg_session_restored, |
| 2757 | + .replaced = xdg_session_replaced, |
| 2758 | +}; |
| 2759 | +#endif |
| 2760 | + |
2721 | 2761 | static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, |
2722 | 2762 | const char *interface, uint32_t ver) |
2723 | 2763 | { |
@@ -2896,6 +2936,25 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id |
2896 | 2936 | wl->wp_tablet_manager = wl_registry_bind(reg, id, &zwp_tablet_manager_v2_interface, ver); |
2897 | 2937 | } |
2898 | 2938 |
|
| 2939 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 2940 | + if (wl->wayland_session && |
| 2941 | + !strcmp(interface, xdg_session_manager_v1_interface.name) && |
| 2942 | + found++) |
| 2943 | + { |
| 2944 | + ver = 1; |
| 2945 | + struct xdg_session_manager_v1 *xdg_session_manager = |
| 2946 | + wl_registry_bind(reg, id, &xdg_session_manager_v1_interface, ver); |
| 2947 | + void *tmp = talloc_new(NULL); |
| 2948 | + char *session_id = read_session_id(tmp, wl); |
| 2949 | + wl->xdg_session = xdg_session_manager_v1_get_session(xdg_session_manager, |
| 2950 | + XDG_SESSION_MANAGER_V1_REASON_LAUNCH, |
| 2951 | + session_id); |
| 2952 | + xdg_session_v1_add_listener(wl->xdg_session, &xdg_session_listener, wl); |
| 2953 | + talloc_free(tmp); |
| 2954 | + xdg_session_manager_v1_destroy(xdg_session_manager); |
| 2955 | + } |
| 2956 | +#endif |
| 2957 | + |
2899 | 2958 | if (found > 1) |
2900 | 2959 | MP_VERBOSE(wl, "Registered interface %s at version %d\n", interface, ver); |
2901 | 2960 | } |
@@ -3168,6 +3227,14 @@ static int create_xdg_surface(struct vo_wayland_state *wl) |
3168 | 3227 | MP_ERR(wl, "failed to create xdg_surface and xdg_toplevel!\n"); |
3169 | 3228 | return 1; |
3170 | 3229 | } |
| 3230 | + |
| 3231 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 3232 | + if (wl->xdg_session) { |
| 3233 | + wl->xdg_toplevel_session = |
| 3234 | + xdg_session_v1_restore_toplevel(wl->xdg_session, wl->xdg_toplevel, "mpv"); |
| 3235 | + } |
| 3236 | +#endif |
| 3237 | + |
3171 | 3238 | return 0; |
3172 | 3239 | } |
3173 | 3240 |
|
@@ -4459,6 +4526,9 @@ bool vo_wayland_init(struct vo *vo) |
4459 | 4526 | if (create_input(wl)) |
4460 | 4527 | goto err; |
4461 | 4528 |
|
| 4529 | + if (wl->opts->wayland_session && *wl->opts->wayland_session) |
| 4530 | + wl->wayland_session = talloc_strdup(wl, wl->opts->wayland_session); |
| 4531 | + |
4462 | 4532 | wl->registry = wl_display_get_registry(wl->display); |
4463 | 4533 | wl_registry_add_listener(wl->registry, ®istry_listener, wl); |
4464 | 4534 |
|
@@ -4861,6 +4931,14 @@ void vo_wayland_uninit(struct vo *vo) |
4861 | 4931 | if (wl->wp_tablet_manager) |
4862 | 4932 | zwp_tablet_manager_v2_destroy(wl->wp_tablet_manager); |
4863 | 4933 |
|
| 4934 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 4935 | + if (wl->xdg_toplevel_session) |
| 4936 | + xdg_toplevel_session_v1_destroy(wl->xdg_toplevel_session); |
| 4937 | + |
| 4938 | + if (wl->xdg_session) |
| 4939 | + xdg_session_v1_destroy(wl->xdg_session); |
| 4940 | +#endif |
| 4941 | + |
4864 | 4942 | if (wl->display) |
4865 | 4943 | wl_display_disconnect(wl->display); |
4866 | 4944 |
|
@@ -4942,3 +5020,43 @@ void vo_wayland_wakeup(struct vo *vo) |
4942 | 5020 | struct vo_wayland_state *wl = vo->wl; |
4943 | 5021 | (void)write(wl->wakeup_pipe[1], &(char){0}, 1); |
4944 | 5022 | } |
| 5023 | + |
| 5024 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 5025 | +static char *session_file(void *talloc_ctx, struct vo_wayland_state *wl) |
| 5026 | +{ |
| 5027 | + char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP"); |
| 5028 | + if (!xdg_current_desktop) |
| 5029 | + xdg_current_desktop = ""; |
| 5030 | + const char *session = wl->wayland_session; |
| 5031 | + bstr full_name = {0}; |
| 5032 | + bstr_xappend_asprintf(talloc_ctx, &full_name, "%16" PRIx64 "%s%16" PRIx64 "%s", |
| 5033 | + (uint64_t)strlen(xdg_current_desktop), |
| 5034 | + xdg_current_desktop, (uint64_t)strlen(session), |
| 5035 | + session); |
| 5036 | + bstr file_name = mp_hash_to_bstr(talloc_ctx, full_name.start, full_name.len, |
| 5037 | + "SHA256"); |
| 5038 | + char *file_path = mp_find_user_file(talloc_ctx, wl->vo->global, "state", "sessions"); |
| 5039 | + mp_mkdirp(file_path); |
| 5040 | + file_path = mp_path_join_bstr(talloc_ctx, bstr0(file_path), file_name); |
| 5041 | + return file_path; |
| 5042 | +} |
| 5043 | + |
| 5044 | +static char *read_session_id(void *talloc_ctx, struct vo_wayland_state *wl) |
| 5045 | +{ |
| 5046 | + char *path = session_file(talloc_ctx, wl); |
| 5047 | + if (!mp_path_exists(path)) |
| 5048 | + return NULL; |
| 5049 | + bstr id = stream_read_file(path, talloc_ctx, wl->vo->global, 4096); |
| 5050 | + if (!id.len) |
| 5051 | + return NULL; |
| 5052 | + if (bstr_validate_utf8(id) < 0) |
| 5053 | + return NULL; |
| 5054 | + return bstrto0(talloc_ctx, id); |
| 5055 | +} |
| 5056 | + |
| 5057 | +static void write_session_id(void *talloc_ctx, struct vo_wayland_state *wl, const char *id) |
| 5058 | +{ |
| 5059 | + char *path = session_file(talloc_ctx, wl); |
| 5060 | + mp_save_to_file(path, id, strlen(id)); |
| 5061 | +} |
| 5062 | +#endif |
0 commit comments