diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 72bc561d..9ed576cd 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -85,6 +85,51 @@ struct _CogWlPlatformClass { struct _CogWlPlatform { CogPlatform parent; }; +static void resize_to_largest_output(); +static void resize_window(); +static void configure_surface_geometry(); +static void xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t serial); +static void xdg_toplevel_on_configure(void * data, + struct xdg_toplevel *toplevel, + int32_t width, + int32_t height, + struct wl_array * states); +static void xdg_toplevel_on_close(void *data, struct xdg_toplevel *xdg_toplevel); +static void shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial); +static void shell_surface_configure(void * data, + struct wl_shell_surface *shell_surface, + uint32_t edges, + int32_t width, + int32_t height); +static void +xdg_popup_on_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); +static void xdg_popup_on_popup_done(void *data, struct xdg_popup *xdg_popup); +static void shell_popup_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial); +static void shell_popup_surface_configure(void * data, + struct wl_shell_surface *shell_surface, + uint32_t edges, + int32_t width, + int32_t height); +static void shell_popup_surface_popup_done(void *data, struct wl_shell_surface *shell_surface); +static void display_popup(void); +static const struct xdg_surface_listener xdg_surface_listener = {.configure = xdg_surface_on_configure}; +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_on_configure, + .close = xdg_toplevel_on_close, +}; +static const struct wl_shell_surface_listener shell_surface_listener = { + .ping = shell_surface_ping, + .configure = shell_surface_configure, +}; +static const struct xdg_popup_listener xdg_popup_listener = { + .configure = xdg_popup_on_configure, + .popup_done = xdg_popup_on_popup_done, +}; +static const struct wl_shell_surface_listener shell_popup_surface_listener = { + .ping = shell_popup_surface_ping, + .configure = shell_popup_surface_configure, + .popup_done = shell_popup_surface_popup_done, +}; G_DECLARE_FINAL_TYPE(CogWlPlatform, cog_wl_platform, COG, WL_PLATFORM, CogPlatform) @@ -132,16 +177,26 @@ struct shm_buffer { #endif #ifndef EGL_WL_create_wayland_buffer_from_image -typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image); +typedef struct wl_buffer *(EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image); #endif +typedef struct shell_functions { + void (*enter_fullscreen)(); + void (*exit_fullscreen)(); + void (*destroy_shell)(); + void (*maximize_surface)(); + void (*create_window)(); + void (*create_popup)(); +} shell_functions; + +shell_functions initial_shell_functions; typedef struct output_metrics { - struct wl_output *output; - int32_t name; - int32_t scale; - int32_t width; - int32_t height; + struct wl_output *output; + int32_t name; + int32_t scale; + int32_t width; + int32_t height; } output_metrics; static struct { @@ -238,9 +293,10 @@ static struct { GHashTable *video_surfaces; #endif - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; + struct xdg_surface * xdg_surface; + struct xdg_toplevel * xdg_toplevel; struct wl_shell_surface *shell_surface; + shell_functions * shell_functions; uint32_t width; uint32_t height; @@ -254,12 +310,11 @@ static struct { bool is_resizing_fullscreen; bool is_maximized; bool should_resize_to_largest_output; -} win_data = { - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - .width_before_fullscreen = DEFAULT_WIDTH, - .height_before_fullscreen = DEFAULT_HEIGHT, -}; +} win_data = {.width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .width_before_fullscreen = DEFAULT_WIDTH, + .height_before_fullscreen = DEFAULT_HEIGHT, + .shell_functions = &initial_shell_functions}; static struct { struct wl_surface *wl_surface; @@ -281,14 +336,200 @@ static struct { .configured = false, }; +//functions that carry out shell operations +//TODO: put in a separate file +// xdg shell operations +static void +xdg_shell_enter_fullscreen() +{ + xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); +} +static void +xdg_shell_exit_fullscreen() +{ + xdg_toplevel_unset_fullscreen(win_data.xdg_toplevel); +} +static void +destroy_xdg_shell() +{ + xdg_wm_base_destroy(wl_data.xdg_shell); +} +static void +maximize_xdg_shell_surface() +{ + xdg_toplevel_set_maximized(win_data.xdg_toplevel); +} +static void +create_xdg_shell_window() +{ + win_data.xdg_surface = xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, win_data.wl_surface); + g_assert(win_data.xdg_surface); + + xdg_surface_add_listener(win_data.xdg_surface, &xdg_surface_listener, NULL); + win_data.xdg_toplevel = xdg_surface_get_toplevel(win_data.xdg_surface); + g_assert(win_data.xdg_toplevel); + + xdg_toplevel_add_listener(win_data.xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title(win_data.xdg_toplevel, COG_DEFAULT_APPNAME); + + const char * app_id = NULL; + GApplication *app = g_application_get_default(); + if (app) { + app_id = g_application_get_application_id(app); + } + if (!app_id) { + app_id = COG_DEFAULT_APPID; + } + xdg_toplevel_set_app_id(win_data.xdg_toplevel, app_id); + wl_surface_commit(win_data.wl_surface); +} +static void +create_xdg_shell_popup() +{ + popup_data.xdg_positioner = xdg_wm_base_create_positioner(wl_data.xdg_shell); + g_assert(popup_data.xdg_positioner); + + xdg_positioner_set_size(popup_data.xdg_positioner, popup_data.width, popup_data.height); + xdg_positioner_set_anchor_rect(popup_data.xdg_positioner, 0, (win_data.height - popup_data.height), + popup_data.width, popup_data.height); + + popup_data.xdg_surface = xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, popup_data.wl_surface); + g_assert(popup_data.xdg_surface); + + xdg_surface_add_listener(popup_data.xdg_surface, &xdg_surface_listener, NULL); + popup_data.xdg_popup = + xdg_surface_get_popup(popup_data.xdg_surface, win_data.xdg_surface, popup_data.xdg_positioner); + g_assert(popup_data.xdg_popup); + + xdg_popup_add_listener(popup_data.xdg_popup, &xdg_popup_listener, NULL); + xdg_popup_grab(popup_data.xdg_popup, wl_data.seat, wl_data.event_serial); + wl_surface_commit(popup_data.wl_surface); +} + +static shell_functions xdg_shell_functions = {.enter_fullscreen = &xdg_shell_enter_fullscreen, + .exit_fullscreen = &xdg_shell_exit_fullscreen, + .destroy_shell = &destroy_xdg_shell, + .maximize_surface = &maximize_xdg_shell_surface, + .create_window = &create_xdg_shell_window, + .create_popup = &create_xdg_shell_popup}; + +// wl shell operations +static void +wl_shell_enter_fullscreen() +{ + wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); +} +static void +wl_shell_exit_fullscreen() +{ + wl_shell_surface_set_toplevel(win_data.shell_surface); + configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); + resize_window(); +} +static void +destroy_wl_shell() +{ + wl_shell_destroy(wl_data.shell); +} +static void +maximize_wl_shell_surface() +{ + wl_shell_surface_set_maximized(win_data.shell_surface, NULL); +} +static void +create_wl_shell_window() +{ + win_data.shell_surface = wl_shell_get_shell_surface(wl_data.shell, win_data.wl_surface); + g_assert(win_data.shell_surface); + + wl_shell_surface_add_listener(win_data.shell_surface, &shell_surface_listener, 0); + wl_shell_surface_set_toplevel(win_data.shell_surface); + + /* wl_shell needs an initial surface configuration. */ + configure_surface_geometry(0, 0); +} +static void +create_wl_shell_popup() +{ + popup_data.shell_surface = wl_shell_get_shell_surface(wl_data.shell, popup_data.wl_surface); + g_assert(popup_data.shell_surface); + + wl_shell_surface_add_listener(popup_data.shell_surface, &shell_popup_surface_listener, NULL); + wl_shell_surface_set_popup(popup_data.shell_surface, wl_data.seat, wl_data.event_serial, win_data.wl_surface, 0, + (win_data.height - popup_data.height), 0); + + display_popup(); +} + +static shell_functions wayland_shell_functions = {.enter_fullscreen = &wl_shell_enter_fullscreen, + .exit_fullscreen = &wl_shell_exit_fullscreen, + .destroy_shell = &destroy_wl_shell, + .maximize_surface = &maximize_wl_shell_surface, + .create_window = &create_wl_shell_window, + .create_popup = &create_wl_shell_popup}; + +// f shell operations +static void +f_shell_enter_fullscreen() +{ + win_data.should_resize_to_largest_output = true; + resize_to_largest_output(); +} +static void +f_shell_exit_fullscreen() +{ + configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); + resize_window(); +} +static void +destroy_f_shell() +{ + zwp_fullscreen_shell_v1_destroy(wl_data.fshell); +} +static void +create_f_shell_window() +{ + zwp_fullscreen_shell_v1_present_surface(wl_data.fshell, + win_data.wl_surface, + ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, + NULL); + + /* Configure the surface so that it respects the width and height + * environment variables */ + configure_surface_geometry(0, 0); +} + +static shell_functions f_shell_functions = {.exit_fullscreen = &f_shell_exit_fullscreen, + .destroy_shell = &destroy_f_shell, + .create_window = &create_f_shell_window, + .enter_fullscreen = &f_shell_enter_fullscreen}; + +//default executed when no shell exist +static void +no_shell_fullscreen() +{ + g_warning("No available shell capable of fullscreening."); + win_data.is_fullscreen = false; +} +static void +no_shell_exit_fullscreen() +{ + g_assert_not_reached(); +} +static void +maximize_no_shell() +{ + g_warning("No available shell capable of maximizing."); + win_data.is_maximized = false; +} static struct { - struct xkb_context* context; - struct xkb_keymap* keymap; - struct xkb_state* state; + struct xkb_context *context; + struct xkb_keymap * keymap; + struct xkb_state * state; - struct xkb_compose_table* compose_table; - struct xkb_compose_state* compose_state; + struct xkb_compose_table *compose_table; + struct xkb_compose_state *compose_state; struct { xkb_mod_index_t control; @@ -296,7 +537,9 @@ static struct { xkb_mod_index_t shift; } indexes; uint8_t modifiers; -} xkb_data = {NULL, }; +} xkb_data = { + NULL, +}; static struct { struct wpe_view_backend_exportable_fdo *exportable; @@ -373,6 +616,23 @@ wl_src_finalize(GSource *base) { } +static void +default_no_shell(shell_functions *shell_functions) +{ + if (shell_functions->enter_fullscreen != NULL) { + no_shell_fullscreen(); + return; + } + if (shell_functions->exit_fullscreen != NULL) { + no_shell_exit_fullscreen(); + return; + } + if (shell_functions->maximize_surface != NULL) { + maximize_no_shell(); + return; + } +} + static GSource * setup_wayland_event_source(GMainContext *main_context, struct wl_display *display) { @@ -460,11 +720,6 @@ shell_surface_configure(void *data, resize_window(); } -static const struct wl_shell_surface_listener shell_surface_listener = { - .ping = shell_surface_ping, - .configure = shell_surface_configure, -}; - static void shell_popup_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) { @@ -486,12 +741,6 @@ shell_popup_surface_popup_done (void *data, { } -static const struct wl_shell_surface_listener shell_popup_surface_listener = { - .ping = shell_popup_surface_ping, - .configure = shell_popup_surface_configure, - .popup_done = shell_popup_surface_popup_done, -}; - static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { @@ -513,14 +762,12 @@ xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t seria } } -static const struct xdg_surface_listener xdg_surface_listener = {.configure = xdg_surface_on_configure}; - static void -xdg_toplevel_on_configure(void *data, +xdg_toplevel_on_configure(void * data, struct xdg_toplevel *toplevel, - int32_t width, - int32_t height, - struct wl_array *states) + int32_t width, + int32_t height, + struct wl_array * states) { configure_surface_geometry(width, height); @@ -535,11 +782,6 @@ xdg_toplevel_on_close(void *data, struct xdg_toplevel *xdg_toplevel) g_application_quit(g_application_get_default()); } -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_on_configure, - .close = xdg_toplevel_on_close, -}; - static void xdg_popup_on_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { @@ -551,11 +793,6 @@ xdg_popup_on_popup_done(void *data, struct xdg_popup *xdg_popup) destroy_popup(); } -static const struct xdg_popup_listener xdg_popup_listener = { - .configure = xdg_popup_on_configure, - .popup_done = xdg_popup_on_popup_done, -}; - static void resize_to_largest_output() { @@ -637,13 +874,7 @@ cog_wl_does_image_match_win_size(struct wpe_fdo_egl_exported_image *image) static void cog_wl_fullscreen_image_ready() { - if (wl_data.xdg_shell) { - xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); - } else if (wl_data.shell) { - wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); - } else if (wl_data.fshell == NULL) { - g_assert_not_reached(); - } + win_data.shell_functions->enter_fullscreen(); win_data.is_resizing_fullscreen = false; #if HAVE_FULLSCREEN_HANDLING @@ -670,18 +901,7 @@ cog_wl_set_fullscreen(void *unused, bool fullscreen) if (cog_wl_does_image_match_win_size(wpe_view_data.image)) cog_wl_fullscreen_image_ready(); } else { - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_unset_fullscreen(win_data.xdg_toplevel); - } else if (wl_data.fshell != NULL) { - configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); - resize_window(); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_toplevel(win_data.shell_surface); - configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); - resize_window(); - } else { - g_assert_not_reached(); - } + win_data.shell_functions->exit_fullscreen(); #if HAVE_FULLSCREEN_HANDLING if (win_data.was_fullscreen_requested_from_dom) wpe_view_backend_dispatch_did_exit_fullscreen(wpe_view_data.backend); @@ -757,14 +977,29 @@ registry_global (void *data, wl_data.subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, version); } else if (strcmp(interface, wl_shell_interface.name) == 0) { wl_data.shell = wl_registry_bind(registry, name, &wl_shell_interface, version); + if (wl_data.shell != NULL) { + win_data.shell_functions = &wayland_shell_functions; + } else { + default_no_shell(&wayland_shell_functions); + } } else if (strcmp(interface, wl_shm_interface.name) == 0) { wl_data.shm = wl_registry_bind(registry, name, &wl_shm_interface, version); } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { wl_data.xdg_shell = wl_registry_bind(registry, name, &xdg_wm_base_interface, version); g_assert(wl_data.xdg_shell); xdg_wm_base_add_listener(wl_data.xdg_shell, &xdg_shell_listener, NULL); + if (wl_data.xdg_shell != NULL) { + win_data.shell_functions = &xdg_shell_functions; + } else { + default_no_shell(&xdg_shell_functions); + } } else if (strcmp(interface, zwp_fullscreen_shell_v1_interface.name) == 0) { wl_data.fshell = wl_registry_bind(registry, name, &zwp_fullscreen_shell_v1_interface, version); + if (wl_data.fshell != NULL) { + win_data.shell_functions = &f_shell_functions; + } else { + default_no_shell(&f_shell_functions); + } } else if (strcmp(interface, wl_seat_interface.name) == 0) { wl_data.seat = wl_registry_bind(registry, name, &wl_seat_interface, version); #if COG_ENABLE_WESTON_DIRECT_DISPLAY @@ -1968,24 +2203,18 @@ init_wayland (GError **error) } static void -clear_wayland (void) +clear_wayland(void) { + win_data.shell_functions->destroy_shell(); g_clear_pointer(&wl_data.event_src, g_source_destroy); - if (wl_data.xdg_shell != NULL) - xdg_wm_base_destroy (wl_data.xdg_shell); - if (wl_data.fshell != NULL) - zwp_fullscreen_shell_v1_destroy (wl_data.fshell); - if (wl_data.shell != NULL) - wl_shell_destroy (wl_data.shell); - - g_clear_pointer (&wl_data.shm, wl_shm_destroy); - g_clear_pointer (&wl_data.subcompositor, wl_subcompositor_destroy); - g_clear_pointer (&wl_data.compositor, wl_compositor_destroy); + g_clear_pointer(&wl_data.shm, wl_shm_destroy); + g_clear_pointer(&wl_data.subcompositor, wl_subcompositor_destroy); + g_clear_pointer(&wl_data.compositor, wl_compositor_destroy); #if COG_ENABLE_WESTON_DIRECT_DISPLAY - g_clear_pointer (&wl_data.protection, weston_content_protection_destroy); - g_clear_pointer (&wl_data.direct_display, weston_direct_display_v1_destroy); + g_clear_pointer(&wl_data.protection, weston_content_protection_destroy); + g_clear_pointer(&wl_data.direct_display, weston_direct_display_v1_destroy); #endif #ifdef COG_USE_WAYLAND_CURSOR @@ -2125,93 +2354,50 @@ clear_egl (void) } static gboolean -create_window (GError **error) +create_window(GError **error) { - g_debug ("Creating Wayland surface..."); + g_debug("Creating Wayland surface..."); - win_data.wl_surface = wl_compositor_create_surface (wl_data.compositor); - g_assert (win_data.wl_surface); + win_data.wl_surface = wl_compositor_create_surface(wl_data.compositor); + g_assert(win_data.wl_surface); #if COG_ENABLE_WESTON_DIRECT_DISPLAY - win_data.video_surfaces = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, destroy_video_surface); + win_data.video_surfaces = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, destroy_video_surface); #endif - wl_surface_add_listener (win_data.wl_surface, &surface_listener, NULL); - - if (wl_data.xdg_shell != NULL) { - win_data.xdg_surface = - xdg_wm_base_get_xdg_surface (wl_data.xdg_shell, - win_data.wl_surface); - g_assert(win_data.xdg_surface); - - xdg_surface_add_listener (win_data.xdg_surface, &xdg_surface_listener, - NULL); - win_data.xdg_toplevel = - xdg_surface_get_toplevel (win_data.xdg_surface); - g_assert(win_data.xdg_toplevel); - - xdg_toplevel_add_listener (win_data.xdg_toplevel, - &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (win_data.xdg_toplevel, COG_DEFAULT_APPNAME); - - const char *app_id = NULL; - GApplication *app = g_application_get_default (); - if (app) { - app_id = g_application_get_application_id (app); - } - if (!app_id) { - app_id = COG_DEFAULT_APPID; - } - xdg_toplevel_set_app_id (win_data.xdg_toplevel, app_id); - wl_surface_commit(win_data.wl_surface); - } else if (wl_data.fshell != NULL) { - zwp_fullscreen_shell_v1_present_surface (wl_data.fshell, - win_data.wl_surface, - ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, - NULL); - - /* Configure the surface so that it respects the width and height - * environment variables */ - configure_surface_geometry(0, 0); - } else if (wl_data.shell != NULL) { - win_data.shell_surface = wl_shell_get_shell_surface(wl_data.shell, win_data.wl_surface); - g_assert(win_data.shell_surface); - - wl_shell_surface_add_listener(win_data.shell_surface, &shell_surface_listener, 0); - wl_shell_surface_set_toplevel(win_data.shell_surface); - - /* wl_shell needs an initial surface configuration. */ - configure_surface_geometry(0, 0); - } + wl_surface_add_listener(win_data.wl_surface, &surface_listener, NULL); + win_data.shell_functions->create_window(); const char *env_var; if ((env_var = g_getenv("COG_PLATFORM_WL_VIEW_FULLSCREEN")) && g_ascii_strtoll(env_var, NULL, 10) > 0) { win_data.is_maximized = false; win_data.is_fullscreen = true; - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); - } else if (wl_data.fshell != NULL) { - win_data.should_resize_to_largest_output = true; - resize_to_largest_output(); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); - } else { - g_warning("No available shell capable of fullscreening."); - win_data.is_fullscreen = false; - } + // if (wl_data.xdg_shell != NULL) { + // xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); + // } else if (wl_data.fshell != NULL) { + // win_data.should_resize_to_largest_output = true; + // resize_to_largest_output(); + // } else if (wl_data.shell != NULL) { + // wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); + // } else { + // g_warning("No available shell capable of fullscreening."); + // win_data.is_fullscreen = false; + // } + win_data.shell_functions->enter_fullscreen(); } else if ((env_var = g_getenv("COG_PLATFORM_WL_VIEW_MAXIMIZE")) && g_ascii_strtoll(env_var, NULL, 10) > 0) { win_data.is_maximized = true; win_data.is_fullscreen = false; - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_set_maximized (win_data.xdg_toplevel); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_maximized (win_data.shell_surface, NULL); - } else { - g_warning ("No available shell capable of maximizing."); - win_data.is_maximized = false; - } + // if (wl_data.xdg_shell != NULL) { + // xdg_toplevel_set_maximized (win_data.xdg_toplevel); + // } else if (wl_data.shell != NULL) { + // wl_shell_surface_set_maximized (win_data.shell_surface, NULL); + // } else { + // g_warning ("No available shell capable of maximizing."); + // win_data.is_maximized = false; + // } + win_data.shell_functions->maximize_surface(); } return TRUE; @@ -2236,63 +2422,19 @@ create_popup (WebKitOptionMenu *option_menu) popup_data.option_menu = option_menu; popup_data.width = win_data.width; - popup_data.height = cog_popup_menu_get_height_for_option_menu (option_menu); - - popup_data.popup_menu = cog_popup_menu_create (option_menu, wl_data.shm, - popup_data.width, - popup_data.height, - wl_data.current_output.scale); - - popup_data.wl_surface = wl_compositor_create_surface (wl_data.compositor); - g_assert (popup_data.wl_surface); - wl_surface_set_buffer_scale (popup_data.wl_surface, wl_data.current_output.scale); - - if (wl_data.xdg_shell != NULL) { - popup_data.xdg_positioner = xdg_wm_base_create_positioner (wl_data.xdg_shell); - g_assert(popup_data.xdg_positioner); + popup_data.height = cog_popup_menu_get_height_for_option_menu(option_menu); - xdg_positioner_set_size (popup_data.xdg_positioner, - popup_data.width, - popup_data.height); - xdg_positioner_set_anchor_rect(popup_data.xdg_positioner, 0, (win_data.height - popup_data.height), - popup_data.width, popup_data.height); + popup_data.popup_menu = cog_popup_menu_create(option_menu, wl_data.shm, popup_data.width, popup_data.height, + wl_data.current_output.scale); - popup_data.xdg_surface = xdg_wm_base_get_xdg_surface (wl_data.xdg_shell, - popup_data.wl_surface); - g_assert (popup_data.xdg_surface); - - xdg_surface_add_listener (popup_data.xdg_surface, - &xdg_surface_listener, - NULL); - popup_data.xdg_popup = xdg_surface_get_popup (popup_data.xdg_surface, - win_data.xdg_surface, - popup_data.xdg_positioner); - g_assert (popup_data.xdg_popup); - - xdg_popup_add_listener (popup_data.xdg_popup, - &xdg_popup_listener, - NULL); - xdg_popup_grab (popup_data.xdg_popup, wl_data.seat, wl_data.event_serial); - wl_surface_commit (popup_data.wl_surface); - } else if (wl_data.shell != NULL) { - popup_data.shell_surface = wl_shell_get_shell_surface (wl_data.shell, - popup_data.wl_surface); - g_assert(popup_data.shell_surface); - - wl_shell_surface_add_listener (popup_data.shell_surface, - &shell_popup_surface_listener, - NULL); - wl_shell_surface_set_popup (popup_data.shell_surface, - wl_data.seat, wl_data.event_serial, - win_data.wl_surface, - 0, (win_data.height - popup_data.height), 0); - - display_popup(); - } + popup_data.wl_surface = wl_compositor_create_surface(wl_data.compositor); + g_assert(popup_data.wl_surface); + wl_surface_set_buffer_scale(popup_data.wl_surface, wl_data.current_output.scale); + win_data.shell_functions->create_popup(); } static void -destroy_popup (void) +destroy_popup(void) { if (popup_data.option_menu == NULL) return;