diff options
Diffstat (limited to 'compositor/compositor.c')
-rw-r--r-- | compositor/compositor.c | 333 |
1 files changed, 296 insertions, 37 deletions
diff --git a/compositor/compositor.c b/compositor/compositor.c index 1d2fed33..9df01418 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -42,7 +42,9 @@ static const char *option_socket_name = NULL; static const char *option_background = "background.jpg"; static const char *option_geometry = "1024x640"; +static int option_idle_time = 5; static int option_connector = 0; +static int option_meego = 0; static const GOptionEntry option_entries[] = { { "background", 'b', 0, G_OPTION_ARG_STRING, @@ -53,6 +55,10 @@ static const GOptionEntry option_entries[] = { &option_geometry, "Geometry" }, { "socket", 's', 0, G_OPTION_ARG_STRING, &option_socket_name, "Socket Name" }, + { "idle-time", 'i', 0, G_OPTION_ARG_INT, + &option_idle_time, "Screensaver idle time" }, + { "meego", 0, 0, G_OPTION_ARG_NONE, + &option_meego, "Launch the meego tablet shell" }, { NULL } }; @@ -120,6 +126,47 @@ wlsc_matrix_transform(struct wlsc_matrix *matrix, struct wlsc_vector *v) *v = t; } +void +wlsc_tweener_init(struct wlsc_tweener *tweener, + double k, double current, double target) +{ + tweener->k = k; + tweener->current = current; + tweener->previous = current; + tweener->target = target; +} + +void +wlsc_tweener_update(struct wlsc_tweener *tweener, uint32_t msec) +{ + double force, current; + + current = tweener->current; + force = tweener->k * (tweener->target - current) / 10.0 + + (tweener->previous - current); + + tweener->current = + current + (current - tweener->previous) + force; + tweener->previous = current; + + if (tweener->current >= 1.0) { + tweener->current = 1.0; + tweener->previous = 1.0; + } + + if (tweener->current <= 0.0) { + tweener->current = 0.0; + tweener->previous = 0.0; + } +} + +int +wlsc_tweener_done(struct wlsc_tweener *tweener) +{ + return fabs(tweener->previous - tweener->target) < 0.0002 && + fabs(tweener->current - tweener->target) < 0.0002; +} + struct wlsc_surface * wlsc_surface_create(struct wlsc_compositor *compositor, int32_t x, int32_t y, int32_t width, int32_t height) @@ -532,10 +579,20 @@ wlsc_surface_update_matrix(struct wlsc_surface *es) } void -wlsc_output_finish_frame(struct wlsc_output *output, int msecs) +wlsc_compositor_damage_all(struct wlsc_compositor *compositor) +{ + struct wlsc_output *output; + + wl_list_for_each(output, &compositor->output_list, link) + wlsc_output_damage(output); +} + +void +wlsc_output_finish_frame(struct wlsc_output *output, uint32_t msecs) { struct wlsc_compositor *compositor = output->compositor; struct wlsc_surface *es; + struct wlsc_animation *animation, *next; wl_list_for_each(es, &compositor->surface_list, link) { if (es->output == output) { @@ -548,6 +605,63 @@ wlsc_output_finish_frame(struct wlsc_output *output, int msecs) wl_event_source_timer_update(compositor->timer_source, 5); compositor->repaint_on_timeout = 1; + + wl_list_for_each_safe(animation, next, + &compositor->animation_list, link) + animation->frame(animation, output, msecs); +} + +void +wlsc_output_damage(struct wlsc_output *output) +{ + struct wlsc_compositor *compositor = output->compositor; + + pixman_region32_union_rect(&compositor->damage_region, + &compositor->damage_region, + output->x, output->y, + output->width, output->height); + wlsc_compositor_schedule_repaint(compositor); +} + +static void +tint_frame(struct wlsc_animation *animation, + struct wlsc_output *output, uint32_t msecs) +{ + struct wlsc_compositor *compositor = + container_of(animation, + struct wlsc_compositor, tint_animation); + + wlsc_tweener_update(&compositor->tint, msecs); + if (wlsc_tweener_done(&compositor->tint)) { + if (compositor->tint.current > 0.999 && + compositor->tablet_shell) + compositor->tablet_shell->lock(compositor); + wl_list_remove(&animation->link); + wl_list_init(&animation->link); + } else + wlsc_output_damage(output); +} + +static void +tint_output(struct wlsc_output *output, + GLfloat tint, pixman_region32_t *region) +{ + struct wlsc_compositor *compositor = output->compositor; + struct wlsc_surface surface; + GLfloat color[4] = { 0.0, 0.0, 0.0, tint }; + + surface.compositor = compositor; + surface.x = output->x; + surface.y = output->y; + surface.width = output->width; + surface.height = output->height; + surface.visual = &compositor->compositor.premultiplied_argb_visual; + surface.texture = GL_NONE; + glUseProgram(compositor->solid_shader.program); + glUniformMatrix4fv(compositor->solid_shader.proj_uniform, + 1, GL_FALSE, output->matrix.d); + glUniform4fv(compositor->solid_shader.color_uniform, 1, color); + wlsc_surface_draw(&surface, output, region); } static void @@ -563,8 +677,10 @@ wlsc_output_repaint(struct wlsc_output *output) glViewport(0, 0, output->width, output->height); - glUniformMatrix4fv(ec->proj_uniform, 1, GL_FALSE, output->matrix.d); - glUniform1i(ec->tex_uniform, 0); + glUseProgram(ec->texture_shader.program); + glUniformMatrix4fv(ec->texture_shader.proj_uniform, + 1, GL_FALSE, output->matrix.d); + glUniform1i(ec->texture_shader.tex_uniform, 0); pixman_region32_init(&new_damage); pixman_region32_init(&total_damage); @@ -581,10 +697,13 @@ wlsc_output_repaint(struct wlsc_output *output) if (ec->focus) if (output->set_hardware_cursor(output, ec->input_device) < 0) using_hardware_cursor = 0; + if (ec->tint.current > 0.001) + using_hardware_cursor = 0; es = container_of(ec->surface_list.next, struct wlsc_surface, link); if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN && es->fullscreen_output == output) { + fprintf(stderr, "fullscreen\n"); if (es->visual == &ec->compositor.rgb_visual && using_hardware_cursor) { if (output->prepare_scanout_surface(output, es) == 0) { @@ -602,6 +721,7 @@ wlsc_output_repaint(struct wlsc_output *output) glClear(GL_COLOR_BUFFER_BIT); wlsc_surface_draw(es, output, &total_damage); } else { +#if 0 wl_list_for_each(es, &ec->surface_list, link) { if (es->visual != &ec->compositor.rgb_visual) continue; @@ -613,17 +733,18 @@ wlsc_output_repaint(struct wlsc_output *output) pixman_region32_subtract(&total_damage, &total_damage, &repaint); } - if (output->background) wlsc_surface_draw(output->background, output, &total_damage); else glClear(GL_COLOR_BUFFER_BIT); +#endif wl_list_for_each_reverse(es, &ec->surface_list, link) { if (ec->overlay == es) continue; +#if 0 if (es->visual == &ec->compositor.rgb_visual) { pixman_region32_union_rect(&total_damage, &total_damage, @@ -631,11 +752,13 @@ wlsc_output_repaint(struct wlsc_output *output) es->width, es->height); continue; } +#endif wlsc_surface_draw(es, output, &total_damage); } } + glUseProgram(ec->texture_shader.program); if (ec->overlay) wlsc_surface_draw(ec->overlay, output, &total_damage); @@ -646,6 +769,9 @@ wlsc_output_repaint(struct wlsc_output *output) wlsc_surface_draw(eid->sprite, output, &total_damage); } + + if (ec->tint.current > 0.001) + tint_output(output, ec->tint.current, &total_damage); } static void @@ -691,6 +817,16 @@ wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor) compositor->repaint_on_timeout = 1; } +void +wlsc_compositor_set_tint(struct wlsc_compositor *compositor, float tint) +{ + compositor->tint.target = tint; + wlsc_compositor_damage_all(compositor); + if (wl_list_empty(&compositor->tint_animation.link)) + wl_list_insert(compositor->animation_list.prev, + &compositor->tint_animation.link); +} + static void surface_destroy(struct wl_client *client, struct wl_surface *surface) @@ -747,6 +883,9 @@ surface_attach(struct wl_client *client, if (x != 0 || y != 0) wlsc_surface_assign_output(es); wlsc_surface_update_matrix(es); + + if (es->compositor->tablet_shell) + es->compositor->tablet_shell->attach(es); } static void @@ -1015,6 +1154,46 @@ static const struct wl_grab_interface motion_grab_interface = { }; void +wlsc_compositor_wake(struct wlsc_compositor *compositor) +{ + if (compositor->idle_inhibit) + return; + + if (compositor->state == WLSC_COMPOSITOR_SLEEPING) + wlsc_compositor_set_tint(compositor, 0.0); + + compositor->state = WLSC_COMPOSITOR_ACTIVE; + wl_event_source_timer_update(compositor->idle_source, + option_idle_time * 1000); +} + +static void +wlsc_compositor_idle_inhibit(struct wlsc_compositor *compositor) +{ + wlsc_compositor_wake(compositor); + compositor->idle_inhibit++; +} + +static void +wlsc_compositor_idle_release(struct wlsc_compositor *compositor) +{ + compositor->idle_inhibit--; + wlsc_compositor_wake(compositor); +} + +static void +idle_handler(void *data) +{ + struct wlsc_compositor *compositor = data; + + if (compositor->idle_inhibit) + return; + + compositor->state = WLSC_COMPOSITOR_SLEEPING; + wlsc_compositor_set_tint(compositor, 1); +} + +void notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) { struct wlsc_surface *es; @@ -1027,6 +1206,8 @@ notify_motion(struct wl_input_device *device, uint32_t time, int x, int y) int x_valid = 0, y_valid = 0; int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN; + wlsc_compositor_wake(ec); + wl_list_for_each(output, &ec->output_list, link) { if (output->x <= x && x <= output->x + output->width) x_valid = 1; @@ -1120,6 +1301,11 @@ notify_button(struct wl_input_device *device, struct wlsc_surface *surface = (struct wlsc_surface *) device->pointer_focus; + if (state) + wlsc_compositor_idle_inhibit(compositor); + else + wlsc_compositor_idle_release(compositor); + if (state && surface && device->grab == NULL) { wlsc_surface_activate(surface, wd, time); wl_input_device_start_grab(device, @@ -1150,7 +1336,8 @@ terminate_binding(struct wl_input_device *device, uint32_t time, { struct wlsc_compositor *compositor = data; - wl_display_terminate(compositor->wl_display); + if (state) + wl_display_terminate(compositor->wl_display); } struct wlsc_binding * @@ -1224,9 +1411,14 @@ notify_key(struct wl_input_device *device, uint32_t *k, *end; struct wlsc_binding *b; + if (state) + wlsc_compositor_idle_inhibit(compositor); + else + wlsc_compositor_idle_release(compositor); + wl_list_for_each(b, &compositor->binding_list, link) { if (b->key == key && - b->modifier == wd->modifier_state && state) { + b->modifier == wd->modifier_state) { b->handler(&wd->input_device, time, key, 0, state, b->data); break; @@ -1307,12 +1499,17 @@ notify_keyboard_focus(struct wl_input_device *device, wd->modifier_state = 0; end = device->keys.data + device->keys.size; for (k = device->keys.data; k < end; k++) { + wlsc_compositor_idle_inhibit(compositor); update_modifier_state(wd, *k, 1); } wl_input_device_set_keyboard_focus(&wd->input_device, &es->surface, time); } else { + end = device->keys.data + device->keys.size; + for (k = device->keys.data; k < end; k++) + wlsc_compositor_idle_release(compositor); + wd->modifier_state = 0; wl_input_device_set_keyboard_focus(&wd->input_device, NULL, time); @@ -1399,7 +1596,7 @@ static const char vertex_shader[] = " v_texcoord = texcoord;\n" "}\n"; -static const char fragment_shader[] = +static const char texture_fragment_shader[] = "precision mediump float;\n" "varying vec2 v_texcoord;\n" "uniform sampler2D tex;\n" @@ -1408,53 +1605,103 @@ static const char fragment_shader[] = " gl_FragColor = texture2D(tex, v_texcoord)\n;" "}\n"; +static const char solid_fragment_shader[] = + "precision mediump float;\n" + "varying vec2 v_texcoord;\n" + "uniform vec4 color;\n" + "void main()\n" + "{\n" + " gl_FragColor = color\n;" + "}\n"; + static int -init_shaders(struct wlsc_compositor *ec) +compile_shader(GLenum type, const char *source) { - GLuint v, f, program; - const char *p; + GLuint s; char msg[512]; GLint status; - p = vertex_shader; - v = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(v, 1, &p, NULL); - glCompileShader(v); - glGetShaderiv(v, GL_COMPILE_STATUS, &status); + s = glCreateShader(type); + glShaderSource(s, 1, &source, NULL); + glCompileShader(s); + glGetShaderiv(s, GL_COMPILE_STATUS, &status); if (!status) { - glGetShaderInfoLog(v, sizeof msg, NULL, msg); - fprintf(stderr, "vertex shader info: %s\n", msg); - return -1; + glGetShaderInfoLog(s, sizeof msg, NULL, msg); + fprintf(stderr, "shader info: %s\n", msg); + return GL_NONE; } - p = fragment_shader; - f = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(f, 1, &p, NULL); - glCompileShader(f); - glGetShaderiv(f, GL_COMPILE_STATUS, &status); + return s; +} + +static int +wlsc_shader_init(struct wlsc_shader *shader, + const char *vertex_source, const char *fragment_source) +{ + char msg[512]; + GLint status; + + shader->vertex_shader = + compile_shader(GL_VERTEX_SHADER, vertex_source); + shader->fragment_shader = + compile_shader(GL_FRAGMENT_SHADER, fragment_source); + + shader->program = glCreateProgram(); + glAttachShader(shader->program, shader->vertex_shader); + glAttachShader(shader->program, shader->fragment_shader); + glBindAttribLocation(shader->program, 0, "position"); + glBindAttribLocation(shader->program, 1, "texcoord"); + + glLinkProgram(shader->program); + glGetProgramiv(shader->program, GL_LINK_STATUS, &status); if (!status) { - glGetShaderInfoLog(f, sizeof msg, NULL, msg); - fprintf(stderr, "fragment shader info: %s\n", msg); + glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg); + fprintf(stderr, "link info: %s\n", msg); return -1; } - program = glCreateProgram(); - glAttachShader(program, v); - glAttachShader(program, f); - glBindAttribLocation(program, 0, "position"); - glBindAttribLocation(program, 1, "texcoord"); + shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); + shader->tex_uniform = glGetUniformLocation(shader->program, "tex"); - glLinkProgram(program); - glGetProgramiv(program, GL_LINK_STATUS, &status); + return 0; +} + +static void +init_solid_shader(struct wlsc_shader *shader, + GLuint vertex_shader, const char *fragment_source) +{ + GLint status; + char msg[512]; + + shader->vertex_shader = vertex_shader; + shader->fragment_shader = + compile_shader(GL_FRAGMENT_SHADER, fragment_source); + + shader->program = glCreateProgram(); + glAttachShader(shader->program, shader->vertex_shader); + glAttachShader(shader->program, shader->fragment_shader); + glBindAttribLocation(shader->program, 0, "position"); + glBindAttribLocation(shader->program, 1, "texcoord"); + + glLinkProgram(shader->program); + glGetProgramiv(shader->program, GL_LINK_STATUS, &status); if (!status) { - glGetProgramInfoLog(program, sizeof msg, NULL, msg); + glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg); fprintf(stderr, "link info: %s\n", msg); - return -1; } - glUseProgram(program); - ec->proj_uniform = glGetUniformLocation(program, "proj"); - ec->tex_uniform = glGetUniformLocation(program, "tex"); + shader->proj_uniform = glGetUniformLocation(shader->program, "proj"); + shader->color_uniform = glGetUniformLocation(shader->program, "color"); +} + +static int +init_shaders(struct wlsc_compositor *ec) +{ + wlsc_shader_init(&ec->texture_shader, + vertex_shader, texture_fragment_shader); + init_solid_shader(&ec->solid_shader, + ec->texture_shader.vertex_shader, + solid_fragment_shader); return 0; } @@ -1537,6 +1784,10 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display) wl_list_init(&ec->input_device_list); wl_list_init(&ec->output_list); wl_list_init(&ec->binding_list); + wl_list_init(&ec->animation_list); + wlsc_tweener_init(&ec->tint, 0.8, 0.0, 1.0); + ec->tint_animation.frame = tint_frame; + wl_list_init(&ec->tint_animation.link); wlsc_shell_init(ec); wlsc_switcher_init(ec); @@ -1561,6 +1812,9 @@ wlsc_compositor_init(struct wlsc_compositor *ec, struct wl_display *display) return -1; loop = wl_display_get_event_loop(ec->wl_display); + ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec); + wl_event_source_timer_update(ec->idle_source, option_idle_time * 1000); + ec->timer_source = wl_event_loop_add_timer(loop, repaint, ec); pixman_region32_init(&ec->damage_region); wlsc_compositor_schedule_repaint(ec); @@ -1636,6 +1890,11 @@ int main(int argc, char *argv[]) wl_event_loop_add_signal(loop, SIGTERM, on_term_signal, ec); wl_event_loop_add_signal(loop, SIGINT, on_term_signal, ec); + if (option_meego) { + printf("Launching the meego tablet shell\n"); + meego_tablet_shell_init(ec); + } + wl_display_run(display); eglUnbindWaylandDisplayWL(ec->display, display); |