diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index fffb3d68a..ef84f5ff5 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -1717,6 +1717,85 @@ shell_set_view_fullscreen(struct shell_surface *shsurf) shsurf->state.lowered = false; } +/* parse app_id in weston.ini section output. it's like + * app_id=org.freedesktop.weston.simple-egl + */ +static bool +shell_output_parse_appid(struct shell_surface *shsurf, char *cur, + char *comma, const char *app_id) +{ + char *str = NULL; + size_t len; + + if (app_id == NULL) + return false; + + if (comma != NULL) + str = strndup(cur, comma-cur); + else + str = strdup(cur); + + if (str == NULL) + return false; + + len = strlen(app_id); + if (strncmp(str, app_id, len) == 0) { + free(str); + return true; + } + + free(str); + return false; +} + +static bool +shell_output_has_app_id(struct shell_output *shell_output, + struct shell_surface *shsurf, const char *app_id) +{ + char *cur, *comma = NULL; + bool has_app_id = false; + + if (!shell_output->app_ids) + return false; + + cur = shell_output->app_ids; + + while ((cur = strstr(cur, app_id))) { + comma = strchr(cur, ','); + has_app_id = shell_output_parse_appid(shsurf, cur, comma, app_id); + if (has_app_id) + return true; + + if (comma != NULL) + cur = comma; + else + break; + } + + return false; +} + +static struct weston_output * +shell_surface_find_assign_output(struct shell_surface *shsurf) +{ + struct shell_output *shell_output; + const char *app_id; + + /* Check if we have a designated output for this app. */ + app_id = weston_desktop_surface_get_app_id(shsurf->desktop_surface); + if (app_id) { + wl_list_for_each(shell_output, &shsurf->shell->output_list, link) { + if (shell_output_has_app_id(shell_output, shsurf, app_id)) { + shsurf->appid_output_assigned = true; + weston_log("%s app-id %s at output %s\n", __func__, app_id, shell_output->output->name); + return shell_output->output; + } + } + } + + return NULL; +} + static void desktop_shell_destroy_seat(struct shell_seat *shseat) { @@ -1916,6 +1995,7 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface, struct wl_client *wl_client = weston_desktop_client_get_client(client); struct weston_view *view; + struct weston_output *output = NULL; struct shell_surface *shsurf; struct weston_surface *surface = weston_desktop_surface_get_surface(desktop_surface); @@ -1941,9 +2021,12 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface, shsurf->desktop_surface = desktop_surface; shsurf->view = view; shsurf->fullscreen.black_view = NULL; + shsurf->appid_output_assigned = false; - shell_surface_set_output( - shsurf, weston_shell_utils_get_default_output(shsurf->shell->compositor)); + output = shell_surface_find_assign_output(shsurf); + if (!output) + output = weston_shell_utils_get_default_output(shsurf->shell->compositor); + shell_surface_set_output(shsurf, output); wl_signal_init(&shsurf->destroy_signal); @@ -2151,6 +2234,8 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface, weston_desktop_surface_get_user_data(desktop_surface); struct weston_surface *surface = weston_desktop_surface_get_surface(desktop_surface); + const char *app_id = + weston_desktop_surface_get_app_id(desktop_surface); struct weston_view *view = shsurf->view; struct desktop_shell *shell = data; bool was_fullscreen; @@ -2167,6 +2252,19 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface, return; } + if (!shsurf->appid_output_assigned && app_id) { + struct weston_output *output = NULL; + + /* reset previous output being set in _added() as the output is + * being cached */ + output = shell_surface_find_assign_output(shsurf); + if (output) { + shsurf->output = NULL; + shell_surface_set_output(shsurf, output); + } + shsurf->appid_output_assigned = true; + } + was_fullscreen = shsurf->state.fullscreen; was_maximized = shsurf->state.maximized; @@ -4412,6 +4510,7 @@ shell_output_destroy(struct shell_output *shell_output) } wl_list_remove(&shell_output->destroy_listener.link); wl_list_remove(&shell_output->link); + free(shell_output->app_ids); free(shell_output); } @@ -4477,6 +4576,21 @@ handle_output_resized(struct wl_listener *listener, void *data) shell_resize_surface_to_output(shell, sh_output->panel_surface, output); } +static void +desktop_shell_output_config(struct shell_output *shell_output) +{ + struct weston_config *wc = wet_get_config(shell_output->shell->compositor); + struct weston_config_section *section = + weston_config_get_section(wc, "output", "name", shell_output->output->name); + + assert(shell_output->app_ids == NULL); + + if (section) { + weston_config_section_get_string(section, "app-ids", + &shell_output->app_ids, NULL); + } +} + static void create_shell_output(struct desktop_shell *shell, struct weston_output *output) @@ -4496,6 +4610,8 @@ create_shell_output(struct desktop_shell *shell, &shell_output->destroy_listener); wl_list_insert(shell->output_list.prev, &shell_output->link); + desktop_shell_output_config(shell_output); + if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1) shell_for_each_layer(shell, shell_output_changed_move_layer, NULL); diff --git a/desktop-shell/shell.h b/desktop-shell/shell.h index 524f8f32e..6fe936ea4 100644 --- a/desktop-shell/shell.h +++ b/desktop-shell/shell.h @@ -129,6 +129,8 @@ struct shell_surface { struct weston_coord_global pos; } xwayland; + bool appid_output_assigned; + int focus_count; bool destroying; @@ -233,6 +235,7 @@ struct shell_output { struct wl_listener destroy_listener; struct wl_list link; + char *app_ids; struct weston_surface *panel_surface; struct weston_view *panel_view; struct wl_listener panel_surface_listener;