swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit d95b8178ddb4304c7c3ee325bdae366b81cb6b89
parent 3333dfd86da6a407fd39ad77d2f5cb85cd8ba824
Author: Michael Forney <mforney@mforney.org>
Date:   Fri,  7 Feb 2014 23:28:55 -0800

view: Make view implementations explicitly change view state

This way, the framebuffer plane can keep a constant size (even if an
oversized buffer is attached). Additionally this enables some tricks for
ensuring smooth move+resize (common operation for tiling window
managers).

Diffstat:
Mlibswc/compositor.c | 50+++++++++++++++++++++++++++++---------------------
Mlibswc/cursor_plane.c | 11++++++++---
Mlibswc/cursor_plane.h | 5+++--
Mlibswc/framebuffer_plane.c | 2++
Mlibswc/pointer.c | 9+++++++++
Mlibswc/screen.c | 6++----
Mlibswc/view.c | 111++++++++++++++++++++++++++++++++++++++-----------------------------------------
Mlibswc/view.h | 37++++++++++---------------------------
8 files changed, 117 insertions(+), 114 deletions(-)

diff --git a/libswc/compositor.c b/libswc/compositor.c @@ -68,6 +68,9 @@ struct view struct swc_surface * surface; struct wld_buffer * buffer; + /* Whether or not the view is visible (mapped). */ + bool visible; + /* The box that the surface covers (including it's border). */ pixman_box32_t extents; @@ -426,12 +429,14 @@ static void schedule_updates(uint32_t screens) compositor.scheduled_updates |= screens; } -static bool update(struct swc_view * view) +static bool update(struct swc_view * base) { + struct view * view = (void *) base; + if (!compositor.active || !view->visible) return false; - schedule_updates(view->screens); + schedule_updates(view->base.screens); return true; } @@ -443,38 +448,36 @@ static bool attach(struct swc_view * base, struct wld_buffer * buffer) if (!renderer_attach(view, buffer)) return false; - return true; -} - -static bool move(struct swc_view * base, int32_t x, int32_t y) -{ - struct view * view = (void *) base; - - if (view->base.visible) + if (view->visible && view->base.buffer) { damage_below_view(view); update(&view->base); } + swc_view_set_size_from_buffer(&view->base, buffer); + return true; } -static void resize(struct swc_view * base) +static bool move(struct swc_view * base, int32_t x, int32_t y) { struct view * view = (void *) base; - if (view->base.visible) + if (view->visible) { damage_below_view(view); update(&view->base); } + + swc_view_set_position(&view->base, x, y); + + return true; } const static struct swc_view_impl view_impl = { .update = &update, .attach = &attach, - .move = &move, - .resize = &resize, + .move = &move }; static void handle_view_event(struct wl_listener * listener, void * data) @@ -487,22 +490,24 @@ static void handle_view_event(struct wl_listener * listener, void * data) case SWC_VIEW_EVENT_MOVED: update_extents(view); - if (view->base.visible) + if (view->visible) { /* Assume worst-case no clipping until we draw the next frame (in case * the surface gets moved again before that). */ pixman_region32_init(&view->clip); damage_below_view(view); + swc_view_update_screens(&view->base); update(&view->base); } break; case SWC_VIEW_EVENT_RESIZED: update_extents(view); - if (view->base.visible) + if (view->visible) { damage_below_view(view); + swc_view_update_screens(&view->base); update(&view->base); } break; @@ -519,11 +524,11 @@ bool swc_compositor_add_surface(struct swc_surface * surface) return false; swc_view_initialize(&view->base, &view_impl); - view->base.visible = false; view->event_listener.notify = &handle_view_event; wl_signal_add(&view->base.event_signal, &view->event_listener); view->surface = surface; view->buffer = NULL; + view->visible = false; view->extents.x1 = 0; view->extents.y1 = 0; view->extents.x2 = 0; @@ -560,7 +565,7 @@ void swc_compositor_surface_show(struct swc_surface * surface) if (view->base.impl != &view_impl) return; - if (view->base.visible) + if (view->visible) return; printf("showing surface %u\n", wl_resource_get_id(surface->resource)); @@ -569,8 +574,10 @@ void swc_compositor_surface_show(struct swc_surface * surface) * surface gets moved before that. */ pixman_region32_clear(&view->clip); + view->visible = true; + swc_view_update_screens(&view->base); + damage_view(view); - swc_view_set_visibility(&view->base, true); update(&view->base); wl_list_insert(&compositor.views, &view->link); } @@ -582,15 +589,16 @@ void swc_compositor_surface_hide(struct swc_surface * surface) if (view->base.impl != &view_impl) return; - if (!view->base.visible) + if (!view->visible) return; /* Update all the outputs the surface was on. */ update(&view->base); damage_below_view(view); - swc_view_set_visibility(&view->base, false); wl_list_remove(&view->link); + swc_view_set_screens(&view->base, 0); + view->visible = false; } void swc_compositor_surface_set_border_width(struct swc_surface * surface, diff --git a/libswc/cursor_plane.c b/libswc/cursor_plane.c @@ -68,6 +68,8 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer) } } + swc_view_set_size_from_buffer(view, buffer); + return true; } @@ -76,13 +78,14 @@ static bool move(struct swc_view * view, int32_t x, int32_t y) struct swc_cursor_plane * plane = CONTAINER_OF(view, typeof(*plane), view); if (drmModeMoveCursor(swc.drm->fd, plane->crtc, - x - view->screen->base.geometry.x, - y - view->screen->base.geometry.y) != 0) + x - plane->origin->x, y - plane->origin->y) != 0) { ERROR("Could not move cursor: %s\n", strerror(errno)); return false; } + swc_view_set_position(view, x, y); + return true; } @@ -107,11 +110,13 @@ static void handle_launch_event(struct wl_listener * listener, void * data) } } -bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc) +bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc, + const struct swc_rectangle * origin) { if (drmModeSetCursor(swc.drm->fd, crtc, 0, 0, 0) != 0) return false; + plane->origin = origin; plane->crtc = crtc; plane->launch_listener.notify = &handle_launch_event; wl_signal_add(&swc.launch->event_signal, &plane->launch_listener); diff --git a/libswc/cursor_plane.h b/libswc/cursor_plane.h @@ -29,12 +29,13 @@ struct swc_cursor_plane { struct swc_view view; + const struct swc_rectangle * origin; uint32_t crtc; struct wl_listener launch_listener; }; -bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, - uint32_t crtc); +bool swc_cursor_plane_initialize(struct swc_cursor_plane * plane, uint32_t crtc, + const struct swc_rectangle * origin); void swc_cursor_plane_finalize(struct swc_cursor_plane * plane); diff --git a/libswc/framebuffer_plane.c b/libswc/framebuffer_plane.c @@ -148,6 +148,8 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer) static bool move(struct swc_view * view, int32_t x, int32_t y) { + swc_view_set_position(view, x, y); + return true; } diff --git a/libswc/pointer.c b/libswc/pointer.c @@ -104,11 +104,15 @@ static bool attach(struct swc_view * view, struct wld_buffer * buffer) /* TODO: Send an early release to the buffer */ + swc_view_set_size_from_buffer(view, buffer); + return true; } static bool move(struct swc_view * view, int32_t x, int32_t y) { + swc_view_set_position(view, x, y); + return true; } @@ -135,6 +139,11 @@ static void handle_view_event(struct wl_listener * listener, void * data) swc_view_move(&screen->planes.cursor.view, view->geometry.x, view->geometry.y); } + + swc_view_update_screens(view); + break; + case SWC_VIEW_EVENT_RESIZED: + swc_view_update_screens(view); break; case SWC_VIEW_EVENT_SCREENS_CHANGED: wl_list_for_each(screen, &swc.screens, link) diff --git a/libswc/screen.c b/libswc/screen.c @@ -80,15 +80,13 @@ struct screen * screen_new(uint32_t crtc, struct swc_output * output) goto error1; } - if (!swc_cursor_plane_initialize(&screen->planes.cursor, crtc)) + if (!swc_cursor_plane_initialize(&screen->planes.cursor, crtc, + &screen->base.geometry)) { ERROR("Failed to initialize cursor plane\n"); goto error2; } - screen->planes.framebuffer.view.screen = screen; - screen->planes.cursor.view.screen = screen; - swc_view_move(&screen->planes.framebuffer.view, x, 0); screen->base.geometry = screen->planes.framebuffer.view.geometry; screen->base.usable_geometry = screen->base.geometry; diff --git a/libswc/view.c b/libswc/view.c @@ -29,53 +29,10 @@ #include <wld/wld.h> -static void update_screens(struct swc_view * view) -{ - struct swc_view_event_data data = { .view = view }; - uint32_t old = view->screens, new = 0; - struct screen * screen; - - if (view->visible) - { - wl_list_for_each(screen, &swc.screens, link) - { - if (swc_rectangle_overlap(&screen->base.geometry, &view->geometry)) - new |= screen_mask(screen); - } - } - - if (new == old) - return; - - view->screens = new; - - data.screens_changed.entered = new & ~old; - data.screens_changed.left = old & ~new; - swc_send_event(&view->event_signal, SWC_VIEW_EVENT_SCREENS_CHANGED, &data); -} - -static void set_size(struct swc_view * view, uint32_t width, uint32_t height) -{ - if (view->geometry.width != width || view->geometry.height != height) - { - struct swc_view_event_data data = { .view = view }; - - if (view->impl->resize) - view->impl->resize(view); - - view->geometry.width = width; - view->geometry.height = height; - update_screens(view); - - swc_send_event(&view->event_signal, SWC_VIEW_EVENT_RESIZED, &data); - } -} - void swc_view_initialize(struct swc_view * view, const struct swc_view_impl * impl) { view->impl = impl; - view->visible = true; view->geometry.x = 0; view->geometry.y = 0; view->geometry.width = 0; @@ -99,12 +56,7 @@ bool swc_view_attach(struct swc_view * view, struct wld_buffer * buffer) wld_buffer_unreference(view->buffer); if (buffer) - { wld_buffer_reference(buffer); - set_size(view, buffer->width, buffer->height); - } - else - set_size(view, 0, 0); view->buffer = buffer; return true; @@ -120,26 +72,71 @@ bool swc_view_update(struct swc_view * view) bool swc_view_move(struct swc_view * view, int32_t x, int32_t y) { + return view->impl->move(view, x, y); +} + +void swc_view_set_position(struct swc_view * view, int32_t x, int32_t y) +{ struct swc_view_event_data data = { .view = view }; if (x == view->geometry.x && y == view->geometry.y) - return true; - - if (!view->impl->move || !view->impl->move(view, x, y)) - return false; + return; view->geometry.x = x; view->geometry.y = y; - update_screens(view); swc_send_event(&view->event_signal, SWC_VIEW_EVENT_MOVED, &data); +} + +void swc_view_set_size(struct swc_view * view, uint32_t width, uint32_t height) +{ + struct swc_view_event_data data = { .view = view }; + + if (view->geometry.width == width && view->geometry.height == height) + return; + + view->geometry.width = width; + view->geometry.height = height; + swc_send_event(&view->event_signal, SWC_VIEW_EVENT_RESIZED, &data); +} + +void swc_view_set_size_from_buffer(struct swc_view * view, + struct wld_buffer * buffer) +{ + if (buffer) + swc_view_set_size(view, buffer->width, buffer->height); + else + swc_view_set_size(view, 0, 0); +} + +void swc_view_set_screens(struct swc_view * view, uint32_t screens) +{ + if (view->screens == screens) + return; + + struct swc_view_event_data data = { + .view = view, + .screens_changed = { + .entered = screens & ~view->screens, + .left = view->screens & ~screens + } + }; - return true; + view->screens = screens; + swc_send_event(&view->event_signal, SWC_VIEW_EVENT_SCREENS_CHANGED, &data); } -void swc_view_set_visibility(struct swc_view * view, bool visible) +void swc_view_update_screens(struct swc_view * view) { - view->visible = visible; - update_screens(view); + uint32_t screens = 0; + struct screen * screen; + + wl_list_for_each(screen, &swc.screens, link) + { + if (swc_rectangle_overlap(&screen->base.geometry, &view->geometry)) + screens |= screen_mask(screen); + } + + swc_view_set_screens(view, screens); } void swc_view_frame(struct swc_view * view, uint32_t time) diff --git a/libswc/view.h b/libswc/view.h @@ -34,8 +34,7 @@ enum /* Sent when the origin of the view has moved. */ SWC_VIEW_EVENT_MOVED, - /* Sent when the view's size changes. This occurs when a buffer of - * different dimensions is attached to the view. */ + /* Sent when the view's size changes. */ SWC_VIEW_EVENT_RESIZED, /* Sent when the set of screens the view is visible on changes. */ @@ -82,16 +81,8 @@ struct swc_view const struct swc_view_impl * impl; struct wl_signal event_signal; - bool visible; - uint32_t screens; - struct swc_rectangle geometry; - - /** - * The screen that the view belongs to (for example if framebuffer or - * cursor plane), or NULL. - */ - struct screen * screen; + uint32_t screens; struct wld_buffer * buffer; }; @@ -106,14 +97,6 @@ struct swc_view_impl bool (* update)(struct swc_view * view); bool (* attach)(struct swc_view * view, struct wld_buffer * buffer); bool (* move)(struct swc_view * view, int32_t x, int32_t y); - - /** - * This function indicates to the view that it is about to be resized. - * - * The view can use this function to do any necessary damage calculations - * with the geometry of the view before the resize occurs. - */ - void (* resize)(struct swc_view * view); }; /** @@ -150,14 +133,14 @@ bool swc_view_update(struct swc_view * view); */ bool swc_view_move(struct swc_view * view, int32_t x, int32_t y); -/** - * Set the visibility flag of the view. - * - * This retains the view's geometry, but indicates that it will not be shown - * when the next frame is finished. This is useful when an unmapped or - * minimized state is desired. - */ -void swc_view_set_visibility(struct swc_view * view, bool visible); +/**** For internal view use only ****/ + +void swc_view_set_position(struct swc_view * view, int32_t x, int32_t y); +void swc_view_set_size(struct swc_view * view, uint32_t width, uint32_t height); +void swc_view_set_size_from_buffer(struct swc_view * view, + struct wld_buffer * bufer); +void swc_view_set_screens(struct swc_view * view, uint32_t screens); +void swc_view_update_screens(struct swc_view * view); /** * Send a new frame event through the view's event signal.