diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 72bc561d..389a302e 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -85,6 +85,33 @@ 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); G_DECLARE_FINAL_TYPE(CogWlPlatform, cog_wl_platform, COG, WL_PLATFORM, CogPlatform) @@ -132,16 +159,56 @@ 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 { + void (*enter_fullscreen)(); + void (*exit_fullscreen)(); + void (*destroy_shell)(); + void (*maximize_surface)(); + void (*create_window)(); + void (*create_popup)(); +} shell_functions; + +typedef struct { + shell_functions * functions; + struct xdg_surface * xdg_surface; + struct xdg_toplevel *xdg_toplevel; + struct xdg_popup * xdg_popup; +} xdg_shell_data; + +typedef struct { + shell_functions * functions; + struct wl_surface * wl_surface; + struct wl_shell_surface *shell_surface; +} wl_shell_data; + +typedef struct { + shell_functions *functions; +} f_shell_data; + +typedef union { + shell_functions functions; + f_shell_data f_shell_data; + wl_shell_data wl_shell_data; + xdg_shell_data xdg_shell_data; +} shell_context; + +static void no_shell_enter_fullscreen(); +static void no_shell_exit_fullscreen(); +static void maximize_no_shell(); + +static shell_functions no_shell_functions = {.enter_fullscreen = &no_shell_enter_fullscreen, + .exit_fullscreen = &no_shell_exit_fullscreen, + .maximize_surface = &maximize_no_shell}; 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 { @@ -232,15 +299,10 @@ static struct { } egl_data; static struct { - struct wl_surface *wl_surface; - #if COG_ENABLE_WESTON_DIRECT_DISPLAY GHashTable *video_surfaces; #endif - - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - struct wl_shell_surface *shell_surface; + shell_context *shell_context; uint32_t width; uint32_t height; @@ -254,19 +316,15 @@ 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_context = (shell_context *) (&no_shell_functions)}; static struct { - struct wl_surface *wl_surface; - struct xdg_positioner *xdg_positioner; - struct xdg_surface *xdg_surface; - struct xdg_popup *xdg_popup; + shell_context * shell_context; struct wl_shell_surface *shell_surface; @@ -281,14 +339,238 @@ static struct { .configured = false, }; +//shell operation functions +//TODO: put in a separate file +static void +xdg_shell_enter_fullscreen() +{ + xdg_toplevel_set_fullscreen(win_data.shell_context->xdg_shell_data.xdg_toplevel, NULL); +} +static void +xdg_shell_exit_fullscreen() +{ + xdg_toplevel_unset_fullscreen(win_data.shell_context->xdg_shell_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.shell_context->xdg_shell_data.xdg_toplevel); +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_on_configure, + .close = xdg_toplevel_on_close, +}; + +static const struct xdg_surface_listener xdg_surface_listener = {.configure = xdg_surface_on_configure}; + +static const struct xdg_popup_listener xdg_popup_listener = { + .configure = xdg_popup_on_configure, + .popup_done = xdg_popup_on_popup_done, +}; + +static void +create_xdg_shell_window() +{ + win_data.shell_context->xdg_shell_data.xdg_surface = + xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, win_data.shell_context->wl_shell_data.wl_surface); + g_assert(win_data.shell_context->xdg_shell_data.xdg_surface); + + xdg_surface_add_listener(win_data.shell_context->xdg_shell_data.xdg_surface, &xdg_surface_listener, NULL); + win_data.shell_context->xdg_shell_data.xdg_toplevel = + xdg_surface_get_toplevel(win_data.shell_context->xdg_shell_data.xdg_surface); + g_assert(win_data.shell_context->xdg_shell_data.xdg_toplevel); + + xdg_toplevel_add_listener(win_data.shell_context->xdg_shell_data.xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title(win_data.shell_context->xdg_shell_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.shell_context->xdg_shell_data.xdg_toplevel, app_id); + wl_surface_commit(win_data.shell_context->wl_shell_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.shell_context->xdg_shell_data.xdg_surface = + xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, popup_data.shell_context->wl_shell_data.wl_surface); + g_assert(popup_data.shell_context->xdg_shell_data.xdg_surface); + + xdg_surface_add_listener(popup_data.shell_context->xdg_shell_data.xdg_surface, &xdg_surface_listener, NULL); + popup_data.shell_context->xdg_shell_data.xdg_popup = + xdg_surface_get_popup(popup_data.shell_context->xdg_shell_data.xdg_surface, + win_data.shell_context->xdg_shell_data.xdg_surface, popup_data.xdg_positioner); + g_assert(popup_data.shell_context->xdg_shell_data.xdg_popup); + + xdg_popup_add_listener(popup_data.shell_context->xdg_shell_data.xdg_popup, &xdg_popup_listener, NULL); + xdg_popup_grab(popup_data.shell_context->xdg_shell_data.xdg_popup, wl_data.seat, wl_data.event_serial); + wl_surface_commit(popup_data.shell_context->wl_shell_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}; +xdg_shell_data xdg_data = {.functions = &xdg_shell_functions}; + +// wl shell operations +static void +wl_shell_enter_fullscreen() +{ + wl_shell_surface_set_fullscreen(win_data.shell_context->wl_shell_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_context->wl_shell_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_context->wl_shell_data.shell_surface, NULL); +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + .ping = shell_surface_ping, + .configure = shell_surface_configure, +}; + +static void +create_wl_shell_window() +{ + win_data.shell_context->wl_shell_data.shell_surface = + wl_shell_get_shell_surface(wl_data.shell, win_data.shell_context->wl_shell_data.wl_surface); + g_assert(win_data.shell_context->wl_shell_data.shell_surface); + + wl_shell_surface_add_listener(win_data.shell_context->wl_shell_data.shell_surface, &shell_surface_listener, 0); + wl_shell_surface_set_toplevel(win_data.shell_context->wl_shell_data.shell_surface); + + /* wl_shell needs an initial surface configuration. */ + configure_surface_geometry(0, 0); +} + +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 +create_wl_shell_popup() +{ + popup_data.shell_surface = + wl_shell_get_shell_surface(wl_data.shell, popup_data.shell_context->wl_shell_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.shell_context->wl_shell_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}; + +wl_shell_data wayland_data = {.functions = &wayland_shell_functions}; + +// 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.shell_context->wl_shell_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}; + +f_shell_data f_data = {.functions = &f_shell_functions}; + +//default executed when no shell exist +static void +no_shell_enter_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 +578,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; @@ -460,11 +744,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 +765,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) { @@ -507,20 +780,18 @@ xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t seria { xdg_surface_ack_configure(surface, serial); - if (popup_data.xdg_surface == surface && !popup_data.configured) { + if (popup_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { popup_data.configured = true; display_popup(); } } -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 +806,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 +817,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 +898,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_context->functions.enter_fullscreen(); win_data.is_resizing_fullscreen = false; #if HAVE_FULLSCREEN_HANDLING @@ -670,18 +925,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_context->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 +1001,17 @@ 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); + win_data.shell_context = (shell_context *) (&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); + win_data.shell_context = (shell_context *) (&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); + win_data.shell_context = (shell_context *) (&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 @@ -901,8 +1148,8 @@ pointer_on_button(void *data, wl_data.pointer.state, }; - if (popup_data.wl_surface) { - if (wl_data.pointer.surface == popup_data.wl_surface) { + if (popup_data.shell_context->wl_shell_data.wl_surface) { + if (wl_data.pointer.surface == popup_data.shell_context->wl_shell_data.wl_surface) { cog_popup_menu_handle_event( popup_data.popup_menu, !!state ? COG_POPUP_MENU_EVENT_STATE_PRESSED : COG_POPUP_MENU_EVENT_STATE_RELEASED, event.x, event.y); @@ -1312,42 +1559,29 @@ touch_on_down (void *data, wpe_input_touch_event_type_down, time, id, - wl_fixed_to_int (x) * wl_data.current_output.scale, - wl_fixed_to_int (y) * wl_data.current_output.scale, + wl_fixed_to_int(x) * wl_data.current_output.scale, + wl_fixed_to_int(y) * wl_data.current_output.scale, }; - memcpy (&wl_data.touch.points[id], - &raw_event, - sizeof (struct wpe_input_touch_event_raw)); + memcpy(&wl_data.touch.points[id], &raw_event, sizeof(struct wpe_input_touch_event_raw)); - if (popup_data.wl_surface) { - if (wl_data.touch.surface == popup_data.wl_surface) { - cog_popup_menu_handle_event (popup_data.popup_menu, - COG_POPUP_MENU_EVENT_STATE_PRESSED, - raw_event.x, raw_event.y); - update_popup (); + if (popup_data.shell_context->wl_shell_data.wl_surface) { + if (wl_data.touch.surface == popup_data.shell_context->wl_shell_data.wl_surface) { + cog_popup_menu_handle_event(popup_data.popup_menu, COG_POPUP_MENU_EVENT_STATE_PRESSED, raw_event.x, + raw_event.y); + update_popup(); return; } else - destroy_popup (); + destroy_popup(); } - struct wpe_input_touch_event event = { - wl_data.touch.points, - 10, - raw_event.type, - raw_event.id, - raw_event.time - }; + struct wpe_input_touch_event event = {wl_data.touch.points, 10, raw_event.type, raw_event.id, raw_event.time}; - wpe_view_backend_dispatch_touch_event (wpe_view_data.backend, &event); + wpe_view_backend_dispatch_touch_event(wpe_view_data.backend, &event); } static void -touch_on_up (void *data, - struct wl_touch *touch, - uint32_t serial, - uint32_t time, - int32_t id) +touch_on_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, int32_t id) { struct wl_surface *target_surface = wl_data.touch.surface; wl_data.touch.surface = NULL; @@ -1357,23 +1591,16 @@ touch_on_up (void *data, return; struct wpe_input_touch_event_raw raw_event = { - wpe_input_touch_event_type_up, - time, - id, - wl_data.touch.points[id].x, - wl_data.touch.points[id].y, + wpe_input_touch_event_type_up, time, id, wl_data.touch.points[id].x, wl_data.touch.points[id].y, }; - if (popup_data.wl_surface) { - if (target_surface == popup_data.wl_surface) { - cog_popup_menu_handle_event (popup_data.popup_menu, - COG_POPUP_MENU_EVENT_STATE_RELEASED, - raw_event.x, raw_event.y); - update_popup (); + if (popup_data.shell_context->wl_shell_data.wl_surface) { + if (target_surface == popup_data.shell_context->wl_shell_data.wl_surface) { + cog_popup_menu_handle_event(popup_data.popup_menu, COG_POPUP_MENU_EVENT_STATE_RELEASED, raw_event.x, + raw_event.y); + update_popup(); - memset (&wl_data.touch.points[id], - 0x00, - sizeof (struct wpe_input_touch_event_raw)); + memset(&wl_data.touch.points[id], 0x00, sizeof(struct wpe_input_touch_event_raw)); return; } } @@ -1563,25 +1790,20 @@ on_presentation_feedback_discarded (void *data, struct wp_presentation_feedback static const struct wp_presentation_feedback_listener presentation_feedback_listener = { .sync_output = on_presentation_feedback_sync_output, .presented = on_presentation_feedback_presented, - .discarded = on_presentation_feedback_discarded -}; + .discarded = on_presentation_feedback_discarded}; static void -request_frame (void) +request_frame(void) { if (wpe_view_data.frame_callback == NULL) { - wpe_view_data.frame_callback = wl_surface_frame (win_data.wl_surface); - wl_callback_add_listener (wpe_view_data.frame_callback, - &frame_listener, - NULL); + wpe_view_data.frame_callback = wl_surface_frame(win_data.shell_context->wl_shell_data.wl_surface); + wl_callback_add_listener(wpe_view_data.frame_callback, &frame_listener, NULL); } if (wl_data.presentation != NULL) { - struct wp_presentation_feedback *presentation_feedback = wp_presentation_feedback (wl_data.presentation, - win_data.wl_surface); - wp_presentation_feedback_add_listener (presentation_feedback, - &presentation_feedback_listener, - NULL); + struct wp_presentation_feedback *presentation_feedback = + wp_presentation_feedback(wl_data.presentation, win_data.shell_context->wl_shell_data.wl_surface); + wp_presentation_feedback_add_listener(presentation_feedback, &presentation_feedback_listener, NULL); } } @@ -1637,37 +1859,34 @@ on_export_wl_egl_image(void *data, struct wpe_fdo_egl_exported_image *image) if (wpe_view_data.should_update_opaque_region) { wpe_view_data.should_update_opaque_region = false; if (win_data.is_fullscreen) { - struct wl_region *region = - wl_compositor_create_region (wl_data.compositor); - wl_region_add (region, 0, 0, win_data.width, win_data.height); - wl_surface_set_opaque_region (win_data.wl_surface, region); - wl_region_destroy (region); + struct wl_region *region = wl_compositor_create_region(wl_data.compositor); + wl_region_add(region, 0, 0, win_data.width, win_data.height); + wl_surface_set_opaque_region(win_data.shell_context->wl_shell_data.wl_surface, region); + wl_region_destroy(region); } else { - wl_surface_set_opaque_region (win_data.wl_surface, NULL); + wl_surface_set_opaque_region(win_data.shell_context->wl_shell_data.wl_surface, NULL); } } - static PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL - s_eglCreateWaylandBufferFromImageWL; + static PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL s_eglCreateWaylandBufferFromImageWL; if (s_eglCreateWaylandBufferFromImageWL == NULL) { - s_eglCreateWaylandBufferFromImageWL = (PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) - load_egl_proc_address ("eglCreateWaylandBufferFromImageWL"); - g_assert (s_eglCreateWaylandBufferFromImageWL); + s_eglCreateWaylandBufferFromImageWL = + (PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) load_egl_proc_address("eglCreateWaylandBufferFromImageWL"); + g_assert(s_eglCreateWaylandBufferFromImageWL); } - wpe_view_data.buffer = s_eglCreateWaylandBufferFromImageWL (egl_data.display, wpe_fdo_egl_exported_image_get_egl_image (wpe_view_data.image)); - g_assert (wpe_view_data.buffer); + wpe_view_data.buffer = s_eglCreateWaylandBufferFromImageWL( + egl_data.display, wpe_fdo_egl_exported_image_get_egl_image(wpe_view_data.image)); + g_assert(wpe_view_data.buffer); wl_buffer_add_listener(wpe_view_data.buffer, &buffer_listener, image); - wl_surface_attach (win_data.wl_surface, wpe_view_data.buffer, 0, 0); - wl_surface_damage (win_data.wl_surface, - 0, 0, - win_data.width * wl_data.current_output.scale, - win_data.height * wl_data.current_output.scale); + wl_surface_attach(win_data.shell_context->wl_shell_data.wl_surface, wpe_view_data.buffer, 0, 0); + wl_surface_damage(win_data.shell_context->wl_shell_data.wl_surface, 0, 0, + win_data.width * wl_data.current_output.scale, win_data.height * wl_data.current_output.scale); - request_frame (); + request_frame(); - wl_surface_commit (win_data.wl_surface); + wl_surface_commit(win_data.shell_context->wl_shell_data.wl_surface); if (win_data.is_resizing_fullscreen && cog_wl_does_image_match_win_size(image)) cog_wl_fullscreen_image_ready(); @@ -1794,12 +2013,12 @@ on_export_shm_buffer (void* data, struct wpe_fdo_shm_exported_buffer* exported_b } buffer->exported_buffer = exported_buffer; - shm_buffer_copy_contents (buffer, exported_shm_buffer); + shm_buffer_copy_contents(buffer, exported_shm_buffer); - wl_surface_attach (win_data.wl_surface, buffer->buffer, 0, 0); - wl_surface_damage(win_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); - request_frame (); - wl_surface_commit (win_data.wl_surface); + wl_surface_attach(win_data.shell_context->wl_shell_data.wl_surface, buffer->buffer, 0, 0); + wl_surface_damage(win_data.shell_context->wl_shell_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); + request_frame(); + wl_surface_commit(win_data.shell_context->wl_shell_data.wl_surface); } #endif @@ -1888,35 +2107,36 @@ on_video_plane_display_dmabuf_receiver_handle_dmabuf (void* data, struct wpe_vid buffer->y = y; buffer->width = width; buffer->height = height; - zwp_linux_buffer_params_v1_add_listener (params, ¶ms_listener, buffer); + zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, buffer); - buffer->buffer = zwp_linux_buffer_params_v1_create_immed (params, buffer->width, buffer->height, VIDEO_BUFFER_FORMAT, 0); - zwp_linux_buffer_params_v1_destroy (params); + buffer->buffer = + zwp_linux_buffer_params_v1_create_immed(params, buffer->width, buffer->height, VIDEO_BUFFER_FORMAT, 0); + zwp_linux_buffer_params_v1_destroy(params); buffer->dmabuf_export = dmabuf_export; - wl_buffer_add_listener (buffer->buffer, &dmabuf_buffer_listener, buffer); + wl_buffer_add_listener(buffer->buffer, &dmabuf_buffer_listener, buffer); - wl_surface_attach (surf->wl_surface, buffer->buffer, 0, 0); - wl_surface_damage (surf->wl_surface, 0, 0, buffer->width, buffer->height); + wl_surface_attach(surf->wl_surface, buffer->buffer, 0, 0); + wl_surface_damage(surf->wl_surface, 0, 0, buffer->width, buffer->height); - struct wl_callback *callback = wl_surface_frame (surf->wl_surface); - wl_callback_add_listener (callback, &dmabuf_frame_listener, NULL); + struct wl_callback *callback = wl_surface_frame(surf->wl_surface); + wl_callback_add_listener(callback, &dmabuf_frame_listener, NULL); if (!surf->wl_subsurface) { - surf->wl_subsurface = wl_subcompositor_get_subsurface (wl_data.subcompositor, - surf->wl_surface, - win_data.wl_surface); - wl_subsurface_set_sync (surf->wl_subsurface); + surf->wl_subsurface = wl_subcompositor_get_subsurface(wl_data.subcompositor, + surf->wl_surface, + win_data.shell_context->wl_shell_data.wl_surface); + wl_subsurface_set_sync(surf->wl_subsurface); } - wl_subsurface_set_position (surf->wl_subsurface, buffer->x, buffer->y); - wl_surface_commit (surf->wl_surface); + wl_subsurface_set_position(surf->wl_subsurface, buffer->x, buffer->y); + wl_surface_commit(surf->wl_surface); } static void -on_video_plane_display_dmabuf_receiver_end_of_stream (void* data, uint32_t id) +on_video_plane_display_dmabuf_receiver_end_of_stream(void *data, uint32_t id) { - g_hash_table_remove (win_data.video_surfaces, GUINT_TO_POINTER (id)); + g_hash_table_remove(win_data.video_surfaces, GUINT_TO_POINTER(id)); } static const struct wpe_video_plane_display_dmabuf_receiver video_plane_display_dmabuf_receiver = { @@ -1968,24 +2188,18 @@ init_wayland (GError **error) } static void -clear_wayland (void) +clear_wayland(void) { + win_data.shell_context->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,108 +2339,44 @@ 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.shell_context->wl_shell_data.wl_surface = wl_compositor_create_surface(wl_data.compositor); + g_assert(win_data.shell_context->wl_shell_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.shell_context->wl_shell_data.wl_surface, &surface_listener, NULL); + win_data.shell_context->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; - } + win_data.shell_context->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; - } + win_data.shell_context->functions.maximize_surface(); } return TRUE; } static void -destroy_window (void) +destroy_window(void) { - g_clear_pointer (&win_data.xdg_toplevel, xdg_toplevel_destroy); - g_clear_pointer (&win_data.xdg_surface, xdg_surface_destroy); - g_clear_pointer (&win_data.shell_surface, wl_shell_surface_destroy); - g_clear_pointer (&win_data.wl_surface, wl_surface_destroy); + g_clear_pointer(&win_data.shell_context->xdg_shell_data.xdg_toplevel, xdg_toplevel_destroy); + g_clear_pointer(&win_data.shell_context->xdg_shell_data.xdg_surface, xdg_surface_destroy); + g_clear_pointer(&win_data.shell_context->wl_shell_data.shell_surface, wl_shell_surface_destroy); + g_clear_pointer(&win_data.shell_context->wl_shell_data.wl_surface, wl_surface_destroy); #if COG_ENABLE_WESTON_DIRECT_DISPLAY - g_clear_pointer (&win_data.video_surfaces, g_hash_table_destroy); + g_clear_pointer(&win_data.video_surfaces, g_hash_table_destroy); #endif } @@ -2236,124 +2386,76 @@ 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); - - 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); - } 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); + popup_data.height = cog_popup_menu_get_height_for_option_menu(option_menu); - display_popup(); - } + 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.shell_context->wl_shell_data.wl_surface = wl_compositor_create_surface(wl_data.compositor); + g_assert(popup_data.shell_context->wl_shell_data.wl_surface); + wl_surface_set_buffer_scale(popup_data.shell_context->wl_shell_data.wl_surface, wl_data.current_output.scale); + win_data.shell_context->functions.create_popup(); } static void -destroy_popup (void) +destroy_popup(void) { if (popup_data.option_menu == NULL) return; - webkit_option_menu_close (popup_data.option_menu); - g_clear_pointer (&popup_data.popup_menu, cog_popup_menu_destroy); - g_clear_object (&popup_data.option_menu); + webkit_option_menu_close(popup_data.option_menu); + g_clear_pointer(&popup_data.popup_menu, cog_popup_menu_destroy); + g_clear_object(&popup_data.option_menu); - g_clear_pointer (&popup_data.xdg_popup, xdg_popup_destroy); - g_clear_pointer (&popup_data.xdg_surface, xdg_surface_destroy); - g_clear_pointer (&popup_data.xdg_positioner, xdg_positioner_destroy); - g_clear_pointer (&popup_data.shell_surface, wl_shell_surface_destroy); - g_clear_pointer (&popup_data.wl_surface, wl_surface_destroy); + g_clear_pointer(&popup_data.shell_context->xdg_shell_data.xdg_popup, xdg_popup_destroy); + g_clear_pointer(&popup_data.shell_context->xdg_shell_data.xdg_surface, xdg_surface_destroy); + g_clear_pointer(&popup_data.xdg_positioner, xdg_positioner_destroy); + g_clear_pointer(&popup_data.shell_surface, wl_shell_surface_destroy); + g_clear_pointer(&popup_data.shell_context->wl_shell_data.wl_surface, wl_surface_destroy); popup_data.configured = false; } static void -display_popup (void) +display_popup(void) { - struct wl_buffer *buffer = cog_popup_menu_get_buffer (popup_data.popup_menu); - wl_surface_attach (popup_data.wl_surface, buffer, 0, 0); - wl_surface_damage (popup_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit (popup_data.wl_surface); + struct wl_buffer *buffer = cog_popup_menu_get_buffer(popup_data.popup_menu); + wl_surface_attach(popup_data.shell_context->wl_shell_data.wl_surface, buffer, 0, 0); + wl_surface_damage(popup_data.shell_context->wl_shell_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(popup_data.shell_context->wl_shell_data.wl_surface); } static void -update_popup (void) +update_popup(void) { - int selected_index; - bool has_final_selection = cog_popup_menu_has_final_selection (popup_data.popup_menu, - &selected_index); + int selected_index; + bool has_final_selection = cog_popup_menu_has_final_selection(popup_data.popup_menu, &selected_index); if (has_final_selection) { if (selected_index != -1) - webkit_option_menu_activate_item (popup_data.option_menu, selected_index); - destroy_popup (); + webkit_option_menu_activate_item(popup_data.option_menu, selected_index); + destroy_popup(); return; } - struct wl_buffer *buffer = cog_popup_menu_get_buffer (popup_data.popup_menu); - wl_surface_attach (popup_data.wl_surface, buffer, 0, 0); - wl_surface_damage (popup_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_commit (popup_data.wl_surface); + struct wl_buffer *buffer = cog_popup_menu_get_buffer(popup_data.popup_menu); + wl_surface_attach(popup_data.shell_context->wl_shell_data.wl_surface, buffer, 0, 0); + wl_surface_damage(popup_data.shell_context->wl_shell_data.wl_surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(popup_data.shell_context->wl_shell_data.wl_surface); } static gboolean -init_input (GError **error) +init_input(GError **error) { if (wl_data.seat != NULL) { - wl_seat_add_listener (wl_data.seat, &seat_listener, NULL); - - xkb_data.context = xkb_context_new (XKB_CONTEXT_NO_FLAGS); - g_assert (xkb_data.context); - xkb_data.compose_table = - xkb_compose_table_new_from_locale (xkb_data.context, - setlocale (LC_CTYPE, NULL), - XKB_COMPOSE_COMPILE_NO_FLAGS); + wl_seat_add_listener(wl_data.seat, &seat_listener, NULL); + + xkb_data.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + g_assert(xkb_data.context); + xkb_data.compose_table = xkb_compose_table_new_from_locale(xkb_data.context, + setlocale(LC_CTYPE, NULL), + XKB_COMPOSE_COMPILE_NO_FLAGS); if (xkb_data.compose_table != NULL) { - xkb_data.compose_state = - xkb_compose_state_new (xkb_data.compose_table, - XKB_COMPOSE_STATE_NO_FLAGS); + xkb_data.compose_state = xkb_compose_state_new(xkb_data.compose_table, XKB_COMPOSE_STATE_NO_FLAGS); } if (wl_data.text_input_manager != NULL) { @@ -2363,7 +2465,8 @@ init_input (GError **error) } else if (wl_data.text_input_manager_v1 != NULL) { struct zwp_text_input_v1 *text_input = zwp_text_input_manager_v1_create_text_input(wl_data.text_input_manager_v1); - cog_im_context_wl_v1_set_text_input(text_input, wl_data.seat, win_data.wl_surface); + cog_im_context_wl_v1_set_text_input(text_input, wl_data.seat, + win_data.shell_context->wl_shell_data.wl_surface); } }