weston_view_animation_frame_func_t reset;
weston_view_animation_done_func_t done;
void *data;
+ void *private;
};
-static void
+WL_EXPORT void
weston_view_animation_destroy(struct weston_view_animation *animation)
{
wl_list_remove(&animation->animation.link);
weston_view_animation_frame_func_t frame,
weston_view_animation_frame_func_t reset,
weston_view_animation_done_func_t done,
- void *data)
+ void *data,
+ void *private)
{
struct weston_view_animation *animation;
animation->data = data;
animation->start = start;
animation->stop = stop;
+ animation->private = private;
weston_matrix_init(&animation->transform.matrix);
wl_list_insert(&view->geometry.transformation_list,
&animation->transform.link);
zoom = weston_view_animation_run(view, start, stop,
zoom_frame, reset_alpha,
- done, data);
+ done, data, NULL);
weston_spring_init(&zoom->spring, 300.0, start, stop);
zoom->spring.friction = 1400;
fade = weston_view_animation_run(view, 0, end,
fade_frame, reset_alpha,
- done, data);
+ done, data, NULL);
weston_spring_init(&fade->spring, k, start, end);
}
static void
+stable_fade_frame(struct weston_view_animation *animation)
+{
+ struct weston_view *back_view;
+
+ if (animation->spring.current > 0.999)
+ animation->view->alpha = 1;
+ else if (animation->spring.current < 0.001 )
+ animation->view->alpha = 0;
+ else
+ animation->view->alpha = animation->spring.current;
+
+ back_view = (struct weston_view *) animation->private;
+ back_view->alpha =
+ (animation->spring.target - animation->view->alpha) /
+ (1.0 - animation->view->alpha);
+ weston_view_geometry_dirty(back_view);
+}
+
+WL_EXPORT struct weston_view_animation *
+weston_stable_fade_run(struct weston_view *front_view, float start,
+ struct weston_view *back_view, float end,
+ weston_view_animation_done_func_t done, void *data)
+{
+ struct weston_view_animation *fade;
+
+ fade = weston_view_animation_run(front_view, 0, 0,
+ stable_fade_frame, NULL,
+ done, data, back_view);
+
+
+ weston_spring_init(&fade->spring, 400, start, end);
+ fade->spring.friction = 1150;
+
+ front_view->alpha = start;
+ back_view->alpha = end;
+
+ return fade;
+}
+
+static void
slide_frame(struct weston_view_animation *animation)
{
float scale;
animation = weston_view_animation_run(view, start, stop,
slide_frame, NULL, done,
- data);
+ data, NULL);
if (!animation)
return NULL;
ANIMATION_NONE,
ANIMATION_ZOOM,
- ANIMATION_FADE
+ ANIMATION_FADE,
+ ANIMATION_DIM_LAYER,
};
enum fade_type {
struct wl_listener surface_destroy_listener;
};
+struct focus_surface {
+ struct weston_surface *surface;
+ struct weston_view *view;
+ struct weston_transform workspace_transform;
+};
+
struct workspace {
struct weston_layer layer;
struct wl_list focus_list;
struct wl_listener seat_destroyed_listener;
+
+ struct focus_surface *fsurf_front;
+ struct focus_surface *fsurf_back;
+ struct weston_view_animation *focus_animation;
};
struct input_panel_surface {
uint32_t binding_modifier;
enum animation_type win_animation_type;
enum animation_type startup_animation_type;
+ enum animation_type focus_animation_type;
struct wl_listener output_create_listener;
struct wl_list output_list;
return ANIMATION_ZOOM;
else if (!strcmp("fade", animation))
return ANIMATION_FADE;
+ else if (!strcmp("dim-layer", animation))
+ return ANIMATION_DIM_LAYER;
else
return ANIMATION_NONE;
}
free(s);
if (shell->startup_animation_type == ANIMATION_ZOOM)
shell->startup_animation_type = ANIMATION_NONE;
-
+ weston_config_section_get_string(section, "focus-animation", &s, "none");
+ shell->focus_animation_type = get_animation_type(s);
+ free(s);
weston_config_section_get_uint(section, "num-workspaces",
&shell->workspaces.num,
DEFAULT_NUM_WORKSPACES);
}
+static struct weston_output *
+get_default_output(struct weston_compositor *compositor)
+{
+ return container_of(compositor->output_list.next,
+ struct weston_output, link);
+}
+
+
+/* no-op func for checking focus surface */
+static void
+focus_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy,
+ int32_t width, int32_t height)
+{
+}
+
+static struct focus_surface *
+get_focus_surface(struct weston_surface *surface)
+{
+ if (surface->configure == focus_surface_configure)
+ return surface->configure_private;
+ else
+ return NULL;
+}
+
+static bool
+is_focus_surface (struct weston_surface *es)
+{
+ return (es->configure == focus_surface_configure);
+}
+
+static bool
+is_focus_view (struct weston_view *view)
+{
+ return is_focus_surface (view->surface);
+}
+
+static struct focus_surface *
+create_focus_surface(struct weston_compositor *ec,
+ struct weston_output *output)
+{
+ struct focus_surface *fsurf = NULL;
+ struct weston_surface *surface = NULL;
+
+ fsurf = malloc(sizeof *fsurf);
+ if (!fsurf)
+ return NULL;
+
+ fsurf->surface = weston_surface_create(ec);
+ surface = fsurf->surface;
+ if (surface == NULL) {
+ free(fsurf);
+ return NULL;
+ }
+
+ surface->configure = focus_surface_configure;
+ surface->output = output;
+ surface->configure_private = fsurf;
+
+ fsurf->view = weston_view_create (surface);
+
+ weston_view_configure(fsurf->view, output->x, output->y,
+ output->width, output->height);
+ weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
+ pixman_region32_fini(&surface->opaque);
+ pixman_region32_init_rect(&surface->opaque, output->x, output->y,
+ output->width, output->height);
+ pixman_region32_fini(&surface->input);
+ pixman_region32_init(&surface->input);
+
+ wl_list_init(&fsurf->workspace_transform.link);
+
+ return fsurf;
+}
+
+static void
+focus_surface_destroy(struct focus_surface *fsurf)
+{
+ weston_surface_destroy(fsurf->surface);
+ free(fsurf);
+}
+
+static void
+focus_animation_done(struct weston_view_animation *animation, void *data)
+{
+ struct workspace *ws = data;
+
+ ws->focus_animation = NULL;
+}
+
static void
focus_state_destroy(struct focus_state *state)
{
wl_list_for_each(view, &state->ws->layer.view_list, layer_link) {
if (view->surface == main_surface)
continue;
+ if (is_focus_view(view))
+ continue;
next = view->surface;
break;
if (main_surface != state->keyboard_focus)
next = main_surface;
+ shell = state->seat->compositor->shell_interface.shell;
if (next) {
- shell = state->seat->compositor->shell_interface.shell;
+ state->keyboard_focus = NULL;
activate(shell, next, state->seat);
} else {
+ if (shell->focus_animation_type == ANIMATION_DIM_LAYER) {
+ if (state->ws->focus_animation)
+ weston_view_animation_destroy(state->ws->focus_animation);
+
+ state->ws->focus_animation = weston_fade_run(
+ state->ws->fsurf_front->view,
+ state->ws->fsurf_front->view->alpha, 0.0, 300,
+ focus_animation_done, state->ws);
+ }
+
wl_list_remove(&state->link);
focus_state_destroy(state);
}
if (state == NULL)
return NULL;
+ state->keyboard_focus = NULL;
state->ws = ws;
state->seat = seat;
wl_list_insert(&ws->focus_list, &state->link);
}
static void
+animate_focus_change(struct desktop_shell *shell, struct workspace *ws,
+ struct weston_view *from, struct weston_view *to)
+{
+ struct weston_output *output;
+ bool focus_surface_created = false;
+
+ /* FIXME: Only support dim animation using two layers */
+ if (from == to || shell->focus_animation_type != ANIMATION_DIM_LAYER)
+ return;
+
+ output = get_default_output(shell->compositor);
+ if (ws->fsurf_front == NULL && (from || to)) {
+ ws->fsurf_front = create_focus_surface(shell->compositor, output);
+ ws->fsurf_back = create_focus_surface(shell->compositor, output);
+ ws->fsurf_front->view->alpha = 0.0;
+ ws->fsurf_back->view->alpha = 0.0;
+ focus_surface_created = true;
+ } else {
+ wl_list_remove(&ws->fsurf_front->view->layer_link);
+ wl_list_remove(&ws->fsurf_back->view->layer_link);
+ }
+
+ if (ws->focus_animation) {
+ weston_view_animation_destroy(ws->focus_animation);
+ ws->focus_animation = NULL;
+ }
+
+ if (to)
+ wl_list_insert(&to->layer_link,
+ &ws->fsurf_front->view->layer_link);
+ else if (from)
+ wl_list_insert(&ws->layer.view_list,
+ &ws->fsurf_front->view->layer_link);
+
+ if (focus_surface_created) {
+ ws->focus_animation = weston_fade_run(
+ ws->fsurf_front->view,
+ ws->fsurf_front->view->alpha, 0.6, 300,
+ focus_animation_done, ws);
+ } else if (from) {
+ wl_list_insert(&from->layer_link,
+ &ws->fsurf_back->view->layer_link);
+ ws->focus_animation = weston_stable_fade_run(
+ ws->fsurf_front->view, 0.0,
+ ws->fsurf_back->view, 0.6,
+ focus_animation_done, ws);
+ } else if (to) {
+ wl_list_insert(&ws->layer.view_list,
+ &ws->fsurf_back->view->layer_link);
+ ws->focus_animation = weston_stable_fade_run(
+ ws->fsurf_front->view, 0.0,
+ ws->fsurf_back->view, 0.6,
+ focus_animation_done, ws);
+ }
+}
+
+static void
workspace_destroy(struct workspace *ws)
{
struct focus_state *state, *next;
wl_list_for_each_safe(state, next, &ws->focus_list, link)
focus_state_destroy(state);
+ if (ws->fsurf_front)
+ focus_surface_destroy(ws->fsurf_front);
+ if (ws->fsurf_back)
+ focus_surface_destroy(ws->fsurf_back);
+
free(ws);
}
wl_list_init(&ws->focus_list);
wl_list_init(&ws->seat_destroyed_listener.link);
ws->seat_destroyed_listener.notify = seat_destroyed;
+ ws->fsurf_front = NULL;
+ ws->fsurf_back = NULL;
+ ws->focus_animation = NULL;
return ws;
}
}
static void
-view_translate(struct weston_view *view, double d)
+view_translate(struct workspace *ws, struct weston_view *view, double d)
{
- struct shell_surface *shsurf = get_shell_surface(view->surface);
struct weston_transform *transform;
- transform = &shsurf->workspace_transform;
+ if (is_focus_view(view)) {
+ struct focus_surface *fsurf = get_focus_surface(view->surface);
+ transform = &fsurf->workspace_transform;
+ } else {
+ struct shell_surface *shsurf = get_shell_surface(view->surface);
+ transform = &shsurf->workspace_transform;
+ }
+
if (wl_list_empty(&transform->link))
wl_list_insert(view->geometry.transformation_list.prev,
- &shsurf->workspace_transform.link);
+ &transform->link);
- weston_matrix_init(&shsurf->workspace_transform.matrix);
- weston_matrix_translate(&shsurf->workspace_transform.matrix,
+ weston_matrix_init(&transform->matrix);
+ weston_matrix_translate(&transform->matrix,
0.0, d, 0.0);
weston_view_geometry_dirty(view);
}
height = get_output_height(view->surface->output);
d = height * fraction;
- view_translate(view, d);
+ view_translate(ws, view, d);
}
}
else
d = height + height * fraction;
- view_translate(view, d);
+ view_translate(ws, view, d);
}
}
workspace_deactivate_transforms(struct workspace *ws)
{
struct weston_view *view;
- struct shell_surface *shsurf;
+ struct weston_transform *transform;
wl_list_for_each(view, &ws->layer.view_list, layer_link) {
- shsurf = get_shell_surface(view->surface);
- if (!wl_list_empty(&shsurf->workspace_transform.link)) {
- wl_list_remove(&shsurf->workspace_transform.link);
- wl_list_init(&shsurf->workspace_transform.link);
+ if (is_focus_view(view)) {
+ struct focus_surface *fsurf = get_focus_surface(view->surface);
+ transform = &fsurf->workspace_transform;
+ } else {
+ struct shell_surface *shsurf = get_shell_surface(view->surface);
+ transform = &shsurf->workspace_transform;
+ }
+
+ if (!wl_list_empty(&transform->link)) {
+ wl_list_remove(&transform->link);
+ wl_list_init(&transform->link);
}
weston_view_geometry_dirty(view);
}
{
struct workspace *from;
struct workspace *to;
+ struct focus_state *state;
if (index == shell->workspaces.current)
return;
restore_focus_state(shell, to);
+ if (shell->focus_animation_type != ANIMATION_NONE) {
+ wl_list_for_each(state, &from->focus_list, link)
+ if (state->keyboard_focus)
+ animate_focus_change(shell, from,
+ get_default_view(state->keyboard_focus), NULL);
+
+ wl_list_for_each(state, &to->focus_list, link)
+ if (state->keyboard_focus)
+ animate_focus_change(shell, to,
+ NULL, get_default_view(state->keyboard_focus));
+ }
+
if (workspace_is_empty(to) && workspace_is_empty(from))
update_workspace(shell, index, from, to);
else
surface = weston_surface_get_main_surface(seat->keyboard->focus);
view = get_default_view(surface);
if (view == NULL ||
- index == shell->workspaces.current)
+ index == shell->workspaces.current ||
+ is_focus_view(view))
return;
from = get_current_workspace(shell);
shsurf->class = strdup(class);
}
-static struct weston_output *
-get_default_output(struct weston_compositor *compositor)
-{
- return container_of(compositor->output_list.next,
- struct weston_output, link);
-}
-
static void
restore_output_mode(struct weston_output *output)
{
struct weston_view *main_view;
struct focus_state *state;
struct workspace *ws;
+ struct weston_surface *old_es;
main_surface = weston_surface_get_main_surface(es);
if (state == NULL)
return;
+ old_es = state->keyboard_focus;
state->keyboard_focus = es;
wl_list_remove(&state->surface_destroy_listener.link);
wl_signal_add(&es->destroy_signal, &state->surface_destroy_listener);
/* should on top of panels */
shell_stack_fullscreen(get_shell_surface(main_surface));
shell_configure_fullscreen(get_shell_surface(main_surface));
- break;
+ return;
default:
restore_all_output_modes(shell->compositor);
ws = get_current_workspace(shell);
weston_view_restack(main_view, &ws->layer.view_list);
break;
}
+
+ if (shell->focus_animation_type != ANIMATION_NONE)
+ animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es));
}
/* no-op func for checking black surface */
struct workspace *ws = get_current_workspace(switcher->shell);
wl_list_for_each(view, &ws->layer.view_list, layer_link) {
+ if (is_focus_view(view))
+ continue;
+
view->alpha = 1.0;
weston_surface_damage(view->surface);
}