diff --git a/cog.c b/cog.c index 2fdc7b21..ed83b6ce 100644 --- a/cog.c +++ b/cog.c @@ -444,6 +444,18 @@ on_create_view (CogShell *shell, void *user_data G_GNUC_UNUSED) return g_steal_pointer (&web_view); } +static void +on_action_resize (G_GNUC_UNUSED GAction *action, + GVariant *param, + CogLauncher *launcher) +{ + g_debug ("%s: Platform = %p", __func__, s_options.platform); + g_return_if_fail (g_variant_is_of_type (param, G_VARIANT_TYPE_STRING)); + + if (s_options.platform) { + cog_platform_resize (s_options.platform, g_variant_get_string (param, NULL)); + } +} int main (int argc, char *argv[]) @@ -462,6 +474,7 @@ main (int argc, char *argv[]) cog_launcher_add_web_settings_option_entries (COG_LAUNCHER (app)); cog_launcher_add_web_cookies_option_entries (COG_LAUNCHER (app)); cog_launcher_add_web_permissions_option_entries (COG_LAUNCHER (app)); + cog_launcher_add_action (COG_LAUNCHER(app), "resize", on_action_resize, G_VARIANT_TYPE_STRING); g_signal_connect (app, "shutdown", G_CALLBACK (on_shutdown), NULL); g_signal_connect (app, "handle-local-options", diff --git a/cogctl.c b/cogctl.c index f20ae7f9..a0eb86a8 100644 --- a/cogctl.c +++ b/cogctl.c @@ -100,8 +100,8 @@ cmd_check_simple_help (const char *name, int needed_argc, int *argc, char ***arg NULL); g_autoptr(GError) error = NULL; - if (!g_option_context_parse (option_context, argc, argv, &error) || *argc > (1 + needed_argc)) { - g_printerr ("%s: %s\n", name, error ? error->message : "No arguments expected"); + if (!g_option_context_parse (option_context, argc, argv, &error) || *argc != (1 + needed_argc)) { + g_printerr ("%s: %s\n", name, error ? error->message : g_strdup_printf("%d arguments expected", needed_argc)); exit (EXIT_FAILURE); } } @@ -187,6 +187,27 @@ cmd_open (const char *name, return EXIT_SUCCESS; } +static int +cmd_resize (const char *name, + G_GNUC_UNUSED const void *data, + int argc, + char **argv) +{ + cmd_check_simple_help ("resize window", 1, &argc, &argv); + + g_autoptr(GVariantBuilder) param = + g_variant_builder_new (G_VARIANT_TYPE ("av")); + g_variant_builder_add (param, "v", g_variant_new_string (argv[1])); + GVariant *params = g_variant_new ("(sava{sv})", "resize", param, NULL); + + g_autoptr(GError) error = NULL; + if (!call_method (GTK_ACTIONS_ACTIVATE, params, &error)) { + g_printerr ("%s\n", error->message); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + static int cmd_ping (const char *name, @@ -299,6 +320,11 @@ cmd_find_by_name (const char *name) .desc = "Exit the application", .handler = cmd_generic_no_args, }, + { + .name = "resize", + .desc = "Resize the window", + .handler = cmd_resize, + }, { .name = "reload", .desc = "Reload the current page", diff --git a/core/cog-launcher.c b/core/cog-launcher.c index 3920b1c2..f42e109a 100644 --- a/core/cog-launcher.c +++ b/core/cog-launcher.c @@ -132,7 +132,7 @@ on_notify_web_view (CogShell *shell, GParamSpec * arg G_GNUC_UNUSED, CogLauncher g_signal_connect (web_view, "permission-request", G_CALLBACK (on_permission_request), launcher); } -static void +void cog_launcher_add_action (CogLauncher *launcher, const char *name, void (*callback) (GAction*, GVariant*, CogLauncher*), diff --git a/core/cog-launcher.h b/core/cog-launcher.h index f3236719..5b5ffd9d 100644 --- a/core/cog-launcher.h +++ b/core/cog-launcher.h @@ -36,6 +36,10 @@ CogShell *cog_launcher_get_shell (CogLauncher *launcher); void cog_launcher_add_web_settings_option_entries (CogLauncher *launcher); void cog_launcher_add_web_cookies_option_entries (CogLauncher *launcher); void cog_launcher_add_web_permissions_option_entries (CogLauncher *launcher); +void cog_launcher_add_action (CogLauncher *launcher, + const char *name, + void (*callback) (GAction*, GVariant*, CogLauncher*), + const GVariantType *param_type); G_END_DECLS diff --git a/core/cog-platform.c b/core/cog-platform.c index 727d33c9..e986e08f 100644 --- a/core/cog-platform.c +++ b/core/cog-platform.c @@ -31,6 +31,8 @@ struct _CogPlatform { GError **error); void (*init_web_view) (CogPlatform *platform, WebKitWebView *view); + void (*resize) (CogPlatform *platform, + const char *params); WebKitInputMethodContext* (*create_im_context) (CogPlatform *platform); }; @@ -82,6 +84,8 @@ cog_platform_try_load (CogPlatform *platform, platform->init_web_view = dlsym (platform->so, "cog_platform_plugin_init_web_view"); + platform->resize = dlsym (platform->so, + "cog_platform_plugin_resize"); platform->create_im_context = dlsym (platform->so, "cog_platform_plugin_create_im_context"); @@ -124,6 +128,15 @@ cog_platform_init_web_view (CogPlatform *platform, platform->init_web_view (platform, view); } +void +cog_platform_resize (CogPlatform *platform, const char *params) +{ + g_return_if_fail (platform != NULL); + + if (platform->resize) + platform->resize (platform, params); +} + WebKitInputMethodContext* cog_platform_create_im_context (CogPlatform *platform) { diff --git a/core/cog-platform.h b/core/cog-platform.h index 75024f55..da2739ad 100644 --- a/core/cog-platform.h +++ b/core/cog-platform.h @@ -53,6 +53,8 @@ WebKitWebViewBackend *cog_platform_get_view_backend (CogPlatform *platfor void cog_platform_init_web_view (CogPlatform *platform, WebKitWebView *view); +void cog_platform_resize (CogPlatform *platform, + const char *params); WebKitInputMethodContext *cog_platform_create_im_context (CogPlatform *platform); diff --git a/platform/fdo/cog-platform-fdo.c b/platform/fdo/cog-platform-fdo.c index c7e1eea2..028d58d7 100644 --- a/platform/fdo/cog-platform-fdo.c +++ b/platform/fdo/cog-platform-fdo.c @@ -226,6 +226,11 @@ static struct { struct egl_display *display; } egl_data; +typedef struct { + long w; + long h; +} rect_t; + static struct { struct wl_surface *wl_surface; @@ -239,6 +244,8 @@ static struct { uint32_t width; uint32_t height; + rect_t min_rect; + rect_t max_rect; bool is_fullscreen; bool is_maximized; @@ -246,6 +253,8 @@ static struct { } win_data = { .width = DEFAULT_WIDTH, .height = DEFAULT_HEIGHT, + .min_rect = {-1, -1}, + .max_rect = {-1, -1}, .is_fullscreen = false, .is_maximized = false, .should_resize_to_largest_output = false, @@ -396,24 +405,29 @@ static void display_popup (void); static void update_popup (void); static void destroy_popup (void); +// either size ("123") or min/size/max ("100:200:300") +// 0 = unset (no mix, max). +// -1 = do not set. static void -configure_surface_geometry (int32_t width, int32_t height) +parse_dim(const char *value, long *min, uint32_t *size, long *max) { - const char* env_var; - if (width == 0) { - env_var = g_getenv("COG_PLATFORM_FDO_VIEW_WIDTH"); - if (env_var != NULL) - width = (int32_t) g_ascii_strtod(env_var, NULL); - else - width = DEFAULT_WIDTH; - } - if (height == 0) { - env_var = g_getenv("COG_PLATFORM_FDO_VIEW_HEIGHT"); - if (env_var != NULL) - height = (int32_t) g_ascii_strtod(env_var, NULL); - else - height = DEFAULT_HEIGHT; + if (!value) + return; + + int count = sscanf(value, "%ld:%" SCNu32 ":%ld", min, size, max); + + if(count == 1) { + *size = *min; + *min = -1; + *max = -1; } +} + +static void +configure_surface_geometry (int32_t width, int32_t height) +{ + width = width ?: win_data.width ?: DEFAULT_WIDTH; + height = height ?: win_data.height ?: DEFAULT_HEIGHT; if (win_data.width != width || win_data.height != height) { g_debug("Configuring new size: %" PRId32 "x%" PRId32, width, height); @@ -429,6 +443,26 @@ resize_window (void) int32_t pixel_width = win_data.width * wl_data.current_output.scale; int32_t pixel_height = win_data.height * wl_data.current_output.scale; + rect_t min = win_data.min_rect; + if (min.w >= 0 && min.h >= 0) { + g_debug("Configuring min size: %ldx%ld", min.w, min.h); + if (wl_data.xdg_shell != NULL) { + xdg_toplevel_set_min_size (win_data.xdg_toplevel, min.w, min.h); + } else { + g_warning ("No available shell capable of settings min size."); + } + } + + rect_t max = win_data.max_rect; + if (max.w >= 0 && max.h >= 0) { + g_debug("Configuring max size: %ldx%ld", max.w, max.h); + if (wl_data.xdg_shell != NULL) { + xdg_toplevel_set_max_size (win_data.xdg_toplevel, max.w, max.h); + } else { + g_warning ("No available shell capable of settings max size."); + } + } + wpe_view_backend_dispatch_set_size (wpe_view_data.backend, win_data.width, win_data.height); @@ -2085,6 +2119,17 @@ create_window (GError **error) wl_surface_add_listener (win_data.wl_surface, &surface_listener, NULL); + // initialize requested window dimensions from environment + parse_dim(g_getenv("COG_PLATFORM_FDO_VIEW_WIDTH"), + &win_data.min_rect.w, + &win_data.width, + &win_data.max_rect.w); + + parse_dim(g_getenv("COG_PLATFORM_FDO_VIEW_HEIGHT"), + &win_data.min_rect.h, + &win_data.height, + &win_data.max_rect.h); + if (wl_data.xdg_shell != NULL) { win_data.xdg_surface = xdg_wm_base_get_xdg_surface (wl_data.xdg_shell, @@ -2512,6 +2557,32 @@ cog_platform_plugin_init_web_view (CogPlatform *platform, g_signal_connect (view, "show-option-menu", G_CALLBACK (on_show_option_menu), NULL); } +void +cog_platform_plugin_resize (CogPlatform *platform, + const char *size_spec) +{ + char w[100], h[100]; + errno = 0; + int count = sscanf(size_spec, "%99[0-9:]x%99[0-9:]", w, h); + if(count != 2) { + g_warning("Invalid size specification: %s (%d != 2)", size_spec, count); + return; + } + + parse_dim(w, + &win_data.min_rect.w, + &win_data.width, + &win_data.max_rect.w); + + parse_dim(h, + &win_data.min_rect.h, + &win_data.height, + &win_data.max_rect.h); + + configure_surface_geometry (0, 0); + resize_window (); +} + #if COG_IM_API_SUPPORTED WebKitInputMethodContext* cog_platform_plugin_create_im_context (CogPlatform *platform)