2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012 Collabora, Ltd.
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of the copyright holders not be used in
11 * advertising or publicity pertaining to distribution of the software
12 * without specific, written prior permission. The copyright holders make
13 * no representations about the suitability of this software for any
14 * purpose. It is provided "as is" without express or implied warranty.
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
21 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <sys/utsname.h>
43 #include <linux/input.h>
51 #define UNW_LOCAL_ONLY
52 #include <libunwind.h>
55 #include "compositor.h"
56 #include "../shared/os-compatibility.h"
57 #include "git-version.h"
60 static struct wl_list child_process_list;
61 static struct weston_compositor *segv_compositor;
64 sigchld_handler(int signal_number, void *data)
66 struct weston_process *p;
70 pid = waitpid(-1, &status, WNOHANG);
74 wl_list_for_each(p, &child_process_list, link) {
79 if (&p->link == &child_process_list) {
80 weston_log("unknown child process exited\n");
84 wl_list_remove(&p->link);
85 p->cleanup(p, status);
91 weston_output_transform_scale_init(struct weston_output *output,
92 uint32_t transform, uint32_t scale);
95 weston_compositor_build_view_list(struct weston_compositor *compositor);
98 weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode,
99 int32_t scale, enum weston_mode_switch_op op)
101 struct weston_seat *seat;
102 struct wl_resource *resource;
103 pixman_region32_t old_output_region;
104 int ret, notify_mode_changed, notify_scale_changed;
105 int temporary_mode, temporary_scale;
107 if (!output->switch_mode)
110 temporary_mode = (output->original_mode != 0);
111 temporary_scale = (output->current_scale != output->original_scale);
114 notify_mode_changed = 0;
115 notify_scale_changed = 0;
117 case WESTON_MODE_SWITCH_SET_NATIVE:
118 output->native_mode = mode;
119 if (!temporary_mode) {
120 notify_mode_changed = 1;
121 ret = output->switch_mode(output, mode);
126 output->native_scale = scale;
128 notify_scale_changed = 1;
130 case WESTON_MODE_SWITCH_SET_TEMPORARY:
132 output->original_mode = output->native_mode;
133 if (!temporary_scale)
134 output->original_scale = output->native_scale;
136 ret = output->switch_mode(output, mode);
140 output->current_scale = scale;
142 case WESTON_MODE_SWITCH_RESTORE_NATIVE:
143 if (!temporary_mode) {
144 weston_log("already in the native mode\n");
148 notify_mode_changed = (output->original_mode != output->native_mode);
150 ret = output->switch_mode(output, mode);
154 if (output->original_scale != output->native_scale) {
155 notify_scale_changed = 1;
156 scale = output->native_scale;
157 output->original_scale = scale;
159 output->original_mode = 0;
161 output->current_scale = output->native_scale;
164 weston_log("unknown weston_switch_mode_op %d\n", op);
168 pixman_region32_init(&old_output_region);
169 pixman_region32_copy(&old_output_region, &output->region);
171 /* Update output region and transformation matrix */
172 weston_output_transform_scale_init(output, output->transform, output->current_scale);
174 pixman_region32_init(&output->previous_damage);
175 pixman_region32_init_rect(&output->region, output->x, output->y,
176 output->width, output->height);
178 weston_output_update_matrix(output);
180 /* If a pointer falls outside the outputs new geometry, move it to its
181 * lower-right corner */
182 wl_list_for_each(seat, &output->compositor->seat_list, link) {
183 struct weston_pointer *pointer = seat->pointer;
189 x = wl_fixed_to_int(pointer->x);
190 y = wl_fixed_to_int(pointer->y);
192 if (!pixman_region32_contains_point(&old_output_region,
194 pixman_region32_contains_point(&output->region,
198 if (x >= output->x + output->width)
199 x = output->x + output->width - 1;
200 if (y >= output->y + output->height)
201 y = output->y + output->height - 1;
203 pointer->x = wl_fixed_from_int(x);
204 pointer->y = wl_fixed_from_int(y);
207 pixman_region32_fini(&old_output_region);
209 /* notify clients of the changes */
210 if (notify_mode_changed || notify_scale_changed) {
211 wl_resource_for_each(resource, &output->resource_list) {
212 if(notify_mode_changed) {
213 wl_output_send_mode(resource,
214 mode->flags | WL_OUTPUT_MODE_CURRENT,
220 if (notify_scale_changed)
221 wl_output_send_scale(resource, scale);
223 if (wl_resource_get_version(resource) >= 2)
224 wl_output_send_done(resource);
232 weston_watch_process(struct weston_process *process)
234 wl_list_insert(&child_process_list, &process->link);
238 child_client_exec(int sockfd, const char *path)
244 /* do not give our signal mask to the new process */
245 sigfillset(&allsigs);
246 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
248 /* Launch clients as the user. Do not lauch clients with wrong euid.*/
249 if (seteuid(getuid()) == -1) {
250 weston_log("compositor: failed seteuid\n");
254 /* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
255 * non-CLOEXEC fd to pass through exec. */
256 clientfd = dup(sockfd);
257 if (clientfd == -1) {
258 weston_log("compositor: dup failed: %m\n");
262 snprintf(s, sizeof s, "%d", clientfd);
263 setenv("WAYLAND_SOCKET", s, 1);
265 if (execl(path, path, NULL) < 0)
266 weston_log("compositor: executing '%s' failed: %m\n",
270 WL_EXPORT struct wl_client *
271 weston_client_launch(struct weston_compositor *compositor,
272 struct weston_process *proc,
274 weston_process_cleanup_func_t cleanup)
278 struct wl_client *client;
280 weston_log("launching '%s'\n", path);
282 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
283 weston_log("weston_client_launch: "
284 "socketpair failed while launching '%s': %m\n",
293 weston_log("weston_client_launch: "
294 "fork failed while launching '%s': %m\n", path);
299 child_client_exec(sv[1], path);
305 client = wl_client_create(compositor->wl_display, sv[0]);
308 weston_log("weston_client_launch: "
309 "wl_client_create failed while launching '%s'.\n",
315 proc->cleanup = cleanup;
316 weston_watch_process(proc);
322 surface_handle_pending_buffer_destroy(struct wl_listener *listener, void *data)
324 struct weston_surface *surface =
325 container_of(listener, struct weston_surface,
326 pending.buffer_destroy_listener);
328 surface->pending.buffer = NULL;
332 empty_region(pixman_region32_t *region)
334 pixman_region32_fini(region);
335 pixman_region32_init(region);
339 region_init_infinite(pixman_region32_t *region)
341 pixman_region32_init_rect(region, INT32_MIN, INT32_MIN,
342 UINT32_MAX, UINT32_MAX);
345 static struct weston_subsurface *
346 weston_surface_to_subsurface(struct weston_surface *surface);
348 WL_EXPORT struct weston_view *
349 weston_view_create(struct weston_surface *surface)
351 struct weston_view *view;
353 view = calloc(1, sizeof *view);
357 view->surface = surface;
359 /* Assign to surface */
360 wl_list_insert(&surface->views, &view->surface_link);
362 wl_signal_init(&view->destroy_signal);
363 wl_list_init(&view->link);
364 wl_list_init(&view->layer_link);
368 pixman_region32_init(&view->clip);
371 pixman_region32_init(&view->transform.opaque);
373 wl_list_init(&view->geometry.transformation_list);
374 wl_list_insert(&view->geometry.transformation_list,
375 &view->transform.position.link);
376 weston_matrix_init(&view->transform.position.matrix);
377 wl_list_init(&view->geometry.child_list);
378 pixman_region32_init(&view->transform.boundingbox);
379 view->transform.dirty = 1;
386 WL_EXPORT struct weston_surface *
387 weston_surface_create(struct weston_compositor *compositor)
389 struct weston_surface *surface;
391 surface = calloc(1, sizeof *surface);
395 wl_signal_init(&surface->destroy_signal);
397 surface->resource = NULL;
399 surface->compositor = compositor;
400 surface->ref_count = 1;
402 surface->buffer_viewport.transform = WL_OUTPUT_TRANSFORM_NORMAL;
403 surface->buffer_viewport.scale = 1;
404 surface->pending.buffer_viewport = surface->buffer_viewport;
405 surface->output = NULL;
406 surface->pending.newly_attached = 0;
408 pixman_region32_init(&surface->damage);
409 pixman_region32_init(&surface->opaque);
410 region_init_infinite(&surface->input);
412 wl_list_init(&surface->views);
414 wl_list_init(&surface->frame_callback_list);
416 surface->pending.buffer_destroy_listener.notify =
417 surface_handle_pending_buffer_destroy;
418 pixman_region32_init(&surface->pending.damage);
419 pixman_region32_init(&surface->pending.opaque);
420 region_init_infinite(&surface->pending.input);
421 wl_list_init(&surface->pending.frame_callback_list);
423 wl_list_init(&surface->subsurface_list);
424 wl_list_init(&surface->subsurface_list_pending);
430 weston_surface_set_color(struct weston_surface *surface,
431 float red, float green, float blue, float alpha)
433 surface->compositor->renderer->surface_set_color(surface, red, green, blue, alpha);
437 weston_view_to_global_float(struct weston_view *view,
438 float sx, float sy, float *x, float *y)
440 if (view->transform.enabled) {
441 struct weston_vector v = { { sx, sy, 0.0f, 1.0f } };
443 weston_matrix_transform(&view->transform.matrix, &v);
445 if (fabsf(v.f[3]) < 1e-6) {
446 weston_log("warning: numerical instability in "
447 "%s(), divisor = %g\n", __func__,
454 *x = v.f[0] / v.f[3];
455 *y = v.f[1] / v.f[3];
457 *x = sx + view->geometry.x;
458 *y = sy + view->geometry.y;
463 weston_transformed_coord(int width, int height,
464 enum wl_output_transform transform,
466 float sx, float sy, float *bx, float *by)
469 case WL_OUTPUT_TRANSFORM_NORMAL:
474 case WL_OUTPUT_TRANSFORM_FLIPPED:
478 case WL_OUTPUT_TRANSFORM_90:
482 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
486 case WL_OUTPUT_TRANSFORM_180:
490 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
494 case WL_OUTPUT_TRANSFORM_270:
498 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
508 WL_EXPORT pixman_box32_t
509 weston_transformed_rect(int width, int height,
510 enum wl_output_transform transform,
514 float x1, x2, y1, y2;
518 weston_transformed_coord(width, height, transform, scale,
519 rect.x1, rect.y1, &x1, &y1);
520 weston_transformed_coord(width, height, transform, scale,
521 rect.x2, rect.y2, &x2, &y2);
543 weston_transformed_region(int width, int height,
544 enum wl_output_transform transform,
546 pixman_region32_t *src, pixman_region32_t *dest)
548 pixman_box32_t *src_rects, *dest_rects;
551 if (transform == WL_OUTPUT_TRANSFORM_NORMAL && scale == 1) {
553 pixman_region32_copy(dest, src);
557 src_rects = pixman_region32_rectangles(src, &nrects);
558 dest_rects = malloc(nrects * sizeof(*dest_rects));
562 if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
563 memcpy(dest_rects, src_rects, nrects * sizeof(*dest_rects));
565 for (i = 0; i < nrects; i++) {
568 case WL_OUTPUT_TRANSFORM_NORMAL:
569 dest_rects[i].x1 = src_rects[i].x1;
570 dest_rects[i].y1 = src_rects[i].y1;
571 dest_rects[i].x2 = src_rects[i].x2;
572 dest_rects[i].y2 = src_rects[i].y2;
574 case WL_OUTPUT_TRANSFORM_90:
575 dest_rects[i].x1 = height - src_rects[i].y2;
576 dest_rects[i].y1 = src_rects[i].x1;
577 dest_rects[i].x2 = height - src_rects[i].y1;
578 dest_rects[i].y2 = src_rects[i].x2;
580 case WL_OUTPUT_TRANSFORM_180:
581 dest_rects[i].x1 = width - src_rects[i].x2;
582 dest_rects[i].y1 = height - src_rects[i].y2;
583 dest_rects[i].x2 = width - src_rects[i].x1;
584 dest_rects[i].y2 = height - src_rects[i].y1;
586 case WL_OUTPUT_TRANSFORM_270:
587 dest_rects[i].x1 = src_rects[i].y1;
588 dest_rects[i].y1 = width - src_rects[i].x2;
589 dest_rects[i].x2 = src_rects[i].y2;
590 dest_rects[i].y2 = width - src_rects[i].x1;
592 case WL_OUTPUT_TRANSFORM_FLIPPED:
593 dest_rects[i].x1 = width - src_rects[i].x2;
594 dest_rects[i].y1 = src_rects[i].y1;
595 dest_rects[i].x2 = width - src_rects[i].x1;
596 dest_rects[i].y2 = src_rects[i].y2;
598 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
599 dest_rects[i].x1 = height - src_rects[i].y2;
600 dest_rects[i].y1 = width - src_rects[i].x2;
601 dest_rects[i].x2 = height - src_rects[i].y1;
602 dest_rects[i].y2 = width - src_rects[i].x1;
604 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
605 dest_rects[i].x1 = src_rects[i].x1;
606 dest_rects[i].y1 = height - src_rects[i].y2;
607 dest_rects[i].x2 = src_rects[i].x2;
608 dest_rects[i].y2 = height - src_rects[i].y1;
610 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
611 dest_rects[i].x1 = src_rects[i].y1;
612 dest_rects[i].y1 = src_rects[i].x1;
613 dest_rects[i].x2 = src_rects[i].y2;
614 dest_rects[i].y2 = src_rects[i].x2;
621 for (i = 0; i < nrects; i++) {
622 dest_rects[i].x1 *= scale;
623 dest_rects[i].x2 *= scale;
624 dest_rects[i].y1 *= scale;
625 dest_rects[i].y2 *= scale;
629 pixman_region32_clear(dest);
630 pixman_region32_init_rects(dest, dest_rects, nrects);
635 weston_surface_to_buffer_float(struct weston_surface *surface,
636 float sx, float sy, float *bx, float *by)
638 weston_transformed_coord(surface->width,
640 surface->buffer_viewport.transform,
641 surface->buffer_viewport.scale,
646 weston_surface_to_buffer(struct weston_surface *surface,
647 int sx, int sy, int *bx, int *by)
651 weston_transformed_coord(surface->width,
653 surface->buffer_viewport.transform,
654 surface->buffer_viewport.scale,
660 WL_EXPORT pixman_box32_t
661 weston_surface_to_buffer_rect(struct weston_surface *surface,
664 return weston_transformed_rect(surface->width,
666 surface->buffer_viewport.transform,
667 surface->buffer_viewport.scale,
672 weston_view_move_to_plane(struct weston_view *view,
673 struct weston_plane *plane)
675 if (view->plane == plane)
678 weston_view_damage_below(view);
680 weston_surface_damage(view->surface);
684 weston_view_damage_below(struct weston_view *view)
686 pixman_region32_t damage;
688 pixman_region32_init(&damage);
689 pixman_region32_subtract(&damage, &view->transform.boundingbox,
692 pixman_region32_union(&view->plane->damage,
693 &view->plane->damage, &damage);
694 pixman_region32_fini(&damage);
695 weston_view_schedule_repaint(view);
699 weston_surface_update_output_mask(struct weston_surface *es, uint32_t mask)
701 uint32_t different = es->output_mask ^ mask;
702 uint32_t entered = mask & different;
703 uint32_t left = es->output_mask & different;
704 struct weston_output *output;
705 struct wl_resource *resource = NULL;
706 struct wl_client *client;
708 es->output_mask = mask;
709 if (es->resource == NULL)
714 client = wl_resource_get_client(es->resource);
716 wl_list_for_each(output, &es->compositor->output_list, link) {
717 if (1 << output->id & different)
719 wl_resource_find_for_client(&output->resource_list,
721 if (resource == NULL)
723 if (1 << output->id & entered)
724 wl_surface_send_enter(es->resource, resource);
725 if (1 << output->id & left)
726 wl_surface_send_leave(es->resource, resource);
731 weston_surface_assign_output(struct weston_surface *es)
733 struct weston_output *new_output;
734 struct weston_view *view;
735 pixman_region32_t region;
736 uint32_t max, area, mask;
742 pixman_region32_init(®ion);
743 wl_list_for_each(view, &es->views, surface_link) {
747 pixman_region32_intersect(®ion, &view->transform.boundingbox,
748 &view->output->region);
750 e = pixman_region32_extents(®ion);
751 area = (e->x2 - e->x1) * (e->y2 - e->y1);
753 mask |= view->output_mask;
756 new_output = view->output;
760 pixman_region32_fini(®ion);
762 es->output = new_output;
763 weston_surface_update_output_mask(es, mask);
767 weston_view_assign_output(struct weston_view *ev)
769 struct weston_compositor *ec = ev->surface->compositor;
770 struct weston_output *output, *new_output;
771 pixman_region32_t region;
772 uint32_t max, area, mask;
778 pixman_region32_init(®ion);
779 wl_list_for_each(output, &ec->output_list, link) {
780 pixman_region32_intersect(®ion, &ev->transform.boundingbox,
783 e = pixman_region32_extents(®ion);
784 area = (e->x2 - e->x1) * (e->y2 - e->y1);
787 mask |= 1 << output->id;
794 pixman_region32_fini(®ion);
796 ev->output = new_output;
797 ev->output_mask = mask;
799 weston_surface_assign_output(ev->surface);
803 view_compute_bbox(struct weston_view *view, int32_t sx, int32_t sy,
804 int32_t width, int32_t height,
805 pixman_region32_t *bbox)
807 float min_x = HUGE_VALF, min_y = HUGE_VALF;
808 float max_x = -HUGE_VALF, max_y = -HUGE_VALF;
813 { sx + width, sy + height }
818 if (width == 0 || height == 0) {
819 /* avoid rounding empty bbox to 1x1 */
820 pixman_region32_init(bbox);
824 for (i = 0; i < 4; ++i) {
826 weston_view_to_global_float(view, s[i][0], s[i][1], &x, &y);
837 int_x = floorf(min_x);
838 int_y = floorf(min_y);
839 pixman_region32_init_rect(bbox, int_x, int_y,
840 ceilf(max_x) - int_x, ceilf(max_y) - int_y);
844 weston_view_update_transform_disable(struct weston_view *view)
846 view->transform.enabled = 0;
848 /* round off fractions when not transformed */
849 view->geometry.x = roundf(view->geometry.x);
850 view->geometry.y = roundf(view->geometry.y);
852 /* Otherwise identity matrix, but with x and y translation. */
853 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
854 view->transform.position.matrix.d[12] = view->geometry.x;
855 view->transform.position.matrix.d[13] = view->geometry.y;
857 view->transform.matrix = view->transform.position.matrix;
859 view->transform.inverse = view->transform.position.matrix;
860 view->transform.inverse.d[12] = -view->geometry.x;
861 view->transform.inverse.d[13] = -view->geometry.y;
863 pixman_region32_init_rect(&view->transform.boundingbox,
866 view->geometry.width,
867 view->geometry.height);
869 if (view->alpha == 1.0) {
870 pixman_region32_copy(&view->transform.opaque,
871 &view->surface->opaque);
872 pixman_region32_translate(&view->transform.opaque,
879 weston_view_update_transform_enable(struct weston_view *view)
881 struct weston_view *parent = view->geometry.parent;
882 struct weston_matrix *matrix = &view->transform.matrix;
883 struct weston_matrix *inverse = &view->transform.inverse;
884 struct weston_transform *tform;
886 view->transform.enabled = 1;
888 /* Otherwise identity matrix, but with x and y translation. */
889 view->transform.position.matrix.type = WESTON_MATRIX_TRANSFORM_TRANSLATE;
890 view->transform.position.matrix.d[12] = view->geometry.x;
891 view->transform.position.matrix.d[13] = view->geometry.y;
893 weston_matrix_init(matrix);
894 wl_list_for_each(tform, &view->geometry.transformation_list, link)
895 weston_matrix_multiply(matrix, &tform->matrix);
898 weston_matrix_multiply(matrix, &parent->transform.matrix);
900 if (weston_matrix_invert(inverse, matrix) < 0) {
901 /* Oops, bad total transformation, not invertible */
902 weston_log("error: weston_view %p"
903 " transformation not invertible.\n", view);
907 view_compute_bbox(view, 0, 0, view->geometry.width,
908 view->geometry.height,
909 &view->transform.boundingbox);
915 weston_view_update_transform(struct weston_view *view)
917 struct weston_view *parent = view->geometry.parent;
919 if (!view->transform.dirty)
923 weston_view_update_transform(parent);
925 view->transform.dirty = 0;
927 weston_view_damage_below(view);
929 pixman_region32_fini(&view->transform.boundingbox);
930 pixman_region32_fini(&view->transform.opaque);
931 pixman_region32_init(&view->transform.opaque);
933 /* transform.position is always in transformation_list */
934 if (view->geometry.transformation_list.next ==
935 &view->transform.position.link &&
936 view->geometry.transformation_list.prev ==
937 &view->transform.position.link &&
939 weston_view_update_transform_disable(view);
941 if (weston_view_update_transform_enable(view) < 0)
942 weston_view_update_transform_disable(view);
945 weston_view_damage_below(view);
947 weston_view_assign_output(view);
949 wl_signal_emit(&view->surface->compositor->transform_signal,
954 weston_view_geometry_dirty(struct weston_view *view)
956 struct weston_view *child;
959 * The invariant: if view->geometry.dirty, then all views
960 * in view->geometry.child_list have geometry.dirty too.
961 * Corollary: if not parent->geometry.dirty, then all ancestors
965 if (view->transform.dirty)
968 view->transform.dirty = 1;
970 wl_list_for_each(child, &view->geometry.child_list,
971 geometry.parent_link)
972 weston_view_geometry_dirty(child);
976 weston_view_to_global_fixed(struct weston_view *view,
977 wl_fixed_t vx, wl_fixed_t vy,
978 wl_fixed_t *x, wl_fixed_t *y)
982 weston_view_to_global_float(view,
983 wl_fixed_to_double(vx),
984 wl_fixed_to_double(vy),
986 *x = wl_fixed_from_double(xf);
987 *y = wl_fixed_from_double(yf);
991 weston_view_from_global_float(struct weston_view *view,
992 float x, float y, float *vx, float *vy)
994 if (view->transform.enabled) {
995 struct weston_vector v = { { x, y, 0.0f, 1.0f } };
997 weston_matrix_transform(&view->transform.inverse, &v);
999 if (fabsf(v.f[3]) < 1e-6) {
1000 weston_log("warning: numerical instability in "
1001 "weston_view_from_global(), divisor = %g\n",
1008 *vx = v.f[0] / v.f[3];
1009 *vy = v.f[1] / v.f[3];
1011 *vx = x - view->geometry.x;
1012 *vy = y - view->geometry.y;
1017 weston_view_from_global_fixed(struct weston_view *view,
1018 wl_fixed_t x, wl_fixed_t y,
1019 wl_fixed_t *vx, wl_fixed_t *vy)
1023 weston_view_from_global_float(view,
1024 wl_fixed_to_double(x),
1025 wl_fixed_to_double(y),
1027 *vx = wl_fixed_from_double(vxf);
1028 *vy = wl_fixed_from_double(vyf);
1032 weston_view_from_global(struct weston_view *view,
1033 int32_t x, int32_t y, int32_t *vx, int32_t *vy)
1037 weston_view_from_global_float(view, x, y, &vxf, &vyf);
1043 weston_surface_schedule_repaint(struct weston_surface *surface)
1045 struct weston_output *output;
1047 wl_list_for_each(output, &surface->compositor->output_list, link)
1048 if (surface->output_mask & (1 << output->id))
1049 weston_output_schedule_repaint(output);
1053 weston_view_schedule_repaint(struct weston_view *view)
1055 struct weston_output *output;
1057 wl_list_for_each(output, &view->surface->compositor->output_list, link)
1058 if (view->output_mask & (1 << output->id))
1059 weston_output_schedule_repaint(output);
1063 weston_surface_damage(struct weston_surface *surface)
1065 pixman_region32_union_rect(&surface->damage, &surface->damage,
1066 0, 0, surface->width,
1069 weston_surface_schedule_repaint(surface);
1073 weston_view_configure(struct weston_view *view,
1074 float x, float y, int width, int height)
1076 view->geometry.x = x;
1077 view->geometry.y = y;
1078 view->geometry.width = width;
1079 view->geometry.height = height;
1080 weston_view_geometry_dirty(view);
1084 weston_view_set_position(struct weston_view *view, float x, float y)
1086 view->geometry.x = x;
1087 view->geometry.y = y;
1088 weston_view_geometry_dirty(view);
1092 transform_parent_handle_parent_destroy(struct wl_listener *listener,
1095 struct weston_view *view =
1096 container_of(listener, struct weston_view,
1097 geometry.parent_destroy_listener);
1099 weston_view_set_transform_parent(view, NULL);
1103 weston_view_set_transform_parent(struct weston_view *view,
1104 struct weston_view *parent)
1106 if (view->geometry.parent) {
1107 wl_list_remove(&view->geometry.parent_destroy_listener.link);
1108 wl_list_remove(&view->geometry.parent_link);
1111 view->geometry.parent = parent;
1113 view->geometry.parent_destroy_listener.notify =
1114 transform_parent_handle_parent_destroy;
1116 wl_signal_add(&parent->destroy_signal,
1117 &view->geometry.parent_destroy_listener);
1118 wl_list_insert(&parent->geometry.child_list,
1119 &view->geometry.parent_link);
1122 weston_view_geometry_dirty(view);
1126 weston_view_is_mapped(struct weston_view *view)
1135 weston_surface_is_mapped(struct weston_surface *surface)
1137 if (surface->output)
1144 weston_surface_buffer_width(struct weston_surface *surface)
1147 switch (surface->buffer_viewport.transform) {
1148 case WL_OUTPUT_TRANSFORM_90:
1149 case WL_OUTPUT_TRANSFORM_270:
1150 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
1151 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
1152 width = surface->buffer_ref.buffer->height;
1155 width = surface->buffer_ref.buffer->width;
1158 return width / surface->buffer_viewport.scale;
1162 weston_surface_buffer_height(struct weston_surface *surface)
1165 switch (surface->buffer_viewport.transform) {
1166 case WL_OUTPUT_TRANSFORM_90:
1167 case WL_OUTPUT_TRANSFORM_270:
1168 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
1169 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
1170 height = surface->buffer_ref.buffer->width;
1173 height = surface->buffer_ref.buffer->height;
1176 return height / surface->buffer_viewport.scale;
1180 weston_compositor_get_time(void)
1184 gettimeofday(&tv, NULL);
1186 return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1189 WL_EXPORT struct weston_view *
1190 weston_compositor_pick_view(struct weston_compositor *compositor,
1191 wl_fixed_t x, wl_fixed_t y,
1192 wl_fixed_t *vx, wl_fixed_t *vy)
1194 struct weston_view *view;
1196 wl_list_for_each(view, &compositor->view_list, link) {
1197 weston_view_from_global_fixed(view, x, y, vx, vy);
1198 if (pixman_region32_contains_point(&view->surface->input,
1199 wl_fixed_to_int(*vx),
1200 wl_fixed_to_int(*vy),
1209 weston_compositor_repick(struct weston_compositor *compositor)
1211 struct weston_seat *seat;
1213 if (!compositor->session_active)
1216 wl_list_for_each(seat, &compositor->seat_list, link)
1217 weston_seat_repick(seat);
1221 weston_view_unmap(struct weston_view *view)
1223 struct weston_seat *seat;
1225 if (!weston_view_is_mapped(view))
1228 weston_view_damage_below(view);
1229 view->output = NULL;
1231 wl_list_remove(&view->layer_link);
1232 wl_list_init(&view->layer_link);
1233 wl_list_remove(&view->link);
1234 wl_list_init(&view->link);
1235 view->output_mask = 0;
1236 weston_surface_assign_output(view->surface);
1238 if (weston_surface_is_mapped(view->surface))
1241 wl_list_for_each(seat, &view->surface->compositor->seat_list, link) {
1242 if (seat->keyboard && seat->keyboard->focus == view->surface)
1243 weston_keyboard_set_focus(seat->keyboard, NULL);
1244 if (seat->pointer && seat->pointer->focus == view)
1245 weston_pointer_set_focus(seat->pointer,
1247 wl_fixed_from_int(0),
1248 wl_fixed_from_int(0));
1249 if (seat->touch && seat->touch->focus == view)
1250 weston_touch_set_focus(seat, NULL);
1255 weston_surface_unmap(struct weston_surface *surface)
1257 struct weston_view *view;
1259 wl_list_for_each(view, &surface->views, surface_link)
1260 weston_view_unmap(view);
1261 surface->output = NULL;
1264 struct weston_frame_callback {
1265 struct wl_resource *resource;
1266 struct wl_list link;
1270 weston_view_destroy(struct weston_view *view)
1272 wl_signal_emit(&view->destroy_signal, view);
1274 assert(wl_list_empty(&view->geometry.child_list));
1276 if (weston_view_is_mapped(view)) {
1277 weston_view_unmap(view);
1278 weston_compositor_build_view_list(view->surface->compositor);
1281 wl_list_remove(&view->link);
1282 wl_list_remove(&view->layer_link);
1284 pixman_region32_fini(&view->clip);
1285 pixman_region32_fini(&view->transform.boundingbox);
1287 weston_view_set_transform_parent(view, NULL);
1289 wl_list_remove(&view->surface_link);
1295 weston_surface_destroy(struct weston_surface *surface)
1297 struct weston_frame_callback *cb, *next;
1298 struct weston_view *ev, *nv;
1300 if (--surface->ref_count > 0)
1303 wl_signal_emit(&surface->destroy_signal, &surface->resource);
1305 assert(wl_list_empty(&surface->subsurface_list_pending));
1306 assert(wl_list_empty(&surface->subsurface_list));
1308 wl_list_for_each_safe(ev, nv, &surface->views, surface_link)
1309 weston_view_destroy(ev);
1311 wl_list_for_each_safe(cb, next,
1312 &surface->pending.frame_callback_list, link)
1313 wl_resource_destroy(cb->resource);
1315 pixman_region32_fini(&surface->pending.input);
1316 pixman_region32_fini(&surface->pending.opaque);
1317 pixman_region32_fini(&surface->pending.damage);
1319 if (surface->pending.buffer)
1320 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
1322 weston_buffer_reference(&surface->buffer_ref, NULL);
1324 pixman_region32_fini(&surface->damage);
1325 pixman_region32_fini(&surface->opaque);
1326 pixman_region32_fini(&surface->input);
1328 wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link)
1329 wl_resource_destroy(cb->resource);
1335 destroy_surface(struct wl_resource *resource)
1337 struct weston_surface *surface = wl_resource_get_user_data(resource);
1339 /* Set the resource to NULL, since we don't want to leave a
1340 * dangling pointer if the surface was refcounted and survives
1341 * the weston_surface_destroy() call. */
1342 surface->resource = NULL;
1343 weston_surface_destroy(surface);
1347 weston_buffer_destroy_handler(struct wl_listener *listener, void *data)
1349 struct weston_buffer *buffer =
1350 container_of(listener, struct weston_buffer, destroy_listener);
1352 wl_signal_emit(&buffer->destroy_signal, buffer);
1356 struct weston_buffer *
1357 weston_buffer_from_resource(struct wl_resource *resource)
1359 struct weston_buffer *buffer;
1360 struct wl_listener *listener;
1362 listener = wl_resource_get_destroy_listener(resource,
1363 weston_buffer_destroy_handler);
1366 return container_of(listener, struct weston_buffer,
1369 buffer = zalloc(sizeof *buffer);
1373 buffer->resource = resource;
1374 wl_signal_init(&buffer->destroy_signal);
1375 buffer->destroy_listener.notify = weston_buffer_destroy_handler;
1376 buffer->y_inverted = 1;
1377 wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
1383 weston_buffer_reference_handle_destroy(struct wl_listener *listener,
1386 struct weston_buffer_reference *ref =
1387 container_of(listener, struct weston_buffer_reference,
1390 assert((struct weston_buffer *)data == ref->buffer);
1395 weston_buffer_reference(struct weston_buffer_reference *ref,
1396 struct weston_buffer *buffer)
1398 if (ref->buffer && buffer != ref->buffer) {
1399 ref->buffer->busy_count--;
1400 if (ref->buffer->busy_count == 0) {
1401 assert(wl_resource_get_client(ref->buffer->resource));
1402 wl_resource_queue_event(ref->buffer->resource,
1405 wl_list_remove(&ref->destroy_listener.link);
1408 if (buffer && buffer != ref->buffer) {
1409 buffer->busy_count++;
1410 wl_signal_add(&buffer->destroy_signal,
1411 &ref->destroy_listener);
1414 ref->buffer = buffer;
1415 ref->destroy_listener.notify = weston_buffer_reference_handle_destroy;
1419 weston_surface_attach(struct weston_surface *surface,
1420 struct weston_buffer *buffer)
1422 weston_buffer_reference(&surface->buffer_ref, buffer);
1425 if (weston_surface_is_mapped(surface))
1426 weston_surface_unmap(surface);
1429 surface->compositor->renderer->attach(surface, buffer);
1433 weston_view_restack(struct weston_view *view, struct wl_list *below)
1435 wl_list_remove(&view->layer_link);
1436 wl_list_insert(below, &view->layer_link);
1437 weston_view_damage_below(view);
1438 weston_surface_damage(view->surface);
1442 weston_compositor_damage_all(struct weston_compositor *compositor)
1444 struct weston_output *output;
1446 wl_list_for_each(output, &compositor->output_list, link)
1447 weston_output_damage(output);
1451 weston_output_damage(struct weston_output *output)
1453 struct weston_compositor *compositor = output->compositor;
1455 pixman_region32_union(&compositor->primary_plane.damage,
1456 &compositor->primary_plane.damage,
1458 weston_output_schedule_repaint(output);
1462 surface_flush_damage(struct weston_surface *surface)
1464 if (surface->buffer_ref.buffer &&
1465 wl_shm_buffer_get(surface->buffer_ref.buffer->resource))
1466 surface->compositor->renderer->flush_damage(surface);
1468 empty_region(&surface->damage);
1472 view_accumulate_damage(struct weston_view *view,
1473 pixman_region32_t *opaque)
1475 pixman_region32_t damage;
1477 pixman_region32_init(&damage);
1478 if (view->transform.enabled) {
1479 pixman_box32_t *extents;
1481 extents = pixman_region32_extents(&view->surface->damage);
1482 view_compute_bbox(view, extents->x1, extents->y1,
1483 extents->x2 - extents->x1,
1484 extents->y2 - extents->y1,
1486 pixman_region32_translate(&damage,
1490 pixman_region32_copy(&damage, &view->surface->damage);
1491 pixman_region32_translate(&damage,
1492 view->geometry.x - view->plane->x,
1493 view->geometry.y - view->plane->y);
1496 pixman_region32_subtract(&damage, &damage, opaque);
1497 pixman_region32_union(&view->plane->damage,
1498 &view->plane->damage, &damage);
1499 pixman_region32_fini(&damage);
1500 pixman_region32_copy(&view->clip, opaque);
1501 pixman_region32_union(opaque, opaque, &view->transform.opaque);
1505 compositor_accumulate_damage(struct weston_compositor *ec)
1507 struct weston_plane *plane;
1508 struct weston_view *ev;
1509 pixman_region32_t opaque, clip;
1511 pixman_region32_init(&clip);
1513 wl_list_for_each(plane, &ec->plane_list, link) {
1514 pixman_region32_copy(&plane->clip, &clip);
1516 pixman_region32_init(&opaque);
1518 wl_list_for_each(ev, &ec->view_list, link) {
1519 if (ev->plane != plane)
1522 view_accumulate_damage(ev, &opaque);
1525 pixman_region32_union(&clip, &clip, &opaque);
1526 pixman_region32_fini(&opaque);
1529 pixman_region32_fini(&clip);
1531 wl_list_for_each(ev, &ec->view_list, link)
1532 ev->surface->touched = 0;
1534 wl_list_for_each(ev, &ec->view_list, link) {
1535 if (ev->surface->touched)
1537 ev->surface->touched = 1;
1539 surface_flush_damage(ev->surface);
1541 /* Both the renderer and the backend have seen the buffer
1542 * by now. If renderer needs the buffer, it has its own
1543 * reference set. If the backend wants to keep the buffer
1544 * around for migrating the surface into a non-primary plane
1545 * later, keep_buffer is true. Otherwise, drop the core
1546 * reference now, and allow early buffer release. This enables
1547 * clients to use single-buffering.
1549 if (!ev->surface->keep_buffer)
1550 weston_buffer_reference(&ev->surface->buffer_ref, NULL);
1555 surface_stash_subsurface_views(struct weston_surface *surface)
1557 struct weston_subsurface *sub;
1559 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
1560 if (sub->surface == surface)
1563 wl_list_insert_list(&sub->unused_views, &sub->surface->views);
1564 wl_list_init(&sub->surface->views);
1566 surface_stash_subsurface_views(sub->surface);
1571 surface_free_unused_subsurface_views(struct weston_surface *surface)
1573 struct weston_subsurface *sub;
1574 struct weston_view *view, *nv;
1576 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
1577 if (sub->surface == surface)
1580 wl_list_for_each_safe(view, nv, &sub->unused_views, surface_link)
1581 weston_view_destroy(view);
1583 surface_free_unused_subsurface_views(sub->surface);
1588 view_list_add_subsurface_view(struct weston_compositor *compositor,
1589 struct weston_subsurface *sub,
1590 struct weston_view *parent)
1592 struct weston_subsurface *child;
1593 struct weston_view *view = NULL, *iv;
1595 wl_list_for_each(iv, &sub->unused_views, surface_link) {
1596 if (iv->geometry.parent == parent) {
1603 /* Put it back in the surface's list of views */
1604 wl_list_remove(&view->surface_link);
1605 wl_list_insert(&sub->surface->views, &view->surface_link);
1607 view = weston_view_create(sub->surface);
1608 weston_view_configure(view,
1611 sub->surface->width,
1612 sub->surface->height);
1613 weston_view_set_transform_parent(view, parent);
1616 weston_view_update_transform(view);
1618 if (wl_list_empty(&sub->surface->subsurface_list)) {
1619 wl_list_insert(compositor->view_list.prev, &view->link);
1623 wl_list_for_each(child, &sub->surface->subsurface_list, parent_link) {
1624 if (child->surface == sub->surface)
1625 wl_list_insert(compositor->view_list.prev, &view->link);
1627 view_list_add_subsurface_view(compositor, child, view);
1632 view_list_add(struct weston_compositor *compositor,
1633 struct weston_view *view)
1635 struct weston_subsurface *sub;
1637 weston_view_update_transform(view);
1639 if (wl_list_empty(&view->surface->subsurface_list)) {
1640 wl_list_insert(compositor->view_list.prev, &view->link);
1644 wl_list_for_each(sub, &view->surface->subsurface_list, parent_link) {
1645 if (sub->surface == view->surface)
1646 wl_list_insert(compositor->view_list.prev, &view->link);
1648 view_list_add_subsurface_view(compositor, sub, view);
1653 weston_compositor_build_view_list(struct weston_compositor *compositor)
1655 struct weston_view *view;
1656 struct weston_layer *layer;
1658 wl_list_for_each(layer, &compositor->layer_list, link)
1659 wl_list_for_each(view, &layer->view_list, layer_link)
1660 surface_stash_subsurface_views(view->surface);
1662 wl_list_init(&compositor->view_list);
1663 wl_list_for_each(layer, &compositor->layer_list, link) {
1664 wl_list_for_each(view, &layer->view_list, layer_link) {
1665 view_list_add(compositor, view);
1669 wl_list_for_each(layer, &compositor->layer_list, link)
1670 wl_list_for_each(view, &layer->view_list, layer_link)
1671 surface_free_unused_subsurface_views(view->surface);
1675 weston_output_repaint(struct weston_output *output, uint32_t msecs)
1677 struct weston_compositor *ec = output->compositor;
1678 struct weston_view *ev;
1679 struct weston_animation *animation, *next;
1680 struct weston_frame_callback *cb, *cnext;
1681 struct wl_list frame_callback_list;
1682 pixman_region32_t output_damage;
1685 /* Rebuild the surface list and update surface transforms up front. */
1686 weston_compositor_build_view_list(ec);
1688 if (output->assign_planes && !output->disable_planes)
1689 output->assign_planes(output);
1691 wl_list_for_each(ev, &ec->view_list, link)
1692 weston_view_move_to_plane(ev, &ec->primary_plane);
1694 wl_list_init(&frame_callback_list);
1695 wl_list_for_each(ev, &ec->view_list, link) {
1696 /* Note: This operation is safe to do multiple times on the
1699 if (ev->surface->output == output) {
1700 wl_list_insert_list(&frame_callback_list,
1701 &ev->surface->frame_callback_list);
1702 wl_list_init(&ev->surface->frame_callback_list);
1706 compositor_accumulate_damage(ec);
1708 pixman_region32_init(&output_damage);
1709 pixman_region32_intersect(&output_damage,
1710 &ec->primary_plane.damage, &output->region);
1711 pixman_region32_subtract(&output_damage,
1712 &output_damage, &ec->primary_plane.clip);
1715 weston_output_update_matrix(output);
1717 r = output->repaint(output, &output_damage);
1719 pixman_region32_fini(&output_damage);
1721 output->repaint_needed = 0;
1723 weston_compositor_repick(ec);
1724 wl_event_loop_dispatch(ec->input_loop, 0);
1726 wl_list_for_each_safe(cb, cnext, &frame_callback_list, link) {
1727 wl_callback_send_done(cb->resource, msecs);
1728 wl_resource_destroy(cb->resource);
1731 wl_list_for_each_safe(animation, next, &output->animation_list, link) {
1732 animation->frame_counter++;
1733 animation->frame(animation, output, msecs);
1740 weston_compositor_read_input(int fd, uint32_t mask, void *data)
1742 struct weston_compositor *compositor = data;
1744 wl_event_loop_dispatch(compositor->input_loop, 0);
1750 weston_output_finish_frame(struct weston_output *output, uint32_t msecs)
1752 struct weston_compositor *compositor = output->compositor;
1753 struct wl_event_loop *loop =
1754 wl_display_get_event_loop(compositor->wl_display);
1757 output->frame_time = msecs;
1759 if (output->repaint_needed &&
1760 compositor->state != WESTON_COMPOSITOR_SLEEPING &&
1761 compositor->state != WESTON_COMPOSITOR_OFFSCREEN) {
1762 r = weston_output_repaint(output, msecs);
1767 output->repaint_scheduled = 0;
1768 if (compositor->input_loop_source)
1771 fd = wl_event_loop_get_fd(compositor->input_loop);
1772 compositor->input_loop_source =
1773 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
1774 weston_compositor_read_input, compositor);
1778 idle_repaint(void *data)
1780 struct weston_output *output = data;
1782 output->start_repaint_loop(output);
1786 weston_layer_init(struct weston_layer *layer, struct wl_list *below)
1788 wl_list_init(&layer->view_list);
1790 wl_list_insert(below, &layer->link);
1794 weston_output_schedule_repaint(struct weston_output *output)
1796 struct weston_compositor *compositor = output->compositor;
1797 struct wl_event_loop *loop;
1799 if (compositor->state == WESTON_COMPOSITOR_SLEEPING ||
1800 compositor->state == WESTON_COMPOSITOR_OFFSCREEN)
1803 loop = wl_display_get_event_loop(compositor->wl_display);
1804 output->repaint_needed = 1;
1805 if (output->repaint_scheduled)
1808 wl_event_loop_add_idle(loop, idle_repaint, output);
1809 output->repaint_scheduled = 1;
1811 if (compositor->input_loop_source) {
1812 wl_event_source_remove(compositor->input_loop_source);
1813 compositor->input_loop_source = NULL;
1818 weston_compositor_schedule_repaint(struct weston_compositor *compositor)
1820 struct weston_output *output;
1822 wl_list_for_each(output, &compositor->output_list, link)
1823 weston_output_schedule_repaint(output);
1827 surface_destroy(struct wl_client *client, struct wl_resource *resource)
1829 wl_resource_destroy(resource);
1833 surface_attach(struct wl_client *client,
1834 struct wl_resource *resource,
1835 struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
1837 struct weston_surface *surface = wl_resource_get_user_data(resource);
1838 struct weston_buffer *buffer = NULL;
1840 if (buffer_resource) {
1841 buffer = weston_buffer_from_resource(buffer_resource);
1842 if (buffer == NULL) {
1843 wl_client_post_no_memory(client);
1848 /* Attach, attach, without commit in between does not send
1849 * wl_buffer.release. */
1850 if (surface->pending.buffer)
1851 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
1853 surface->pending.sx = sx;
1854 surface->pending.sy = sy;
1855 surface->pending.buffer = buffer;
1856 surface->pending.newly_attached = 1;
1858 wl_signal_add(&buffer->destroy_signal,
1859 &surface->pending.buffer_destroy_listener);
1864 surface_damage(struct wl_client *client,
1865 struct wl_resource *resource,
1866 int32_t x, int32_t y, int32_t width, int32_t height)
1868 struct weston_surface *surface = wl_resource_get_user_data(resource);
1870 pixman_region32_union_rect(&surface->pending.damage,
1871 &surface->pending.damage,
1872 x, y, width, height);
1876 destroy_frame_callback(struct wl_resource *resource)
1878 struct weston_frame_callback *cb = wl_resource_get_user_data(resource);
1880 wl_list_remove(&cb->link);
1885 surface_frame(struct wl_client *client,
1886 struct wl_resource *resource, uint32_t callback)
1888 struct weston_frame_callback *cb;
1889 struct weston_surface *surface = wl_resource_get_user_data(resource);
1891 cb = malloc(sizeof *cb);
1893 wl_resource_post_no_memory(resource);
1897 cb->resource = wl_resource_create(client, &wl_callback_interface, 1,
1899 if (cb->resource == NULL) {
1901 wl_resource_post_no_memory(resource);
1905 wl_resource_set_implementation(cb->resource, NULL, cb,
1906 destroy_frame_callback);
1908 wl_list_insert(surface->pending.frame_callback_list.prev, &cb->link);
1912 surface_set_opaque_region(struct wl_client *client,
1913 struct wl_resource *resource,
1914 struct wl_resource *region_resource)
1916 struct weston_surface *surface = wl_resource_get_user_data(resource);
1917 struct weston_region *region;
1919 if (region_resource) {
1920 region = wl_resource_get_user_data(region_resource);
1921 pixman_region32_copy(&surface->pending.opaque,
1924 empty_region(&surface->pending.opaque);
1929 surface_set_input_region(struct wl_client *client,
1930 struct wl_resource *resource,
1931 struct wl_resource *region_resource)
1933 struct weston_surface *surface = wl_resource_get_user_data(resource);
1934 struct weston_region *region;
1936 if (region_resource) {
1937 region = wl_resource_get_user_data(region_resource);
1938 pixman_region32_copy(&surface->pending.input,
1941 pixman_region32_fini(&surface->pending.input);
1942 region_init_infinite(&surface->pending.input);
1947 weston_surface_commit_subsurface_order(struct weston_surface *surface)
1949 struct weston_subsurface *sub;
1951 wl_list_for_each_reverse(sub, &surface->subsurface_list_pending,
1952 parent_link_pending) {
1953 wl_list_remove(&sub->parent_link);
1954 wl_list_insert(&surface->subsurface_list, &sub->parent_link);
1959 weston_surface_commit(struct weston_surface *surface)
1961 struct weston_view *view;
1962 pixman_region32_t opaque;
1964 /* wl_surface.set_buffer_transform */
1965 /* wl_surface.set_buffer_scale */
1966 surface->buffer_viewport = surface->pending.buffer_viewport;
1968 /* wl_surface.attach */
1969 if (surface->pending.buffer || surface->pending.newly_attached)
1970 weston_surface_attach(surface, surface->pending.buffer);
1973 surface->height = 0;
1974 if (surface->buffer_ref.buffer) {
1975 /* This already includes the buffer scale */
1976 surface->width = weston_surface_buffer_width(surface);
1977 surface->height = weston_surface_buffer_height(surface);
1980 if (surface->configure && surface->pending.newly_attached)
1981 surface->configure(surface,
1982 surface->pending.sx, surface->pending.sy,
1983 surface->width, surface->height);
1985 if (surface->pending.buffer)
1986 wl_list_remove(&surface->pending.buffer_destroy_listener.link);
1987 surface->pending.buffer = NULL;
1988 surface->pending.sx = 0;
1989 surface->pending.sy = 0;
1990 surface->pending.newly_attached = 0;
1992 /* wl_surface.damage */
1993 pixman_region32_union(&surface->damage, &surface->damage,
1994 &surface->pending.damage);
1995 pixman_region32_intersect_rect(&surface->damage, &surface->damage,
1999 empty_region(&surface->pending.damage);
2001 /* wl_surface.set_opaque_region */
2002 pixman_region32_init_rect(&opaque, 0, 0,
2005 pixman_region32_intersect(&opaque,
2006 &opaque, &surface->pending.opaque);
2008 if (!pixman_region32_equal(&opaque, &surface->opaque)) {
2009 pixman_region32_copy(&surface->opaque, &opaque);
2010 wl_list_for_each(view, &surface->views, surface_link)
2011 weston_view_geometry_dirty(view);
2014 pixman_region32_fini(&opaque);
2016 /* wl_surface.set_input_region */
2017 pixman_region32_fini(&surface->input);
2018 pixman_region32_init_rect(&surface->input, 0, 0,
2021 pixman_region32_intersect(&surface->input,
2022 &surface->input, &surface->pending.input);
2024 /* wl_surface.frame */
2025 wl_list_insert_list(&surface->frame_callback_list,
2026 &surface->pending.frame_callback_list);
2027 wl_list_init(&surface->pending.frame_callback_list);
2029 weston_surface_commit_subsurface_order(surface);
2031 weston_surface_schedule_repaint(surface);
2035 weston_subsurface_commit(struct weston_subsurface *sub);
2038 weston_subsurface_parent_commit(struct weston_subsurface *sub,
2039 int parent_is_synchronized);
2042 surface_commit(struct wl_client *client, struct wl_resource *resource)
2044 struct weston_surface *surface = wl_resource_get_user_data(resource);
2045 struct weston_subsurface *sub = weston_surface_to_subsurface(surface);
2048 weston_subsurface_commit(sub);
2052 weston_surface_commit(surface);
2054 wl_list_for_each(sub, &surface->subsurface_list, parent_link) {
2055 if (sub->surface != surface)
2056 weston_subsurface_parent_commit(sub, 0);
2061 surface_set_buffer_transform(struct wl_client *client,
2062 struct wl_resource *resource, int transform)
2064 struct weston_surface *surface = wl_resource_get_user_data(resource);
2066 surface->pending.buffer_viewport.transform = transform;
2070 surface_set_buffer_scale(struct wl_client *client,
2071 struct wl_resource *resource,
2074 struct weston_surface *surface = wl_resource_get_user_data(resource);
2076 surface->pending.buffer_viewport.scale = scale;
2079 static const struct wl_surface_interface surface_interface = {
2084 surface_set_opaque_region,
2085 surface_set_input_region,
2087 surface_set_buffer_transform,
2088 surface_set_buffer_scale
2092 compositor_create_surface(struct wl_client *client,
2093 struct wl_resource *resource, uint32_t id)
2095 struct weston_compositor *ec = wl_resource_get_user_data(resource);
2096 struct weston_surface *surface;
2098 surface = weston_surface_create(ec);
2099 if (surface == NULL) {
2100 wl_resource_post_no_memory(resource);
2105 wl_resource_create(client, &wl_surface_interface,
2106 wl_resource_get_version(resource), id);
2107 if (surface->resource == NULL) {
2108 weston_surface_destroy(surface);
2109 wl_resource_post_no_memory(resource);
2112 wl_resource_set_implementation(surface->resource, &surface_interface,
2113 surface, destroy_surface);
2117 destroy_region(struct wl_resource *resource)
2119 struct weston_region *region = wl_resource_get_user_data(resource);
2121 pixman_region32_fini(®ion->region);
2126 region_destroy(struct wl_client *client, struct wl_resource *resource)
2128 wl_resource_destroy(resource);
2132 region_add(struct wl_client *client, struct wl_resource *resource,
2133 int32_t x, int32_t y, int32_t width, int32_t height)
2135 struct weston_region *region = wl_resource_get_user_data(resource);
2137 pixman_region32_union_rect(®ion->region, ®ion->region,
2138 x, y, width, height);
2142 region_subtract(struct wl_client *client, struct wl_resource *resource,
2143 int32_t x, int32_t y, int32_t width, int32_t height)
2145 struct weston_region *region = wl_resource_get_user_data(resource);
2146 pixman_region32_t rect;
2148 pixman_region32_init_rect(&rect, x, y, width, height);
2149 pixman_region32_subtract(®ion->region, ®ion->region, &rect);
2150 pixman_region32_fini(&rect);
2153 static const struct wl_region_interface region_interface = {
2160 compositor_create_region(struct wl_client *client,
2161 struct wl_resource *resource, uint32_t id)
2163 struct weston_region *region;
2165 region = malloc(sizeof *region);
2166 if (region == NULL) {
2167 wl_resource_post_no_memory(resource);
2171 pixman_region32_init(®ion->region);
2174 wl_resource_create(client, &wl_region_interface, 1, id);
2175 if (region->resource == NULL) {
2177 wl_resource_post_no_memory(resource);
2180 wl_resource_set_implementation(region->resource, ®ion_interface,
2181 region, destroy_region);
2184 static const struct wl_compositor_interface compositor_interface = {
2185 compositor_create_surface,
2186 compositor_create_region
2190 weston_subsurface_commit_from_cache(struct weston_subsurface *sub)
2192 struct weston_surface *surface = sub->surface;
2193 struct weston_view *view;
2194 pixman_region32_t opaque;
2196 /* wl_surface.set_buffer_transform */
2197 /* wl_surface.set_buffer_scale */
2198 surface->buffer_viewport = sub->cached.buffer_viewport;
2200 /* wl_surface.attach */
2201 if (sub->cached.buffer_ref.buffer || sub->cached.newly_attached)
2202 weston_surface_attach(surface, sub->cached.buffer_ref.buffer);
2203 weston_buffer_reference(&sub->cached.buffer_ref, NULL);
2206 surface->height = 0;
2207 if (surface->buffer_ref.buffer) {
2208 surface->width = weston_surface_buffer_width(surface);
2209 surface->height = weston_surface_buffer_height(surface);
2212 if (surface->configure && sub->cached.newly_attached)
2213 surface->configure(surface, sub->cached.sx, sub->cached.sy,
2214 surface->width, surface->height);
2217 sub->cached.newly_attached = 0;
2219 /* wl_surface.damage */
2220 pixman_region32_union(&surface->damage, &surface->damage,
2221 &sub->cached.damage);
2222 pixman_region32_intersect_rect(&surface->damage, &surface->damage,
2226 empty_region(&sub->cached.damage);
2228 /* wl_surface.set_opaque_region */
2229 pixman_region32_init_rect(&opaque, 0, 0,
2232 pixman_region32_intersect(&opaque,
2233 &opaque, &sub->cached.opaque);
2235 if (!pixman_region32_equal(&opaque, &surface->opaque)) {
2236 pixman_region32_copy(&surface->opaque, &opaque);
2237 wl_list_for_each(view, &surface->views, surface_link)
2238 weston_view_geometry_dirty(view);
2241 pixman_region32_fini(&opaque);
2243 /* wl_surface.set_input_region */
2244 pixman_region32_fini(&surface->input);
2245 pixman_region32_init_rect(&surface->input, 0, 0,
2248 pixman_region32_intersect(&surface->input,
2249 &surface->input, &sub->cached.input);
2251 /* wl_surface.frame */
2252 wl_list_insert_list(&surface->frame_callback_list,
2253 &sub->cached.frame_callback_list);
2254 wl_list_init(&sub->cached.frame_callback_list);
2256 weston_surface_commit_subsurface_order(surface);
2258 weston_surface_schedule_repaint(surface);
2260 sub->cached.has_data = 0;
2264 weston_subsurface_commit_to_cache(struct weston_subsurface *sub)
2266 struct weston_surface *surface = sub->surface;
2269 * If this commit would cause the surface to move by the
2270 * attach(dx, dy) parameters, the old damage region must be
2271 * translated to correspond to the new surface coordinate system
2274 pixman_region32_translate(&sub->cached.damage,
2275 -surface->pending.sx, -surface->pending.sy);
2276 pixman_region32_union(&sub->cached.damage, &sub->cached.damage,
2277 &surface->pending.damage);
2278 empty_region(&surface->pending.damage);
2280 if (surface->pending.newly_attached) {
2281 sub->cached.newly_attached = 1;
2282 weston_buffer_reference(&sub->cached.buffer_ref,
2283 surface->pending.buffer);
2285 sub->cached.sx += surface->pending.sx;
2286 sub->cached.sy += surface->pending.sy;
2287 surface->pending.sx = 0;
2288 surface->pending.sy = 0;
2289 surface->pending.newly_attached = 0;
2291 sub->cached.buffer_viewport = surface->pending.buffer_viewport;
2293 pixman_region32_copy(&sub->cached.opaque, &surface->pending.opaque);
2295 pixman_region32_copy(&sub->cached.input, &surface->pending.input);
2297 wl_list_insert_list(&sub->cached.frame_callback_list,
2298 &surface->pending.frame_callback_list);
2299 wl_list_init(&surface->pending.frame_callback_list);
2301 sub->cached.has_data = 1;
2305 weston_subsurface_is_synchronized(struct weston_subsurface *sub)
2308 if (sub->synchronized)
2314 sub = weston_surface_to_subsurface(sub->parent);
2321 weston_subsurface_commit(struct weston_subsurface *sub)
2323 struct weston_surface *surface = sub->surface;
2324 struct weston_subsurface *tmp;
2326 /* Recursive check for effectively synchronized. */
2327 if (weston_subsurface_is_synchronized(sub)) {
2328 weston_subsurface_commit_to_cache(sub);
2330 if (sub->cached.has_data) {
2331 /* flush accumulated state from cache */
2332 weston_subsurface_commit_to_cache(sub);
2333 weston_subsurface_commit_from_cache(sub);
2335 weston_surface_commit(surface);
2338 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
2339 if (tmp->surface != surface)
2340 weston_subsurface_parent_commit(tmp, 0);
2346 weston_subsurface_synchronized_commit(struct weston_subsurface *sub)
2348 struct weston_surface *surface = sub->surface;
2349 struct weston_subsurface *tmp;
2351 /* From now on, commit_from_cache the whole sub-tree, regardless of
2352 * the synchronized mode of each child. This sub-surface or some
2353 * of its ancestors were synchronized, so we are synchronized
2357 if (sub->cached.has_data)
2358 weston_subsurface_commit_from_cache(sub);
2360 wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
2361 if (tmp->surface != surface)
2362 weston_subsurface_parent_commit(tmp, 1);
2367 weston_subsurface_parent_commit(struct weston_subsurface *sub,
2368 int parent_is_synchronized)
2370 struct weston_view *view;
2371 if (sub->position.set) {
2372 wl_list_for_each(view, &sub->surface->views, surface_link)
2373 weston_view_set_position(view,
2377 sub->position.set = 0;
2380 if (parent_is_synchronized || sub->synchronized)
2381 weston_subsurface_synchronized_commit(sub);
2385 subsurface_configure(struct weston_surface *surface, int32_t dx, int32_t dy,
2386 int32_t width, int32_t height)
2388 struct weston_compositor *compositor = surface->compositor;
2389 struct weston_view *view;
2391 wl_list_for_each(view, &surface->views, surface_link)
2392 weston_view_configure(view,
2393 view->geometry.x + dx,
2394 view->geometry.y + dy,
2397 /* No need to check parent mappedness, because if parent is not
2398 * mapped, parent is not in a visible layer, so this sub-surface
2399 * will not be drawn either.
2401 if (!weston_surface_is_mapped(surface)) {
2402 /* Cannot call weston_surface_update_transform(),
2403 * because that would call it also for the parent surface,
2404 * which might not be mapped yet. That would lead to
2405 * inconsistent state, where the window could never be
2408 * Instead just assing any output, to make
2409 * weston_surface_is_mapped() return true, so that when the
2410 * parent surface does get mapped, this one will get
2411 * included, too. See surface_list_add().
2413 assert(!wl_list_empty(&compositor->output_list));
2414 surface->output = container_of(compositor->output_list.next,
2415 struct weston_output, link);
2419 static struct weston_subsurface *
2420 weston_surface_to_subsurface(struct weston_surface *surface)
2422 if (surface->configure == subsurface_configure)
2423 return surface->configure_private;
2428 WL_EXPORT struct weston_surface *
2429 weston_surface_get_main_surface(struct weston_surface *surface)
2431 struct weston_subsurface *sub;
2433 while (surface && (sub = weston_surface_to_subsurface(surface)))
2434 surface = sub->parent;
2440 subsurface_set_position(struct wl_client *client,
2441 struct wl_resource *resource, int32_t x, int32_t y)
2443 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2448 sub->position.x = x;
2449 sub->position.y = y;
2450 sub->position.set = 1;
2453 static struct weston_subsurface *
2454 subsurface_from_surface(struct weston_surface *surface)
2456 struct weston_subsurface *sub;
2458 sub = weston_surface_to_subsurface(surface);
2462 wl_list_for_each(sub, &surface->subsurface_list, parent_link)
2463 if (sub->surface == surface)
2469 static struct weston_subsurface *
2470 subsurface_sibling_check(struct weston_subsurface *sub,
2471 struct weston_surface *surface,
2472 const char *request)
2474 struct weston_subsurface *sibling;
2476 sibling = subsurface_from_surface(surface);
2479 wl_resource_post_error(sub->resource,
2480 WL_SUBSURFACE_ERROR_BAD_SURFACE,
2481 "%s: wl_surface@%d is not a parent or sibling",
2482 request, wl_resource_get_id(surface->resource));
2486 if (sibling->parent != sub->parent) {
2487 wl_resource_post_error(sub->resource,
2488 WL_SUBSURFACE_ERROR_BAD_SURFACE,
2489 "%s: wl_surface@%d has a different parent",
2490 request, wl_resource_get_id(surface->resource));
2498 subsurface_place_above(struct wl_client *client,
2499 struct wl_resource *resource,
2500 struct wl_resource *sibling_resource)
2502 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2503 struct weston_surface *surface =
2504 wl_resource_get_user_data(sibling_resource);
2505 struct weston_subsurface *sibling;
2510 sibling = subsurface_sibling_check(sub, surface, "place_above");
2514 wl_list_remove(&sub->parent_link_pending);
2515 wl_list_insert(sibling->parent_link_pending.prev,
2516 &sub->parent_link_pending);
2520 subsurface_place_below(struct wl_client *client,
2521 struct wl_resource *resource,
2522 struct wl_resource *sibling_resource)
2524 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2525 struct weston_surface *surface =
2526 wl_resource_get_user_data(sibling_resource);
2527 struct weston_subsurface *sibling;
2532 sibling = subsurface_sibling_check(sub, surface, "place_below");
2536 wl_list_remove(&sub->parent_link_pending);
2537 wl_list_insert(&sibling->parent_link_pending,
2538 &sub->parent_link_pending);
2542 subsurface_set_sync(struct wl_client *client, struct wl_resource *resource)
2544 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2547 sub->synchronized = 1;
2551 subsurface_set_desync(struct wl_client *client, struct wl_resource *resource)
2553 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2555 if (sub && sub->synchronized) {
2556 sub->synchronized = 0;
2558 /* If sub became effectively desynchronized, flush. */
2559 if (!weston_subsurface_is_synchronized(sub))
2560 weston_subsurface_synchronized_commit(sub);
2565 weston_subsurface_cache_init(struct weston_subsurface *sub)
2567 pixman_region32_init(&sub->cached.damage);
2568 pixman_region32_init(&sub->cached.opaque);
2569 pixman_region32_init(&sub->cached.input);
2570 wl_list_init(&sub->cached.frame_callback_list);
2571 sub->cached.buffer_ref.buffer = NULL;
2575 weston_subsurface_cache_fini(struct weston_subsurface *sub)
2577 struct weston_frame_callback *cb, *tmp;
2579 wl_list_for_each_safe(cb, tmp, &sub->cached.frame_callback_list, link)
2580 wl_resource_destroy(cb->resource);
2582 weston_buffer_reference(&sub->cached.buffer_ref, NULL);
2583 pixman_region32_fini(&sub->cached.damage);
2584 pixman_region32_fini(&sub->cached.opaque);
2585 pixman_region32_fini(&sub->cached.input);
2589 weston_subsurface_unlink_parent(struct weston_subsurface *sub)
2591 wl_list_remove(&sub->parent_link);
2592 wl_list_remove(&sub->parent_link_pending);
2593 wl_list_remove(&sub->parent_destroy_listener.link);
2598 weston_subsurface_destroy(struct weston_subsurface *sub);
2601 subsurface_handle_surface_destroy(struct wl_listener *listener, void *data)
2603 struct weston_subsurface *sub =
2604 container_of(listener, struct weston_subsurface,
2605 surface_destroy_listener);
2606 assert(data == &sub->surface->resource);
2608 /* The protocol object (wl_resource) is left inert. */
2610 wl_resource_set_user_data(sub->resource, NULL);
2612 weston_subsurface_destroy(sub);
2616 subsurface_handle_parent_destroy(struct wl_listener *listener, void *data)
2618 struct weston_subsurface *sub =
2619 container_of(listener, struct weston_subsurface,
2620 parent_destroy_listener);
2621 assert(data == &sub->parent->resource);
2622 assert(sub->surface != sub->parent);
2624 if (weston_surface_is_mapped(sub->surface))
2625 weston_surface_unmap(sub->surface);
2627 weston_subsurface_unlink_parent(sub);
2631 subsurface_resource_destroy(struct wl_resource *resource)
2633 struct weston_subsurface *sub = wl_resource_get_user_data(resource);
2636 weston_subsurface_destroy(sub);
2640 subsurface_destroy(struct wl_client *client, struct wl_resource *resource)
2642 wl_resource_destroy(resource);
2646 weston_subsurface_link_parent(struct weston_subsurface *sub,
2647 struct weston_surface *parent)
2649 sub->parent = parent;
2650 sub->parent_destroy_listener.notify = subsurface_handle_parent_destroy;
2651 wl_signal_add(&parent->destroy_signal,
2652 &sub->parent_destroy_listener);
2654 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
2655 wl_list_insert(&parent->subsurface_list_pending,
2656 &sub->parent_link_pending);
2660 weston_subsurface_link_surface(struct weston_subsurface *sub,
2661 struct weston_surface *surface)
2663 sub->surface = surface;
2664 sub->surface_destroy_listener.notify =
2665 subsurface_handle_surface_destroy;
2666 wl_signal_add(&surface->destroy_signal,
2667 &sub->surface_destroy_listener);
2671 weston_subsurface_destroy(struct weston_subsurface *sub)
2673 struct weston_view *view, *next;
2675 assert(sub->surface);
2677 if (sub->resource) {
2678 assert(weston_surface_to_subsurface(sub->surface) == sub);
2679 assert(sub->parent_destroy_listener.notify ==
2680 subsurface_handle_parent_destroy);
2682 wl_list_for_each_safe(view, next, &sub->surface->views, surface_link)
2683 weston_view_destroy(view);
2686 weston_subsurface_unlink_parent(sub);
2688 weston_subsurface_cache_fini(sub);
2690 sub->surface->configure = NULL;
2691 sub->surface->configure_private = NULL;
2693 /* the dummy weston_subsurface for the parent itself */
2694 assert(sub->parent_destroy_listener.notify == NULL);
2695 wl_list_remove(&sub->parent_link);
2696 wl_list_remove(&sub->parent_link_pending);
2699 wl_list_remove(&sub->surface_destroy_listener.link);
2703 static const struct wl_subsurface_interface subsurface_implementation = {
2705 subsurface_set_position,
2706 subsurface_place_above,
2707 subsurface_place_below,
2708 subsurface_set_sync,
2709 subsurface_set_desync
2712 static struct weston_subsurface *
2713 weston_subsurface_create(uint32_t id, struct weston_surface *surface,
2714 struct weston_surface *parent)
2716 struct weston_subsurface *sub;
2717 struct wl_client *client = wl_resource_get_client(surface->resource);
2719 sub = calloc(1, sizeof *sub);
2723 wl_list_init(&sub->unused_views);
2726 wl_resource_create(client, &wl_subsurface_interface, 1, id);
2727 if (!sub->resource) {
2732 wl_resource_set_implementation(sub->resource,
2733 &subsurface_implementation,
2734 sub, subsurface_resource_destroy);
2735 weston_subsurface_link_surface(sub, surface);
2736 weston_subsurface_link_parent(sub, parent);
2737 weston_subsurface_cache_init(sub);
2738 sub->synchronized = 1;
2743 /* Create a dummy subsurface for having the parent itself in its
2744 * sub-surface lists. Makes stacking order manipulation easy.
2746 static struct weston_subsurface *
2747 weston_subsurface_create_for_parent(struct weston_surface *parent)
2749 struct weston_subsurface *sub;
2751 sub = calloc(1, sizeof *sub);
2755 weston_subsurface_link_surface(sub, parent);
2756 sub->parent = parent;
2757 wl_list_insert(&parent->subsurface_list, &sub->parent_link);
2758 wl_list_insert(&parent->subsurface_list_pending,
2759 &sub->parent_link_pending);
2765 subcompositor_get_subsurface(struct wl_client *client,
2766 struct wl_resource *resource,
2768 struct wl_resource *surface_resource,
2769 struct wl_resource *parent_resource)
2771 struct weston_surface *surface =
2772 wl_resource_get_user_data(surface_resource);
2773 struct weston_surface *parent =
2774 wl_resource_get_user_data(parent_resource);
2775 struct weston_subsurface *sub;
2776 static const char where[] = "get_subsurface: wl_subsurface@";
2778 if (surface == parent) {
2779 wl_resource_post_error(resource,
2780 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
2781 "%s%d: wl_surface@%d cannot be its own parent",
2782 where, id, wl_resource_get_id(surface_resource));
2786 if (weston_surface_to_subsurface(surface)) {
2787 wl_resource_post_error(resource,
2788 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
2789 "%s%d: wl_surface@%d is already a sub-surface",
2790 where, id, wl_resource_get_id(surface_resource));
2794 if (surface->configure) {
2795 wl_resource_post_error(resource,
2796 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
2797 "%s%d: wl_surface@%d already has a role",
2798 where, id, wl_resource_get_id(surface_resource));
2802 if (weston_surface_get_main_surface(parent) == surface) {
2803 wl_resource_post_error(resource,
2804 WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
2805 "%s%d: wl_surface@%d is an ancestor of parent",
2806 where, id, wl_resource_get_id(surface_resource));
2810 /* make sure the parent is in its own list */
2811 if (wl_list_empty(&parent->subsurface_list)) {
2812 if (!weston_subsurface_create_for_parent(parent)) {
2813 wl_resource_post_no_memory(resource);
2818 sub = weston_subsurface_create(id, surface, parent);
2820 wl_resource_post_no_memory(resource);
2824 surface->configure = subsurface_configure;
2825 surface->configure_private = sub;
2829 subcompositor_destroy(struct wl_client *client, struct wl_resource *resource)
2831 wl_resource_destroy(resource);
2834 static const struct wl_subcompositor_interface subcompositor_interface = {
2835 subcompositor_destroy,
2836 subcompositor_get_subsurface
2840 bind_subcompositor(struct wl_client *client,
2841 void *data, uint32_t version, uint32_t id)
2843 struct weston_compositor *compositor = data;
2844 struct wl_resource *resource;
2847 wl_resource_create(client, &wl_subcompositor_interface, 1, id);
2848 if (resource == NULL) {
2849 wl_client_post_no_memory(client);
2852 wl_resource_set_implementation(resource, &subcompositor_interface,
2857 weston_compositor_dpms(struct weston_compositor *compositor,
2858 enum dpms_enum state)
2860 struct weston_output *output;
2862 wl_list_for_each(output, &compositor->output_list, link)
2863 if (output->set_dpms)
2864 output->set_dpms(output, state);
2868 weston_compositor_wake(struct weston_compositor *compositor)
2870 uint32_t old_state = compositor->state;
2872 /* The state needs to be changed before emitting the wake
2873 * signal because that may try to schedule a repaint which
2874 * will not work if the compositor is still sleeping */
2875 compositor->state = WESTON_COMPOSITOR_ACTIVE;
2877 switch (old_state) {
2878 case WESTON_COMPOSITOR_SLEEPING:
2879 weston_compositor_dpms(compositor, WESTON_DPMS_ON);
2881 case WESTON_COMPOSITOR_IDLE:
2882 case WESTON_COMPOSITOR_OFFSCREEN:
2883 wl_signal_emit(&compositor->wake_signal, compositor);
2886 wl_event_source_timer_update(compositor->idle_source,
2887 compositor->idle_time * 1000);
2892 weston_compositor_offscreen(struct weston_compositor *compositor)
2894 switch (compositor->state) {
2895 case WESTON_COMPOSITOR_OFFSCREEN:
2897 case WESTON_COMPOSITOR_SLEEPING:
2898 weston_compositor_dpms(compositor, WESTON_DPMS_ON);
2901 compositor->state = WESTON_COMPOSITOR_OFFSCREEN;
2902 wl_event_source_timer_update(compositor->idle_source, 0);
2907 weston_compositor_sleep(struct weston_compositor *compositor)
2909 if (compositor->state == WESTON_COMPOSITOR_SLEEPING)
2912 wl_event_source_timer_update(compositor->idle_source, 0);
2913 compositor->state = WESTON_COMPOSITOR_SLEEPING;
2914 weston_compositor_dpms(compositor, WESTON_DPMS_OFF);
2918 idle_handler(void *data)
2920 struct weston_compositor *compositor = data;
2922 if (compositor->idle_inhibit)
2925 compositor->state = WESTON_COMPOSITOR_IDLE;
2926 wl_signal_emit(&compositor->idle_signal, compositor);
2932 weston_plane_init(struct weston_plane *plane,
2933 struct weston_compositor *ec,
2934 int32_t x, int32_t y)
2936 pixman_region32_init(&plane->damage);
2937 pixman_region32_init(&plane->clip);
2940 plane->compositor = ec;
2942 /* Init the link so that the call to wl_list_remove() when releasing
2943 * the plane without ever stacking doesn't lead to a crash */
2944 wl_list_init(&plane->link);
2948 weston_plane_release(struct weston_plane *plane)
2950 struct weston_view *view;
2952 pixman_region32_fini(&plane->damage);
2953 pixman_region32_fini(&plane->clip);
2955 wl_list_for_each(view, &plane->compositor->view_list, link) {
2956 if (view->plane == plane)
2960 wl_list_remove(&plane->link);
2964 weston_compositor_stack_plane(struct weston_compositor *ec,
2965 struct weston_plane *plane,
2966 struct weston_plane *above)
2969 wl_list_insert(above->link.prev, &plane->link);
2971 wl_list_insert(&ec->plane_list, &plane->link);
2974 static void unbind_resource(struct wl_resource *resource)
2976 wl_list_remove(wl_resource_get_link(resource));
2980 bind_output(struct wl_client *client,
2981 void *data, uint32_t version, uint32_t id)
2983 struct weston_output *output = data;
2984 struct weston_mode *mode;
2985 struct wl_resource *resource;
2987 resource = wl_resource_create(client, &wl_output_interface,
2988 MIN(version, 2), id);
2989 if (resource == NULL) {
2990 wl_client_post_no_memory(client);
2994 wl_list_insert(&output->resource_list, wl_resource_get_link(resource));
2995 wl_resource_set_implementation(resource, NULL, data, unbind_resource);
2997 wl_output_send_geometry(resource,
3003 output->make, output->model,
3006 wl_output_send_scale(resource,
3007 output->current_scale);
3009 wl_list_for_each (mode, &output->mode_list, link) {
3010 wl_output_send_mode(resource,
3018 wl_output_send_done(resource);
3022 weston_output_destroy(struct weston_output *output)
3024 wl_signal_emit(&output->destroy_signal, output);
3027 pixman_region32_fini(&output->region);
3028 pixman_region32_fini(&output->previous_damage);
3029 output->compositor->output_id_pool &= ~(1 << output->id);
3031 wl_global_destroy(output->global);
3035 weston_output_compute_transform(struct weston_output *output)
3037 struct weston_matrix transform;
3040 weston_matrix_init(&transform);
3041 transform.type = WESTON_MATRIX_TRANSFORM_ROTATE;
3043 switch(output->transform) {
3044 case WL_OUTPUT_TRANSFORM_FLIPPED:
3045 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3046 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3047 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3048 transform.type |= WESTON_MATRIX_TRANSFORM_OTHER;
3056 switch(output->transform) {
3057 case WL_OUTPUT_TRANSFORM_NORMAL:
3058 case WL_OUTPUT_TRANSFORM_FLIPPED:
3059 transform.d[0] = flip;
3064 case WL_OUTPUT_TRANSFORM_90:
3065 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3067 transform.d[1] = -flip;
3071 case WL_OUTPUT_TRANSFORM_180:
3072 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3073 transform.d[0] = -flip;
3076 transform.d[5] = -1;
3078 case WL_OUTPUT_TRANSFORM_270:
3079 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3081 transform.d[1] = flip;
3082 transform.d[4] = -1;
3089 weston_matrix_multiply(&output->matrix, &transform);
3093 weston_output_update_matrix(struct weston_output *output)
3095 float magnification;
3096 struct weston_matrix camera;
3097 struct weston_matrix modelview;
3099 weston_matrix_init(&output->matrix);
3100 weston_matrix_translate(&output->matrix,
3101 -(output->x + output->width / 2.0),
3102 -(output->y + output->height / 2.0), 0);
3104 weston_matrix_scale(&output->matrix,
3105 2.0 / output->width,
3106 -2.0 / output->height, 1);
3108 weston_output_compute_transform(output);
3110 if (output->zoom.active) {
3111 magnification = 1 / (1 - output->zoom.spring_z.current);
3112 weston_matrix_init(&camera);
3113 weston_matrix_init(&modelview);
3114 weston_output_update_zoom(output);
3115 weston_matrix_translate(&camera, output->zoom.trans_x,
3116 -output->zoom.trans_y, 0);
3117 weston_matrix_invert(&modelview, &camera);
3118 weston_matrix_scale(&modelview, magnification, magnification, 1.0);
3119 weston_matrix_multiply(&output->matrix, &modelview);
3126 weston_output_transform_scale_init(struct weston_output *output, uint32_t transform, uint32_t scale)
3128 output->transform = transform;
3130 switch (transform) {
3131 case WL_OUTPUT_TRANSFORM_90:
3132 case WL_OUTPUT_TRANSFORM_270:
3133 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3134 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3135 /* Swap width and height */
3136 output->width = output->current_mode->height;
3137 output->height = output->current_mode->width;
3139 case WL_OUTPUT_TRANSFORM_NORMAL:
3140 case WL_OUTPUT_TRANSFORM_180:
3141 case WL_OUTPUT_TRANSFORM_FLIPPED:
3142 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3143 output->width = output->current_mode->width;
3144 output->height = output->current_mode->height;
3150 output->native_scale = output->current_scale = scale;
3151 output->width /= scale;
3152 output->height /= scale;
3156 weston_output_move(struct weston_output *output, int x, int y)
3161 pixman_region32_init(&output->previous_damage);
3162 pixman_region32_init_rect(&output->region, x, y,
3168 weston_output_init(struct weston_output *output, struct weston_compositor *c,
3169 int x, int y, int mm_width, int mm_height, uint32_t transform,
3172 output->compositor = c;
3175 output->mm_width = mm_width;
3176 output->mm_height = mm_height;
3178 output->original_scale = scale;
3180 weston_output_transform_scale_init(output, transform, scale);
3181 weston_output_init_zoom(output);
3183 weston_output_move(output, x, y);
3184 weston_output_damage(output);
3186 wl_signal_init(&output->frame_signal);
3187 wl_signal_init(&output->destroy_signal);
3188 wl_list_init(&output->animation_list);
3189 wl_list_init(&output->resource_list);
3191 output->id = ffs(~output->compositor->output_id_pool) - 1;
3192 output->compositor->output_id_pool |= 1 << output->id;
3195 wl_global_create(c->wl_display, &wl_output_interface, 2,
3196 output, bind_output);
3197 wl_signal_emit(&c->output_created_signal, output);
3201 weston_output_transform_coordinate(struct weston_output *output,
3202 wl_fixed_t device_x, wl_fixed_t device_y,
3203 wl_fixed_t *x, wl_fixed_t *y)
3206 wl_fixed_t width, height;
3208 width = wl_fixed_from_int(output->width * output->current_scale - 1);
3209 height = wl_fixed_from_int(output->height * output->current_scale - 1);
3211 switch(output->transform) {
3212 case WL_OUTPUT_TRANSFORM_NORMAL:
3217 case WL_OUTPUT_TRANSFORM_90:
3219 ty = height - device_x;
3221 case WL_OUTPUT_TRANSFORM_180:
3222 tx = width - device_x;
3223 ty = height - device_y;
3225 case WL_OUTPUT_TRANSFORM_270:
3226 tx = width - device_y;
3229 case WL_OUTPUT_TRANSFORM_FLIPPED:
3230 tx = width - device_x;
3233 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
3234 tx = width - device_y;
3235 ty = height - device_x;
3237 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
3239 ty = height - device_y;
3241 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
3247 *x = tx / output->current_scale + wl_fixed_from_int(output->x);
3248 *y = ty / output->current_scale + wl_fixed_from_int(output->y);
3252 compositor_bind(struct wl_client *client,
3253 void *data, uint32_t version, uint32_t id)
3255 struct weston_compositor *compositor = data;
3256 struct wl_resource *resource;
3258 resource = wl_resource_create(client, &wl_compositor_interface,
3259 MIN(version, 3), id);
3260 if (resource == NULL) {
3261 wl_client_post_no_memory(client);
3265 wl_resource_set_implementation(resource, &compositor_interface,
3272 struct utsname usys;
3276 weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
3277 usys.version, usys.machine);
3281 weston_environment_get_fd(const char *env)
3289 fd = strtol(e, &end, 0);
3293 flags = fcntl(fd, F_GETFD);
3297 fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
3304 weston_compositor_init(struct weston_compositor *ec,
3305 struct wl_display *display,
3306 int *argc, char *argv[],
3307 struct weston_config *config)
3309 struct wl_event_loop *loop;
3310 struct xkb_rule_names xkb_names;
3311 struct weston_config_section *s;
3313 ec->config = config;
3314 ec->wl_display = display;
3315 wl_signal_init(&ec->destroy_signal);
3316 wl_signal_init(&ec->activate_signal);
3317 wl_signal_init(&ec->transform_signal);
3318 wl_signal_init(&ec->kill_signal);
3319 wl_signal_init(&ec->idle_signal);
3320 wl_signal_init(&ec->wake_signal);
3321 wl_signal_init(&ec->show_input_panel_signal);
3322 wl_signal_init(&ec->hide_input_panel_signal);
3323 wl_signal_init(&ec->update_input_panel_signal);
3324 wl_signal_init(&ec->seat_created_signal);
3325 wl_signal_init(&ec->output_created_signal);
3326 wl_signal_init(&ec->session_signal);
3327 ec->session_active = 1;
3329 ec->output_id_pool = 0;
3331 if (!wl_global_create(display, &wl_compositor_interface, 3,
3332 ec, compositor_bind))
3335 if (!wl_global_create(display, &wl_subcompositor_interface, 1,
3336 ec, bind_subcompositor))
3339 wl_list_init(&ec->view_list);
3340 wl_list_init(&ec->plane_list);
3341 wl_list_init(&ec->layer_list);
3342 wl_list_init(&ec->seat_list);
3343 wl_list_init(&ec->output_list);
3344 wl_list_init(&ec->key_binding_list);
3345 wl_list_init(&ec->modifier_binding_list);
3346 wl_list_init(&ec->button_binding_list);
3347 wl_list_init(&ec->touch_binding_list);
3348 wl_list_init(&ec->axis_binding_list);
3349 wl_list_init(&ec->debug_binding_list);
3351 weston_plane_init(&ec->primary_plane, ec, 0, 0);
3352 weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
3354 s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
3355 weston_config_section_get_string(s, "keymap_rules",
3356 (char **) &xkb_names.rules, NULL);
3357 weston_config_section_get_string(s, "keymap_model",
3358 (char **) &xkb_names.model, NULL);
3359 weston_config_section_get_string(s, "keymap_layout",
3360 (char **) &xkb_names.layout, NULL);
3361 weston_config_section_get_string(s, "keymap_variant",
3362 (char **) &xkb_names.variant, NULL);
3363 weston_config_section_get_string(s, "keymap_options",
3364 (char **) &xkb_names.options, NULL);
3366 if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
3369 ec->ping_handler = NULL;
3371 screenshooter_create(ec);
3372 text_backend_init(ec);
3374 wl_data_device_manager_init(ec->wl_display);
3376 wl_display_init_shm(display);
3378 loop = wl_display_get_event_loop(ec->wl_display);
3379 ec->idle_source = wl_event_loop_add_timer(loop, idle_handler, ec);
3380 wl_event_source_timer_update(ec->idle_source, ec->idle_time * 1000);
3382 ec->input_loop = wl_event_loop_create();
3384 weston_layer_init(&ec->fade_layer, &ec->layer_list);
3385 weston_layer_init(&ec->cursor_layer, &ec->fade_layer.link);
3387 weston_compositor_schedule_repaint(ec);
3393 weston_compositor_shutdown(struct weston_compositor *ec)
3395 struct weston_output *output, *next;
3397 wl_event_source_remove(ec->idle_source);
3398 if (ec->input_loop_source)
3399 wl_event_source_remove(ec->input_loop_source);
3401 /* Destroy all outputs associated with this compositor */
3402 wl_list_for_each_safe(output, next, &ec->output_list, link)
3403 output->destroy(output);
3405 weston_binding_list_destroy_all(&ec->key_binding_list);
3406 weston_binding_list_destroy_all(&ec->button_binding_list);
3407 weston_binding_list_destroy_all(&ec->touch_binding_list);
3408 weston_binding_list_destroy_all(&ec->axis_binding_list);
3409 weston_binding_list_destroy_all(&ec->debug_binding_list);
3411 weston_plane_release(&ec->primary_plane);
3413 wl_event_loop_destroy(ec->input_loop);
3415 weston_config_destroy(ec->config);
3419 weston_compositor_set_default_pointer_grab(struct weston_compositor *ec,
3420 const struct weston_pointer_grab_interface *interface)
3422 struct weston_seat *seat;
3424 ec->default_pointer_grab = interface;
3425 wl_list_for_each(seat, &ec->seat_list, link) {
3426 if (seat->pointer) {
3427 weston_pointer_set_default_grab(seat->pointer,
3434 weston_version(int *major, int *minor, int *micro)
3436 *major = WESTON_VERSION_MAJOR;
3437 *minor = WESTON_VERSION_MINOR;
3438 *micro = WESTON_VERSION_MICRO;
3441 static const struct {
3442 uint32_t bit; /* enum weston_capability */
3444 } capability_strings[] = {
3445 { WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
3446 { WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
3450 weston_compositor_log_capabilities(struct weston_compositor *compositor)
3455 weston_log("Compositor capabilities:\n");
3456 for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
3457 yes = compositor->capabilities & capability_strings[i].bit;
3458 weston_log_continue(STAMP_SPACE "%s %s\n",
3459 capability_strings[i].desc,
3460 yes ? "yes" : "no");
3464 static int on_term_signal(int signal_number, void *data)
3466 struct wl_display *display = data;
3468 weston_log("caught signal %d\n", signal_number);
3469 wl_display_terminate(display);
3474 #ifdef HAVE_LIBUNWIND
3477 print_backtrace(void)
3479 unw_cursor_t cursor;
3480 unw_context_t context;
3482 unw_proc_info_t pip;
3485 const char *filename;
3488 pip.unwind_info = NULL;
3489 ret = unw_getcontext(&context);
3491 weston_log("unw_getcontext: %d\n", ret);
3495 ret = unw_init_local(&cursor, &context);
3497 weston_log("unw_init_local: %d\n", ret);
3501 ret = unw_step(&cursor);
3503 ret = unw_get_proc_info(&cursor, &pip);
3505 weston_log("unw_get_proc_info: %d\n", ret);
3509 ret = unw_get_proc_name(&cursor, procname, 256, &off);
3510 if (ret && ret != -UNW_ENOMEM) {
3511 if (ret != -UNW_EUNSPEC)
3512 weston_log("unw_get_proc_name: %d\n", ret);
3517 if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
3519 filename = dlinfo.dli_fname;
3523 weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
3524 ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
3526 ret = unw_step(&cursor);
3528 weston_log("unw_step: %d\n", ret);
3535 print_backtrace(void)
3541 count = backtrace(buffer, ARRAY_LENGTH(buffer));
3542 for (i = 0; i < count; i++) {
3543 dladdr(buffer[i], &info);
3544 weston_log(" [%016lx] %s (%s)\n",
3546 info.dli_sname ? info.dli_sname : "--",
3554 on_caught_signal(int s, siginfo_t *siginfo, void *context)
3556 /* This signal handler will do a best-effort backtrace, and
3557 * then call the backend restore function, which will switch
3558 * back to the vt we launched from or ungrab X etc and then
3559 * raise SIGTRAP. If we run weston under gdb from X or a
3560 * different vt, and tell gdb "handle *s* nostop", this
3561 * will allow weston to switch back to gdb on crash and then
3562 * gdb will catch the crash with SIGTRAP.*/
3564 weston_log("caught signal: %d\n", s);
3568 segv_compositor->restore(segv_compositor);
3574 weston_load_module(const char *name, const char *entrypoint)
3576 char path[PATH_MAX];
3577 void *module, *init;
3580 snprintf(path, sizeof path, "%s/%s", MODULEDIR, name);
3582 snprintf(path, sizeof path, "%s", name);
3584 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
3586 weston_log("Module '%s' already loaded\n", path);
3591 weston_log("Loading module '%s'\n", path);
3592 module = dlopen(path, RTLD_NOW);
3594 weston_log("Failed to load module: %s\n", dlerror());
3598 init = dlsym(module, entrypoint);
3600 weston_log("Failed to lookup init function: %s\n", dlerror());
3609 load_modules(struct weston_compositor *ec, const char *modules,
3610 int *argc, char *argv[])
3612 const char *p, *end;
3614 int (*module_init)(struct weston_compositor *ec,
3615 int *argc, char *argv[]);
3617 if (modules == NULL)
3622 end = strchrnul(p, ',');
3623 snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
3624 module_init = weston_load_module(buffer, "module_init");
3626 module_init(ec, argc, argv);
3636 static const char xdg_error_message[] =
3637 "fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
3639 static const char xdg_wrong_message[] =
3640 "fatal: environment variable XDG_RUNTIME_DIR\n"
3641 "is set to \"%s\", which is not a directory.\n";
3643 static const char xdg_wrong_mode_message[] =
3644 "warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
3645 "correctly. Unix access mode must be 0700 but is %o,\n"
3646 "and XDG_RUNTIME_DIR must be owned by the user, but is\n"
3647 "owned by UID %d.\n";
3649 static const char xdg_detail_message[] =
3650 "Refer to your distribution on how to get it, or\n"
3651 "http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
3652 "on how to implement it.\n";
3655 verify_xdg_runtime_dir(void)
3657 char *dir = getenv("XDG_RUNTIME_DIR");
3661 weston_log(xdg_error_message);
3662 weston_log_continue(xdg_detail_message);
3666 if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
3667 weston_log(xdg_wrong_message, dir);
3668 weston_log_continue(xdg_detail_message);
3672 if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
3673 weston_log(xdg_wrong_mode_message,
3674 dir, s.st_mode & 0777, s.st_uid);
3675 weston_log_continue(xdg_detail_message);
3680 usage(int error_code)
3683 "Usage: weston [OPTIONS]\n\n"
3684 "This is weston version " VERSION ", the Wayland reference compositor.\n"
3685 "Weston supports multiple backends, and depending on which backend is in use\n"
3686 "different options will be accepted.\n\n"
3690 " --version\t\tPrint weston version\n"
3691 " -B, --backend=MODULE\tBackend module, one of drm-backend.so,\n"
3692 "\t\t\t\tfbdev-backend.so, x11-backend.so or\n"
3693 "\t\t\t\twayland-backend.so\n"
3694 " --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
3695 " -S, --socket=NAME\tName of socket to listen on\n"
3696 " -i, --idle-time=SECS\tIdle time in seconds\n"
3697 " --modules\t\tLoad the comma-separated list of modules\n"
3698 " --log==FILE\t\tLog to the given file\n"
3699 " -h, --help\t\tThis help message\n\n");
3702 "Options for drm-backend.so:\n\n"
3703 " --connector=ID\tBring up only this connector\n"
3704 " --seat=SEAT\t\tThe seat that weston should run on\n"
3705 " --tty=TTY\t\tThe tty to use\n"
3706 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
3707 " --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
3710 "Options for fbdev-backend.so:\n\n"
3711 " --tty=TTY\t\tThe tty to use\n"
3712 " --device=DEVICE\tThe framebuffer device to use\n\n");
3715 "Options for x11-backend.so:\n\n"
3716 " --width=WIDTH\t\tWidth of X window\n"
3717 " --height=HEIGHT\tHeight of X window\n"
3718 " --fullscreen\t\tRun in fullscreen mode\n"
3719 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
3720 " --output-count=COUNT\tCreate multiple outputs\n"
3721 " --no-input\t\tDont create input devices\n\n");
3724 "Options for wayland-backend.so:\n\n"
3725 " --width=WIDTH\t\tWidth of Wayland surface\n"
3726 " --height=HEIGHT\tHeight of Wayland surface\n"
3727 " --scale=SCALE\tScale factor of ouput\n"
3728 " --fullscreen\t\tRun in fullscreen mode\n"
3729 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
3730 " --output-count=COUNT\tCreate multiple outputs\n"
3731 " --display=DISPLAY\tWayland display to connect to\n\n");
3733 #if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
3735 "Options for rpi-backend.so:\n\n"
3736 " --tty=TTY\t\tThe tty to use\n"
3737 " --single-buffer\tUse single-buffered Dispmanx elements.\n"
3738 " --transform=TR\tThe output transformation, TR is one of:\n"
3739 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
3743 #if defined(BUILD_RDP_COMPOSITOR)
3745 "Options for rdp-backend.so:\n\n"
3746 " --width=WIDTH\t\tWidth of desktop\n"
3747 " --height=HEIGHT\tHeight of desktop\n"
3748 " --extra-modes=MODES\t\n"
3749 " --env-socket=SOCKET\tUse that socket as peer connection\n"
3750 " --address=ADDR\tThe address to bind\n"
3751 " --port=PORT\tThe port to listen on\n"
3752 " --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
3753 " --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
3754 " --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
3764 struct sigaction action;
3766 action.sa_flags = SA_SIGINFO | SA_RESETHAND;
3767 action.sa_sigaction = on_caught_signal;
3768 sigemptyset(&action.sa_mask);
3769 sigaction(SIGSEGV, &action, NULL);
3770 sigaction(SIGABRT, &action, NULL);
3773 int main(int argc, char *argv[])
3775 int ret = EXIT_SUCCESS;
3776 struct wl_display *display;
3777 struct weston_compositor *ec;
3778 struct wl_event_source *signals[4];
3779 struct wl_event_loop *loop;
3780 struct weston_compositor
3781 *(*backend_init)(struct wl_display *display,
3782 int *argc, char *argv[],
3783 struct weston_config *config);
3785 char *backend = NULL;
3786 char *option_backend = NULL;
3788 char *modules, *option_modules = NULL;
3790 int32_t idle_time = 300;
3792 char *socket_name = "wayland-0";
3793 int32_t version = 0;
3794 struct weston_config *config;
3795 struct weston_config_section *section;
3797 const struct weston_option core_options[] = {
3798 { WESTON_OPTION_STRING, "backend", 'B', &option_backend },
3799 { WESTON_OPTION_STRING, "shell", 0, &shell },
3800 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
3801 { WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
3802 { WESTON_OPTION_STRING, "modules", 0, &option_modules },
3803 { WESTON_OPTION_STRING, "log", 0, &log },
3804 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
3805 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
3808 parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
3811 usage(EXIT_SUCCESS);
3814 printf(PACKAGE_STRING "\n");
3815 return EXIT_SUCCESS;
3818 weston_log_file_open(log);
3822 STAMP_SPACE "Bug reports to: %s\n"
3823 STAMP_SPACE "Build: %s\n",
3824 PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
3828 verify_xdg_runtime_dir();
3830 display = wl_display_create();
3832 loop = wl_display_get_event_loop(display);
3833 signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
3835 signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
3837 signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
3840 wl_list_init(&child_process_list);
3841 signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
3844 config = weston_config_parse("weston.ini");
3845 if (config != NULL) {
3846 weston_log("Using config file '%s'\n",
3847 weston_config_get_full_path(config));
3849 weston_log("Starting with no config file.\n");
3851 section = weston_config_get_section(config, "core", NULL, NULL);
3853 weston_config_section_get_string(section, "backend", &backend, NULL);
3854 if (option_backend) {
3855 backend = option_backend;
3858 if (getenv("WAYLAND_DISPLAY"))
3859 backend = "wayland-backend.so";
3860 else if (getenv("DISPLAY"))
3861 backend = "x11-backend.so";
3863 backend = WESTON_NATIVE_BACKEND;
3866 weston_config_section_get_string(section, "modules", &modules, "");
3868 backend_init = weston_load_module(backend, "backend_init");
3872 ec = backend_init(display, &argc, argv, config);
3874 weston_log("fatal: failed to create compositor\n");
3879 segv_compositor = ec;
3881 ec->idle_time = idle_time;
3882 ec->default_pointer_grab = NULL;
3884 setenv("WAYLAND_DISPLAY", socket_name, 1);
3887 weston_config_section_get_string(section, "shell", &shell,
3888 "desktop-shell.so");
3889 if (load_modules(ec, shell, &argc, argv) < 0)
3892 if (load_modules(ec, modules, &argc, argv) < 0)
3894 if (load_modules(ec, option_modules, &argc, argv) < 0)
3897 for (i = 1; i < argc; i++)
3898 weston_log("fatal: unhandled option: %s\n", argv[i]);
3904 weston_compositor_log_capabilities(ec);
3906 if (wl_display_add_socket(display, socket_name)) {
3907 weston_log("fatal: failed to add socket: %m\n");
3912 weston_compositor_wake(ec);
3914 wl_display_run(display);
3917 /* prevent further rendering while shutting down */
3918 ec->state = WESTON_COMPOSITOR_OFFSCREEN;
3920 wl_signal_emit(&ec->destroy_signal, ec);
3922 for (i = ARRAY_LENGTH(signals); i;)
3923 wl_event_source_remove(signals[--i]);
3925 weston_compositor_xkb_destroy(ec);
3928 wl_display_destroy(display);
3930 weston_log_file_close();