|
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" |
31 | 34 | #include "osdep/io.h" |
| 35 | +#include "osdep/path.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 *vo); |
| 346 | +static void write_session_id(void *talloc_ctx, struct vo *vo, 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, |
@@ -2719,6 +2732,33 @@ static const struct zwp_linux_dmabuf_feedback_v1_listener dmabuf_feedback_listen |
2719 | 2732 | .tranche_flags = tranche_flags, |
2720 | 2733 | }; |
2721 | 2734 |
|
| 2735 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 2736 | +static void xdg_session_created(void *data, struct xdg_session_v1 *xdg_session_v1, const char *session_id) |
| 2737 | +{ |
| 2738 | + struct vo_wayland_state *wl = data; |
| 2739 | + void *tmp = talloc_new(NULL); |
| 2740 | + write_session_id(tmp, wl->vo, session_id); |
| 2741 | + talloc_free(tmp); |
| 2742 | +} |
| 2743 | + |
| 2744 | +static void xdg_session_restored(void *data, struct xdg_session_v1 *xdg_session_v1) |
| 2745 | +{ |
| 2746 | + // nothing |
| 2747 | +} |
| 2748 | + |
| 2749 | +static void xdg_session_replaced(void *data, struct xdg_session_v1 *xdg_session_v1) |
| 2750 | +{ |
| 2751 | + struct vo_wayland_state *wl = data; |
| 2752 | + MP_WARN(wl, "Session has been replaced!\n"); |
| 2753 | +} |
| 2754 | + |
| 2755 | +static const struct xdg_session_v1_listener xdg_session_listener = { |
| 2756 | + .created = xdg_session_created, |
| 2757 | + .restored = xdg_session_restored, |
| 2758 | + .replaced = xdg_session_replaced, |
| 2759 | +}; |
| 2760 | +#endif |
| 2761 | + |
2722 | 2762 | static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id, |
2723 | 2763 | const char *interface, uint32_t ver) |
2724 | 2764 | { |
@@ -2897,6 +2937,21 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id |
2897 | 2937 | wl->wp_tablet_manager = wl_registry_bind(reg, id, &zwp_tablet_manager_v2_interface, ver); |
2898 | 2938 | } |
2899 | 2939 |
|
| 2940 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 2941 | + if (!strcmp(interface, xdg_session_manager_v1_interface.name) && found++) { |
| 2942 | + ver = 1; |
| 2943 | + struct xdg_session_manager_v1 *xdg_session_manager = |
| 2944 | + wl_registry_bind(reg, id, &xdg_session_manager_v1_interface, ver); |
| 2945 | + void *tmp = talloc_new(NULL); |
| 2946 | + char *session_id = read_session_id(tmp, wl->vo); |
| 2947 | + wl->xdg_session = xdg_session_manager_v1_get_session(xdg_session_manager, |
| 2948 | + XDG_SESSION_MANAGER_V1_REASON_LAUNCH, |
| 2949 | + session_id); |
| 2950 | + xdg_session_v1_add_listener(wl->xdg_session, &xdg_session_listener, wl); |
| 2951 | + talloc_free(tmp); |
| 2952 | + } |
| 2953 | +#endif |
| 2954 | + |
2900 | 2955 | if (found > 1) |
2901 | 2956 | MP_VERBOSE(wl, "Registered interface %s at version %d\n", interface, ver); |
2902 | 2957 | } |
@@ -3169,6 +3224,14 @@ static int create_xdg_surface(struct vo_wayland_state *wl) |
3169 | 3224 | MP_ERR(wl, "failed to create xdg_surface and xdg_toplevel!\n"); |
3170 | 3225 | return 1; |
3171 | 3226 | } |
| 3227 | + |
| 3228 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 3229 | + if (wl->xdg_session) { |
| 3230 | + wl->xdg_toplevel_session = |
| 3231 | + xdg_session_v1_restore_toplevel(wl->xdg_session, wl->xdg_toplevel, "mpv"); |
| 3232 | + } |
| 3233 | +#endif |
| 3234 | + |
3172 | 3235 | return 0; |
3173 | 3236 | } |
3174 | 3237 |
|
@@ -4859,6 +4922,14 @@ void vo_wayland_uninit(struct vo *vo) |
4859 | 4922 | if (wl->wp_tablet_manager) |
4860 | 4923 | zwp_tablet_manager_v2_destroy(wl->wp_tablet_manager); |
4861 | 4924 |
|
| 4925 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 4926 | + if (wl->xdg_toplevel_session) |
| 4927 | + xdg_toplevel_session_v1_destroy(wl->xdg_toplevel_session); |
| 4928 | + |
| 4929 | + if (wl->xdg_session) |
| 4930 | + xdg_session_v1_destroy(wl->xdg_session); |
| 4931 | +#endif |
| 4932 | + |
4862 | 4933 | if (wl->display) |
4863 | 4934 | wl_display_disconnect(wl->display); |
4864 | 4935 |
|
@@ -4940,3 +5011,44 @@ void vo_wayland_wakeup(struct vo *vo) |
4940 | 5011 | struct vo_wayland_state *wl = vo->wl; |
4941 | 5012 | (void)write(wl->wakeup_pipe[1], &(char){0}, 1); |
4942 | 5013 | } |
| 5014 | + |
| 5015 | +#if HAVE_WAYLAND_PROTOCOLS_1_48 |
| 5016 | +static char *session_file(void *talloc_ctx, struct vo *vo) |
| 5017 | +{ |
| 5018 | + char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP"); |
| 5019 | + if (!xdg_current_desktop) |
| 5020 | + xdg_current_desktop = ""; |
| 5021 | + const char *session = vo->opts->wayland_session; |
| 5022 | + char *full_name = ta_asprintf(talloc_ctx, "%16" PRIx64 "%s%16" PRIx64 "%s", |
| 5023 | + (uint64_t)strlen(xdg_current_desktop), |
| 5024 | + xdg_current_desktop, (uint64_t)strlen(session), |
| 5025 | + session); |
| 5026 | + bstr file_name = mp_hash_to_bstr(talloc_ctx, (uint8_t*)full_name, |
| 5027 | + strlen(full_name), "SHA256"); |
| 5028 | + char *file_path; |
| 5029 | + file_path = (char*)mp_get_platform_path_unix(talloc_ctx, "state"); |
| 5030 | + file_path = mp_path_join(talloc_ctx, file_path, "sessions"); |
| 5031 | + mp_mkdirp(file_path); |
| 5032 | + file_path = mp_path_join(talloc_ctx, file_path, (char*)file_name.start); |
| 5033 | + return file_path; |
| 5034 | +} |
| 5035 | + |
| 5036 | +static char *read_session_id(void *talloc_ctx, struct vo *vo) |
| 5037 | +{ |
| 5038 | + char *path = session_file(talloc_ctx, vo); |
| 5039 | + if (!mp_path_exists(path)) |
| 5040 | + return NULL; |
| 5041 | + bstr id = stream_read_file(path, talloc_ctx, vo->global, 4096); |
| 5042 | + if (!id.len) |
| 5043 | + return NULL; |
| 5044 | + if (bstr_validate_utf8(id) < 0) |
| 5045 | + return NULL; |
| 5046 | + return (char*)id.start; |
| 5047 | +} |
| 5048 | + |
| 5049 | +static void write_session_id(void *talloc_ctx, struct vo *vo, const char *id) |
| 5050 | +{ |
| 5051 | + char *path = session_file(talloc_ctx, vo); |
| 5052 | + mp_save_to_file(path, id, strlen(id)); |
| 5053 | +} |
| 5054 | +#endif |
0 commit comments