struct desktop {
struct display *display;
struct desktop_shell *shell;
+ uint32_t interface_version;
struct unlock_dialog *unlock_dialog;
struct task unlock_task;
struct wl_list outputs;
struct widget *grab_widget;
enum cursor_type grab_cursor;
+
+ int painted;
};
struct surface {
struct widget *widget;
struct wl_list launcher_list;
struct panel_clock *clock;
+ int painted;
};
struct background {
struct surface base;
struct window *window;
struct widget *widget;
+ int painted;
};
struct output {
x - 10, y - 10, menu_func, entries, 4);
}
+static int
+is_desktop_painted(struct desktop *desktop)
+{
+ struct output *output;
+
+ wl_list_for_each(output, &desktop->outputs, link) {
+ if (output->panel && !output->panel->painted)
+ return 0;
+ if (output->background && !output->background->painted)
+ return 0;
+ }
+
+ return 1;
+}
+
+static void
+check_desktop_ready(struct window *window)
+{
+ struct display *display;
+ struct desktop *desktop;
+
+ display = window_get_display(window);
+ desktop = display_get_user_data(display);
+
+ if (!desktop->painted && is_desktop_painted(desktop)) {
+ desktop->painted = 1;
+
+ if (desktop->interface_version >= 2)
+ desktop_shell_desktop_ready(desktop->shell);
+ }
+}
+
static void
panel_launcher_activate(struct panel_launcher *widget)
{
cairo_destroy(cr);
surface = window_get_surface(panel->window);
cairo_surface_destroy(surface);
+ panel->painted = 1;
+ check_desktop_ready(panel->window);
}
static int
allocation.width, allocation.height);
wl_surface_set_opaque_region(window_get_wl_surface(background->window), opaque);
wl_region_destroy(opaque);
+
+ background->painted = 1;
+ check_desktop_ready(background->window);
}
static void
struct desktop *desktop = data;
if (!strcmp(interface, "desktop_shell")) {
+ desktop->interface_version = (version < 2) ? version : 2;
desktop->shell = display_bind(desktop->display,
- id, &desktop_shell_interface, 1);
+ id, &desktop_shell_interface,
+ desktop->interface_version);
desktop_shell_add_listener(desktop->shell, &listener, desktop);
} else if (!strcmp(interface, "wl_output")) {
create_output(desktop, id);
struct weston_surface *surface;
struct weston_surface_animation *animation;
enum fade_type type;
+ struct wl_event_source *startup_timer;
} fade;
uint32_t binding_modifier;
static void
surface_rotate(struct shell_surface *surface, struct weston_seat *seat);
+static void
+shell_fade_startup(struct desktop_shell *shell);
+
static bool
shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
{
shell->grab_surface = surface_resource->data;
}
+static void
+desktop_shell_desktop_ready(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ struct desktop_shell *shell = resource->data;
+
+ shell_fade_startup(shell);
+}
+
static const struct desktop_shell_interface desktop_shell_implementation = {
desktop_shell_set_background,
desktop_shell_set_panel,
desktop_shell_set_lock_surface,
desktop_shell_unlock,
- desktop_shell_set_grab_surface
+ desktop_shell_set_grab_surface,
+ desktop_shell_desktop_ready
};
static enum shell_surface_type
}
}
-static void
-shell_fade(struct desktop_shell *shell, enum fade_type type)
+static struct weston_surface *
+shell_fade_create_surface(struct desktop_shell *shell)
{
struct weston_compositor *compositor = shell->compositor;
struct weston_surface *surface;
+
+ surface = weston_surface_create(compositor);
+ if (!surface)
+ return NULL;
+
+ weston_surface_configure(surface, 0, 0, 8192, 8192);
+ weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
+ wl_list_insert(&compositor->fade_layer.surface_list,
+ &surface->layer_link);
+ pixman_region32_init(&surface->input);
+
+ return surface;
+}
+
+static void
+shell_fade(struct desktop_shell *shell, enum fade_type type)
+{
float tint;
switch (type) {
shell->fade.type = type;
if (shell->fade.surface == NULL) {
- surface = weston_surface_create(compositor);
- if (!surface)
+ shell->fade.surface = shell_fade_create_surface(shell);
+ if (!shell->fade.surface)
return;
- weston_surface_configure(surface, 0, 0, 8192, 8192);
- weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
- surface->alpha = 1.0 - tint;
- wl_list_insert(&compositor->fade_layer.surface_list,
- &surface->layer_link);
- weston_surface_update_transform(surface);
- shell->fade.surface = surface;
- pixman_region32_init(&surface->input);
+ shell->fade.surface->alpha = 1.0 - tint;
+ weston_surface_update_transform(shell->fade.surface);
}
if (shell->fade.animation)
}
static void
+do_shell_fade_startup(void *data)
+{
+ struct desktop_shell *shell = data;
+
+ shell_fade(shell, FADE_IN);
+}
+
+static void
+shell_fade_startup(struct desktop_shell *shell)
+{
+ struct wl_event_loop *loop;
+
+ if (!shell->fade.startup_timer)
+ return;
+
+ wl_event_source_remove(shell->fade.startup_timer);
+ shell->fade.startup_timer = NULL;
+
+ loop = wl_display_get_event_loop(shell->compositor->wl_display);
+ wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
+}
+
+static int
+fade_startup_timeout(void *data)
+{
+ struct desktop_shell *shell = data;
+
+ shell_fade_startup(shell);
+ return 0;
+}
+
+static void
+shell_fade_init(struct desktop_shell *shell)
+{
+ /* Make compositor output all black, and wait for the desktop-shell
+ * client to signal it is ready, then fade in. The timer triggers a
+ * fade-in, in case the desktop-shell client takes too long.
+ */
+
+ struct wl_event_loop *loop;
+
+ if (shell->fade.surface != NULL) {
+ weston_log("%s: warning: fade surface already exists\n",
+ __func__);
+ return;
+ }
+
+ shell->fade.surface = shell_fade_create_surface(shell);
+ if (!shell->fade.surface)
+ return;
+
+ weston_surface_update_transform(shell->fade.surface);
+ weston_surface_damage(shell->fade.surface);
+
+ loop = wl_display_get_event_loop(shell->compositor->wl_display);
+ shell->fade.startup_timer =
+ wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
+ wl_event_source_timer_update(shell->fade.startup_timer, 15000);
+}
+
+static void
idle_handler(struct wl_listener *listener, void *data)
{
struct desktop_shell *shell =
weston_log("weston-desktop-shell died, respawning...\n");
launch_desktop_shell_process(shell);
+ shell_fade_startup(shell);
}
static void
if (client == shell->child.client) {
resource->destroy = unbind_desktop_shell;
shell->child.desktop_shell = resource;
+
+ if (version < 2)
+ shell_fade_startup(shell);
+
return;
}
shell_add_bindings(ec, shell);
- shell_fade(shell, FADE_IN);
+ shell_fade_init(shell);
return 0;
}