uint32_t meta_state;
struct wl_list animate_list;
- struct wlsc_surface *primary;
+
+ struct wlsc_session *primary;
+ struct wl_list session_list;
};
#define META_DOWN 256
+struct wlsc_vector {
+ GLdouble x, y, z;
+};
+
struct wlsc_animate {
struct wl_list link;
void (*animate)(struct wlsc_animate *animate,
uint32_t frame, uint32_t msecs);
};
-struct wlsc_vector {
- GLdouble x, y, z;
+struct wlsc_session {
+ struct wlsc_surface *surface;
+ struct wlsc_vector target, current, previous;
+ GLdouble target_angle, current_angle, previous_angle;
+ struct wlsc_animate animate;
+ struct wl_list link;
+ struct wlsc_listener listener;
};
struct wlsc_surface {
struct wl_list link;
struct wlsc_matrix matrix;
- struct wlsc_vector target, current, previous;
- GLdouble target_angle, current_angle, previous_angle;
- struct wlsc_animate animate;
+ /* FIXME: This should be it's own object at some point. */
+ struct wlsc_session session;
};
static const char *option_background = "background.jpg";
}
static void
-wlsc_surface_update_matrix(struct wlsc_surface *es)
-{
- GLdouble tx, ty;
-
- tx = es->map.x + es->map.width / 2;
- ty = es->map.y + es->map.height / 2;
-
- wlsc_matrix_init(&es->matrix);
- wlsc_matrix_translate(&es->matrix, -tx, -ty, 0);
- wlsc_matrix_rotate(&es->matrix, es->current_angle, 0, 1, 0);
- wlsc_matrix_translate(&es->matrix, tx + es->current.x,
- ty + es->current.y, es->current.z);
-}
-
-static void
wlsc_surface_init(struct wlsc_surface *surface,
struct wlsc_compositor *compositor, struct wl_visual *visual,
int32_t x, int32_t y, int32_t width, int32_t height)
surface->map.height = height;
surface->surface = EGL_NO_SURFACE;
surface->visual = visual;
- surface->current.x = 0;
- surface->current.y = 0;
- surface->current.z = 0;
- surface->current_angle = 0;
- surface->target.x = 0;
- surface->target.y = 0;
- surface->target.z = 0;
- surface->target_angle = 0;
- surface->previous_angle = 0;
-
- wlsc_surface_update_matrix(surface);
+ wlsc_matrix_init(&surface->matrix);
}
static struct wlsc_surface *
wlsc_surface_destroy(struct wlsc_surface *surface,
struct wlsc_compositor *compositor)
{
- struct wlsc_listener *l;
+ struct wlsc_listener *l, *next;
l = container_of(compositor->surface_destroy_listener_list.next,
struct wlsc_listener, link);
while (&l->link != &compositor->surface_destroy_listener_list) {
+ next = container_of(l->link.next, struct wlsc_listener, link);
l->func(l, surface);
- l = container_of(l->link.next, struct wlsc_listener, link);
+ l = next;
}
wl_list_remove(&surface->link);
- wl_list_remove(&surface->animate.link);
glDeleteTextures(1, &surface->texture);
if (surface->surface != EGL_NO_SURFACE)
}
static void
+wlsc_surface_raise(struct wlsc_surface *surface)
+{
+ struct wlsc_compositor *compositor = surface->compositor;
+
+ wl_list_remove(&surface->link);
+ wl_list_insert(compositor->surface_list.prev, &surface->link);
+}
+
+static void
+wlsc_surface_lower(struct wlsc_surface *surface)
+{
+ struct wlsc_compositor *compositor = surface->compositor;
+
+ wl_list_remove(&surface->link);
+ wl_list_insert(&compositor->surface_list, &surface->link);
+}
+
+static void
wlsc_vector_add(struct wlsc_vector *v1, struct wlsc_vector *v2)
{
v1->x += v2->x;
output->height / s, -output->height / s, 1, 2 * s);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
- glClearColor(0, 0, 0.2, 1);
+ glClearColor(0, 0, 0, 1);
glTranslatef(-output->width / 2, -output->height / 2, -s / 2);
}
static void
-schedule_repaint(struct wlsc_compositor *ec)
+wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor)
{
struct wl_event_loop *loop;
- ec->repaint_needed = 1;
- if (!ec->repaint_on_timeout) {
- loop = wl_display_get_event_loop(ec->wl_display);
- wl_event_loop_add_idle(loop, repaint, ec);
+ compositor->repaint_needed = 1;
+ if (!compositor->repaint_on_timeout) {
+ loop = wl_display_get_event_loop(compositor->wl_display);
+ wl_event_loop_add_idle(loop, repaint, compositor);
}
}
wlsc_surface_destroy(es, ec);
- schedule_repaint(ec);
+ wlsc_compositor_schedule_repaint(ec);
}
static void
}
static void
+wlsc_session_update_matrix(struct wlsc_session *session);
+
+static void
surface_map(struct wl_client *client,
struct wl_surface *surface,
int32_t x, int32_t y, int32_t width, int32_t height)
es->map.y = y;
es->map.width = width;
es->map.height = height;
- wlsc_surface_update_matrix(es);
+
+ wlsc_session_update_matrix(&es->session);
}
static void
};
static void
-animate_surface(struct wlsc_animate *animate,
- struct wlsc_compositor *compositor,
- uint32_t frame, uint32_t msecs)
+wlsc_session_update_matrix(struct wlsc_session *session)
{
+ GLdouble tx, ty;
+ struct wlsc_surface *s = session->surface;
+
+ tx = s->map.x + s->map.width / 2;
+ ty = s->map.y + s->map.height / 2;
+
+ wlsc_matrix_init(&s->matrix);
+ wlsc_matrix_translate(&s->matrix, -tx, -ty, 0);
+ wlsc_matrix_rotate(&s->matrix, session->current_angle, 0, 1, 0);
+ wlsc_matrix_translate(&s->matrix, tx + session->current.x,
+ ty + session->current.y, session->current.z);
+}
+
+static void
+wl_session_animate(struct wlsc_animate *animate,
+ struct wlsc_compositor *compositor,
+ uint32_t frame, uint32_t msecs)
+{
+ struct wlsc_session *session;
struct wlsc_surface *s;
double angle_force, angle;
struct wlsc_vector force, tmp;
- double step = 0.3;
- double friction = 1;
+ double step = 0.2;
+ double friction = 1.5;
double spring = 0.2;
- s = container_of(animate, struct wlsc_surface, animate);
+ session = container_of(animate, struct wlsc_session, animate);
+ s = session->surface;
- angle = s->current_angle;
- angle_force = (s->target_angle - angle) * spring +
- (s->previous_angle - angle) * friction;
+ angle = session->current_angle;
+ angle_force = (session->target_angle - angle) * spring +
+ (session->previous_angle - angle) * friction;
- s->current_angle = angle + (angle - s->previous_angle) + angle_force * step;
- s->previous_angle = angle;
+ session->current_angle =
+ angle + (angle - session->previous_angle) + angle_force * step;
+ session->previous_angle = angle;
- force = s->target;
- wlsc_vector_subtract(&force, &s->current);
+ force = session->target;
+ wlsc_vector_subtract(&force, &session->current);
wlsc_vector_scalar(&force, spring);
- tmp = s->previous;
- wlsc_vector_subtract(&tmp, &s->current);
+ tmp = session->previous;
+ wlsc_vector_subtract(&tmp, &session->current);
wlsc_vector_scalar(&tmp, friction);
wlsc_vector_add(&force, &tmp);
wlsc_vector_scalar(&force, step);
- wlsc_vector_add(&force, &s->current);
- wlsc_vector_subtract(&force, &s->previous);
- s->previous = s->current;
- wlsc_vector_add(&s->current, &force);
+ wlsc_vector_add(&force, &session->current);
+ wlsc_vector_subtract(&force, &session->previous);
+ session->previous = session->current;
+ wlsc_vector_add(&session->current, &force);
- wlsc_surface_update_matrix(s);
+ wlsc_session_update_matrix(session);
- tmp = s->current;
- wlsc_vector_subtract(&tmp, &s->target);
+ tmp = session->current;
+ wlsc_vector_subtract(&tmp, &session->target);
if (tmp.x * tmp.x + tmp.y * tmp.y + tmp.z * tmp.z > 0.001) {
- schedule_repaint(compositor);
+ wlsc_compositor_schedule_repaint(compositor);
} else {
+ wl_list_remove(&session->animate.link);
+ wl_list_init(&session->animate.link);
+ }
+}
+
+static void
+wlsc_session_activate(struct wlsc_compositor *compositor, struct wlsc_session *session)
+{
+ struct wlsc_session *s;
+ int i;
+
+ compositor->primary = session;
+ if (wl_list_empty(&compositor->session_list))
+ return;
+
+ session->target.x = 0;
+ session->target.y = 0;
+ session->target.z = -600;
+ session->target_angle = 0;
+ wl_list_remove(&session->animate.link);
+ wl_list_insert(compositor->animate_list.prev, &session->animate.link);
+
+ i = 0;
+ s = container_of(session->link.prev,
+ struct wlsc_session, link);
+ while (&s->link != &compositor->session_list) {
+ s->target.x = -1000 - 500 * i;
+ s->target.y = 0;
+ s->target.z = -2500;
+ s->target_angle = M_PI / 4;
+ wl_list_remove(&s->animate.link);
+ wl_list_insert(compositor->animate_list.prev, &s->animate.link);
+ wlsc_surface_lower(s->surface);
+
+ s = container_of(s->link.prev,
+ struct wlsc_session, link);
+ i++;
+ }
+
+ i = 0;
+ s = container_of(session->link.next,
+ struct wlsc_session, link);
+ while (&s->link != &compositor->session_list) {
+ s->target.x = 1000 + 500 * i;
+ s->target.y = 0;
+ s->target.z = -2500;
+ s->target_angle = -M_PI / 4;
wl_list_remove(&s->animate.link);
- wl_list_init(&s->animate.link);
+ wl_list_insert(compositor->animate_list.prev, &s->animate.link);
+ wlsc_surface_lower(s->surface);
+
+ s = container_of(s->link.next,
+ struct wlsc_session, link);
+ i++;
+ }
+
+ wlsc_compositor_schedule_repaint(compositor);
+}
+
+static void
+wlsc_session_handle_surface_destroy(struct wlsc_listener *listener,
+ struct wlsc_surface *surface)
+{
+ struct wlsc_session *session =
+ container_of(listener, struct wlsc_session, listener);
+ struct wlsc_compositor *compositor;
+ struct wlsc_session *primary;
+
+ if (session->surface != surface)
+ return;
+
+ compositor = session->surface->compositor;
+ if (compositor->primary == session) {
+ printf("destroy session %p [%p, %p]\n", session, session->link.prev, session->link.next);
+ if (session->link.next != &compositor->session_list)
+ primary = container_of(session->link.next,
+ struct wlsc_session, link);
+ else if (session->link.prev != &compositor->session_list)
+ primary = container_of(session->link.prev,
+ struct wlsc_session, link);
+ else
+ primary = NULL;
+ }
+
+ wl_list_remove(&session->animate.link);
+ wl_list_remove(&session->link);
+ wl_list_remove(&session->listener.link);
+
+ if (compositor->primary == session) {
+ printf("activating session %p\n", primary);
+ wlsc_session_activate(compositor, primary);
}
}
static void
+wlsc_session_init(struct wlsc_session *session, struct wlsc_surface *surface)
+{
+ struct wlsc_compositor *c = surface->compositor;
+
+ session->animate.animate = wl_session_animate;
+ wl_list_init(&session->animate.link);
+ wl_list_insert(c->session_list.prev, &session->link);
+
+ session->surface = surface;
+ session->current.x = 0;
+ session->current.y = 0;
+ session->current.z = 0;
+ session->current_angle = 0;
+ session->target.x = 0;
+ session->target.y = 0;
+ session->target.z = 0;
+ session->target_angle = 0;
+ session->previous_angle = 0;
+
+ wlsc_session_update_matrix(session);
+
+ session->listener.func = wlsc_session_handle_surface_destroy;
+ wl_list_insert(c->surface_destroy_listener_list.prev,
+ &session->listener.link);
+
+ printf("added session %p [%p, %p]\n", session, session->link.prev, session->link.next);
+ printf(" - prev [%p]\n", session->link.prev->prev);
+}
+
+static void
compositor_create_surface(struct wl_client *client,
struct wl_compositor *compositor, uint32_t id)
{
struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
- struct wlsc_surface *es;
+ struct wlsc_surface *surface;
- es = malloc(sizeof *es);
- if (es == NULL)
+ surface = malloc(sizeof *surface);
+ if (surface == NULL)
/* FIXME: Send OOM event. */
return;
- wlsc_surface_init(es, ec, NULL, 0, 0, 0, 0);
- es->animate.animate = animate_surface;
- wl_list_init(&es->animate.link);
+ wlsc_surface_init(surface, ec, NULL, 0, 0, 0, 0);
- wl_list_insert(ec->surface_list.prev, &es->link);
- wl_client_add_surface(client, &es->base,
+ wl_list_insert(ec->surface_list.prev, &surface->link);
+ wl_client_add_surface(client, &surface->base,
&surface_interface, id);
+
+ wlsc_session_init(&surface->session, surface);
+ wlsc_session_activate(ec, &surface->session);
}
static void
{
struct wlsc_compositor *ec = (struct wlsc_compositor *) compositor;
- schedule_repaint(ec);
+ wlsc_compositor_schedule_repaint(ec);
wl_client_send_acknowledge(client, compositor, key, ec->current_frame);
}
device->sprite->map.x = x - hotspot_x;
device->sprite->map.y = y - hotspot_y;
- schedule_repaint(device->ec);
+ wlsc_compositor_schedule_repaint(device->ec);
}
void
notify_button(struct wlsc_input_device *device,
int32_t button, int32_t state)
{
- struct wlsc_surface *es;
- struct wlsc_compositor *ec = device->ec;
+ struct wlsc_surface *surface;
+ struct wlsc_compositor *compositor = device->ec;
int32_t sx, sy;
- if (!ec->vt_active)
+ if (!compositor->vt_active)
return;
- es = pick_surface(device, &sx, &sy);
- if (es) {
- wl_list_remove(&es->link);
- wl_list_insert(device->ec->surface_list.prev, &es->link);
+ surface = pick_surface(device, &sx, &sy);
+ if (surface) {
+ wlsc_surface_raise(surface);
if (state) {
- /* FIXME: We need callbacks when the surfaces
- * we reference here go away. */
device->grab++;
- device->grab_surface = es;
- wlsc_input_device_set_keyboard_focus(device, es);
+ device->grab_surface = surface;
+ wlsc_input_device_set_keyboard_focus(device,
+ surface);
} else {
device->grab--;
}
/* FIXME: Swallow click on raise? */
- wl_surface_post_event(&es->base, &device->base,
+ wl_surface_post_event(&surface->base, &device->base,
WL_INPUT_BUTTON, button, state,
device->x, device->y, sx, sy);
- schedule_repaint(device->ec);
+ wlsc_compositor_schedule_repaint(compositor);
}
}
static void on_term_signal(int signal_number, void *data);
-static void
-update_surface_targets(struct wlsc_compositor *compositor, int primary)
-{
- struct wlsc_surface *s;
- int i;
-
- i = 0;
- s = container_of(compositor->surface_list.next,
- struct wlsc_surface, link);
- while (&s->link != &compositor->surface_list) {
- if (i < primary) {
- s->target.x = -400 + 500 * (i - primary);
- s->target.y = 0;
- s->target.z = -1500;
- s->target_angle = M_PI / 4;
- } else if (i == primary) {
- s->target.x = 0;
- s->target.y = 0;
- s->target.z = -1000;
- s->target_angle = 0;
- compositor->primary = s;
- } else {
- s->target.x = 400 + 500 * (i - primary);
- s->target.y = 0;
- s->target.z = -1500;
- s->target_angle = -M_PI / 4;
- }
- wl_list_remove(&s->animate.link);
- wl_list_insert(compositor->animate_list.prev, &s->animate.link);
- s = container_of(s->link.next,
- struct wlsc_surface, link);
- i++;
- }
-
- schedule_repaint(compositor);
-}
-
void
notify_key(struct wlsc_input_device *device,
uint32_t key, uint32_t state)
{
- struct wlsc_compositor *ec = device->ec;
+ struct wlsc_compositor *compositor = device->ec;
+ struct wlsc_session *s;
uint32_t *k, *end;
- if (!ec->vt_active)
+ if (!compositor->vt_active)
return;
- switch (key | ec->meta_state) {
+ switch (key | compositor->meta_state) {
case KEY_EJECTCD | META_DOWN:
- on_term_signal(SIGTERM, ec);
+ on_term_signal(SIGTERM, compositor);
return;
- case KEY_1 | META_DOWN:
- case KEY_2 | META_DOWN:
- case KEY_3 | META_DOWN:
- case KEY_4 | META_DOWN:
- case KEY_5 | META_DOWN:
- update_surface_targets(ec, key - KEY_1);
- if (device->grab == 0)
- wlsc_input_device_set_keyboard_focus(device, ec->primary);
- device->keyboard_focus = ec->primary;
+ case KEY_LEFT | META_DOWN:
+ if (!compositor->primary || !state)
+ break;
+ s = container_of(compositor->primary->link.prev,
+ struct wlsc_session, link);
+ if (&s->link != &compositor->session_list) {
+ wlsc_session_activate(compositor, s);
+ if (device->grab == 0)
+ wlsc_input_device_set_keyboard_focus(device, s->surface);
+ }
+ return;
+
+
+ case KEY_RIGHT | META_DOWN:
+ if (!compositor->primary || !state)
+ break;
+ s = container_of(compositor->primary->link.next,
+ struct wlsc_session, link);
+ if (&s->link != &compositor->session_list) {
+ wlsc_session_activate(compositor, s);
+ if (device->grab == 0)
+ wlsc_input_device_set_keyboard_focus(device, s->surface);
+
+ }
return;
case KEY_LEFTMETA:
case KEY_RIGHTMETA:
case KEY_LEFTMETA | META_DOWN:
case KEY_RIGHTMETA | META_DOWN:
- ec->meta_state = state ? META_DOWN : 0;
- if (state == 0 && ec->primary != NULL) {
- ec->primary->target.z = 0;
- wl_list_remove(&ec->primary->animate.link);
- wl_list_insert(&ec->animate_list,
- &ec->primary->animate.link);
- schedule_repaint(ec);
+ compositor->meta_state = state ? META_DOWN : 0;
+
+ if (state == 0 && compositor->primary) {
+ s = compositor->primary;
+ s->target.z = 0;
+ wl_list_remove(&s->animate.link);
+ wl_list_insert(compositor->animate_list.prev, &s->animate.link);
+ wlsc_compositor_schedule_repaint(compositor);
}
+
return;
}
setup_tty(ec, loop);
ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec);
- schedule_repaint(ec);
+ wlsc_compositor_schedule_repaint(ec);
wl_list_init(&ec->animate_list);
+ wl_list_init(&ec->session_list);
return ec;
}