commit 300de28
Michael Forney
·
2014-01-17 02:06:26 +0000 UTC
parent 0dc0ed3
Move common state to swc_view
10 files changed,
+374,
-329
+145,
-210
1@@ -23,6 +23,7 @@
2 struct view
3 {
4 struct swc_view base;
5+ struct wl_listener event_listener;
6 struct swc_compositor * compositor;
7 struct swc_surface * surface;
8
9@@ -40,9 +41,7 @@ struct view
10 bool damaged;
11 } border;
12
13- bool mapped;
14-
15- struct wl_listener surface_event_listener;
16+ struct wl_list link;
17 };
18
19 /* Rendering {{{ */
20@@ -51,50 +50,39 @@ struct render_target
21 {
22 struct wld_buffer * buffer;
23 struct swc_rectangle geometry;
24+ uint32_t mask;
25 };
26
27-static void repaint_surface(struct render_target * target,
28- struct swc_surface * surface,
29- pixman_region32_t * damage)
30+static void repaint_view(struct render_target * target, struct view * view,
31+ pixman_region32_t * damage)
32 {
33- pixman_region32_t surface_damage;
34- pixman_region32_t border_damage;
35- pixman_region32_t surface_region;
36- struct view * view = (void *) surface->view;
37+ pixman_region32_t view_region, view_damage, border_damage;
38+ const struct swc_rectangle * geometry = &view->base.geometry;
39
40- if (!surface->state.buffer)
41+ if (!view->base.buffer)
42 return;
43
44- pixman_region32_init_with_extents(&surface_damage, &view->extents);
45+ pixman_region32_init_rect(&view_region, geometry->x, geometry->y,
46+ geometry->width, geometry->height);
47+ pixman_region32_init_with_extents(&view_damage, &view->extents);
48 pixman_region32_init(&border_damage);
49- pixman_region32_init_rect
50- (&surface_region, surface->geometry.x, surface->geometry.y,
51- surface->geometry.width, surface->geometry.height);
52
53- pixman_region32_intersect(&surface_damage, &surface_damage, damage);
54- pixman_region32_subtract(&surface_damage, &surface_damage, &view->clip);
55- pixman_region32_subtract(&border_damage, &surface_damage, &surface_region);
56- pixman_region32_intersect(&surface_damage, &surface_damage,
57- &surface_region);
58+ pixman_region32_intersect(&view_damage, &view_damage, damage);
59+ pixman_region32_subtract(&view_damage, &view_damage, &view->clip);
60+ pixman_region32_subtract(&border_damage, &view_damage, &view_region);
61+ pixman_region32_intersect(&view_damage, &view_damage, &view_region);
62
63- pixman_region32_fini(&surface_region);
64+ pixman_region32_fini(&view_region);
65
66- if (pixman_region32_not_empty(&surface_damage))
67+ if (pixman_region32_not_empty(&view_damage))
68 {
69- DEBUG("\tDRM surface %u { x: %d, y: %d, w: %u, h: %u }\n",
70- wl_resource_get_id(surface->resource),
71- surface->geometry.x, surface->geometry.y,
72- surface->geometry.width, surface->geometry.height);
73-
74- pixman_region32_translate(&surface_damage,
75- -surface->geometry.x, -surface->geometry.y);
76- wld_copy_region(swc.drm->renderer, surface->state.buffer->wld,
77- surface->geometry.x - target->geometry.x,
78- surface->geometry.y - target->geometry.y,
79- &surface_damage);
80+ pixman_region32_translate(&view_damage, -geometry->x, -geometry->y);
81+ wld_copy_region(swc.drm->renderer, view->base.buffer->wld,
82+ geometry->x - target->geometry.x,
83+ geometry->y - target->geometry.y, &view_damage);
84 }
85
86- pixman_region32_fini(&surface_damage);
87+ pixman_region32_fini(&view_damage);
88
89 /* Draw border */
90 if (pixman_region32_not_empty(&border_damage))
91@@ -112,9 +100,9 @@ static void repaint_surface(struct render_target * target,
92 static void renderer_repaint(struct render_target * target,
93 pixman_region32_t * damage,
94 pixman_region32_t * base_damage,
95- struct wl_list * surfaces)
96+ struct wl_list * views)
97 {
98- struct swc_surface * surface;
99+ struct view * view;
100
101 DEBUG("Rendering to target { x: %d, y: %d, w: %u, h: %u }\n",
102 target->geometry.x, target->geometry.y,
103@@ -128,20 +116,21 @@ static void renderer_repaint(struct render_target * target,
104 wld_fill_region(swc.drm->renderer, 0xff000000, base_damage);
105 }
106
107- wl_list_for_each_reverse(surface, surfaces, link)
108+ wl_list_for_each_reverse(view, views, link)
109 {
110- if (swc_rectangle_overlap(&target->geometry, &surface->geometry))
111- repaint_surface(target, surface, damage);
112+ if (view->base.screens & target->mask)
113+ repaint_view(target, view, damage);
114 }
115
116 wld_flush(swc.drm->renderer);
117 }
118
119-static void renderer_attach(struct view * view, struct swc_buffer * buffer)
120+static bool renderer_attach(struct view * view, struct swc_buffer * buffer)
121 {
122+ return true;
123 }
124
125-static void renderer_flush_surface(struct swc_surface * surface)
126+static void renderer_flush_view(struct view * view)
127 {
128 }
129
130@@ -150,12 +139,11 @@ static void renderer_flush_surface(struct swc_surface * surface)
131 /* Surface Views {{{ */
132
133 /**
134- * Adds damage from the region below a surface, taking into account it's clip
135+ * Adds damage from the region below a view, taking into account it's clip
136 * region, to the region specified by `damage'.
137 */
138-static void damage_below_surface(struct swc_surface * surface)
139+static void damage_below_view(struct view * view)
140 {
141- struct view * view = (void *) surface->view;
142 struct swc_compositor * compositor = view->compositor;
143 pixman_region32_t damage_below;
144
145@@ -169,101 +157,40 @@ static void damage_below_surface(struct swc_surface * surface)
146 /**
147 * Completely damages the surface and its border.
148 */
149-static void damage_surface(struct swc_surface * surface)
150+static void damage_view(struct view * view)
151 {
152- struct view * view = (void *) surface->view;
153- printf("damaging surface\n");
154-
155- pixman_region32_fini(&surface->state.damage);
156- pixman_region32_init_rect(&surface->state.damage, 0, 0,
157- surface->geometry.width,
158- surface->geometry.height);
159+ damage_below_view(view);
160 view->border.damaged = true;
161 }
162
163-static void update_extents(struct swc_surface * surface)
164+static void update_extents(struct view * view)
165 {
166- struct view * view = (void *) surface->view;
167-
168- view->extents.x1 = surface->geometry.x - view->border.width;
169- view->extents.y1 = surface->geometry.y - view->border.width;
170- view->extents.x2 = surface->geometry.x + surface->geometry.width
171+ view->extents.x1 = view->base.geometry.x - view->border.width;
172+ view->extents.y1 = view->base.geometry.y - view->border.width;
173+ view->extents.x2 = view->base.geometry.x + view->base.geometry.width
174 + view->border.width;
175- view->extents.y2 = surface->geometry.y + surface->geometry.height
176+ view->extents.y2 = view->base.geometry.y + view->base.geometry.height
177 + view->border.width;
178
179 /* Damage border. */
180 view->border.damaged = true;
181 }
182
183-static void update_screens(struct swc_surface * surface)
184+static bool update(struct swc_view * base)
185 {
186- struct view * view = (void *) surface->view;
187- uint32_t old_screens = surface->screens, new_screens = 0,
188- entered_screens, left_screens, changed_screens;
189+ struct view * view = (void *) base;
190 struct swc_screen_internal * screen;
191- struct swc_output * output;
192- struct wl_client * client;
193- struct wl_resource * resource;
194
195- if (view->mapped)
196- {
197- wl_list_for_each(screen, &swc.screens, link)
198- {
199- if (swc_rectangle_overlap(&screen->base.geometry, &surface->geometry))
200- new_screens |= swc_screen_mask(screen);
201- }
202- }
203-
204- if (new_screens == old_screens)
205- return;
206-
207- entered_screens = new_screens & ~old_screens;
208- left_screens = old_screens & ~new_screens;
209- changed_screens = old_screens ^ new_screens;
210+ if (!view->base.visible)
211+ return false;
212
213 wl_list_for_each(screen, &swc.screens, link)
214 {
215- if (!(changed_screens & swc_screen_mask(screen)))
216- continue;
217-
218- output = CONTAINER_OF(screen->outputs.next, typeof(*output), link);
219- client = wl_resource_get_client(surface->resource);
220- resource = wl_resource_find_for_client(&output->resources, client);
221-
222- if (resource)
223- {
224- if (entered_screens & swc_screen_mask(screen))
225- wl_surface_send_enter(surface->resource, resource);
226- else if (left_screens & swc_screen_mask(screen))
227- wl_surface_send_leave(surface->resource, resource);
228- }
229+ if (view->base.screens & swc_screen_mask(screen))
230+ swc_compositor_schedule_update(view->compositor, screen);
231 }
232
233- surface->screens = new_screens;
234-}
235-
236-static void update(struct swc_view * view);
237-
238-static void handle_surface_event(struct wl_listener * listener, void * data)
239-{
240- struct view * view
241- = CONTAINER_OF(listener, typeof(*view), surface_event_listener);
242- struct swc_event * event = data;
243- struct swc_surface_event_data * event_data = event->data;
244- struct swc_surface * surface = event_data->surface;
245-
246- switch (event->type)
247- {
248- case SWC_SURFACE_EVENT_TYPE_RESIZE:
249- damage_below_surface(surface);
250-
251- update_extents(surface);
252- update(&view->base);
253- update_screens(surface);
254-
255- break;
256- }
257+ return true;
258 }
259
260 static void remove_(struct swc_view * base)
261@@ -271,69 +198,84 @@ static void remove_(struct swc_view * base)
262 struct view * view = (void *) base;
263
264 swc_compositor_surface_hide(view->surface);
265- wl_list_remove(&view->surface_event_listener.link);
266 pixman_region32_fini(&view->clip);
267 free(view);
268 }
269
270-static void attach(struct swc_view * base, struct swc_buffer * buffer)
271+static bool attach(struct swc_view * base, struct swc_buffer * buffer)
272 {
273 struct view * view = (void *) base;
274
275- renderer_attach(view, buffer);
276+ if (!renderer_attach(view, buffer))
277+ return false;
278+
279+ return true;
280 }
281
282-static void update(struct swc_view * base)
283+static bool move(struct swc_view * base, int32_t x, int32_t y)
284 {
285 struct view * view = (void *) base;
286- struct swc_screen_internal * screen;
287-
288- if (!view->mapped)
289- return;
290
291- wl_list_for_each(screen, &swc.screens, link)
292+ if (view->base.visible)
293 {
294- if (view->surface->screens & swc_screen_mask(screen))
295- swc_compositor_schedule_update(view->compositor, screen);
296+ damage_below_view(view);
297+ update(&view->base);
298 }
299+
300+ return true;
301 }
302
303-static void move(struct swc_view * base, int32_t x, int32_t y)
304+static void resize(struct swc_view * base)
305 {
306 struct view * view = (void *) base;
307- struct swc_surface * surface = view->surface;
308-
309- if (x == surface->geometry.x && y == surface->geometry.y)
310- return;
311-
312- if (view->mapped)
313- damage_below_surface(surface);
314
315- surface->geometry.x = x;
316- surface->geometry.y = y;
317-
318- update_extents(surface);
319-
320- if (view->mapped)
321+ if (view->base.visible)
322 {
323- /* Assume worst-case no clipping until we draw the next frame (in case
324- * the surface gets moved again before that). */
325- pixman_region32_init(&view->clip);
326-
327- damage_below_surface(surface);
328- update(&view->base);
329- update_screens(surface);
330+ damage_below_view(view);
331 update(&view->base);
332 }
333 }
334
335-const struct swc_view_impl view_impl = {
336- .remove = &remove_,
337- .attach = &attach,
338+const static struct swc_view_impl view_impl = {
339 .update = &update,
340- .move = &move
341+ .attach = &attach,
342+ .move = &move,
343+ .resize = &resize,
344+ .remove = &remove_,
345 };
346
347+static void handle_view_event(struct wl_listener * listener, void * data)
348+{
349+ struct view * view = CONTAINER_OF(listener, typeof(*view), event_listener);
350+ struct swc_event * event = data;
351+
352+ switch (event->type)
353+ {
354+ case SWC_VIEW_EVENT_MOVED:
355+ update_extents(view);
356+
357+ if (view->base.visible)
358+ {
359+ /* Assume worst-case no clipping until we draw the next frame (in case
360+ * the surface gets moved again before that). */
361+ pixman_region32_init(&view->clip);
362+
363+ damage_below_view(view);
364+ update(&view->base);
365+ }
366+ break;
367+ case SWC_VIEW_EVENT_RESIZED:
368+ update_extents(view);
369+
370+ if (view->base.visible)
371+ {
372+ damage_below_view(view);
373+ update(&view->base);
374+ }
375+ break;
376+ }
377+}
378+
379 bool swc_compositor_add_surface(struct swc_compositor * compositor,
380 struct swc_surface * surface)
381 {
382@@ -345,18 +287,18 @@ bool swc_compositor_add_surface(struct swc_compositor * compositor,
383 return false;
384
385 swc_view_initialize(&view->base, &view_impl);
386+ view->base.visible = false;
387+ view->event_listener.notify = &handle_view_event;
388+ wl_signal_add(&view->base.event_signal, &view->event_listener);
389 view->compositor = compositor;
390 view->surface = surface;
391- view->mapped = false;
392- view->extents.x1 = surface->geometry.x;
393- view->extents.y1 = surface->geometry.y;
394- view->extents.x2 = surface->geometry.x + surface->geometry.width;
395- view->extents.y2 = surface->geometry.y + surface->geometry.height;
396+ view->extents.x1 = 0;
397+ view->extents.y1 = 0;
398+ view->extents.x2 = 0;
399+ view->extents.y2 = 0;
400 view->border.width = 0;
401 view->border.color = 0x000000;
402 view->border.damaged = false;
403- view->surface_event_listener.notify = &handle_surface_event;
404- wl_signal_add(&surface->event_signal, &view->surface_event_listener);
405 pixman_region32_init(&view->clip);
406 swc_surface_set_view(surface, &view->base);
407
408@@ -366,26 +308,23 @@ bool swc_compositor_add_surface(struct swc_compositor * compositor,
409 void swc_compositor_surface_show(struct swc_surface * surface)
410 {
411 struct view * view = (void *) surface->view;
412- struct swc_compositor * compositor = view->compositor;
413
414 if (view->base.impl != &view_impl)
415 return;
416
417- if (view->mapped)
418+ if (view->base.visible)
419 return;
420
421 printf("showing surface %u\n", wl_resource_get_id(surface->resource));
422
423- view->mapped = true;
424-
425 /* Assume worst-case no clipping until we draw the next frame (in case the
426 * surface gets moved before that. */
427 pixman_region32_clear(&view->clip);
428
429- damage_surface(surface);
430- update_screens(surface);
431+ damage_view(view);
432+ swc_view_set_visibility(&view->base, true);
433 update(&view->base);
434- wl_list_insert(&compositor->surfaces, &surface->link);
435+ wl_list_insert(&view->compositor->views, &view->link);
436 }
437
438 void swc_compositor_surface_hide(struct swc_surface * surface)
439@@ -395,17 +334,15 @@ void swc_compositor_surface_hide(struct swc_surface * surface)
440 if (view->base.impl != &view_impl)
441 return;
442
443- if (!view->mapped)
444+ if (!view->base.visible)
445 return;
446
447 /* Update all the outputs the surface was on. */
448 update(&view->base);
449
450- view->mapped = false;
451-
452- damage_below_surface(surface);
453- update_screens(surface);
454- wl_list_remove(&surface->link);
455+ damage_below_view(view);
456+ swc_view_set_visibility(&view->base, false);
457+ wl_list_remove(&view->link);
458 }
459
460 void swc_compositor_surface_set_border_width(struct swc_surface * surface,
461@@ -421,7 +358,7 @@ void swc_compositor_surface_set_border_width(struct swc_surface * surface,
462
463 /* XXX: Damage above surface for transparent surfaces? */
464
465- update_extents(surface);
466+ update_extents(view);
467 update(&view->base);
468 }
469
470@@ -445,63 +382,61 @@ void swc_compositor_surface_set_border_color(struct swc_surface * surface,
471
472 static void calculate_damage(struct swc_compositor * compositor)
473 {
474- struct swc_surface * surface;
475 struct view * view;
476- pixman_region32_t surface_opaque;
477+ pixman_region32_t surface_opaque, * surface_damage;
478
479 pixman_region32_clear(&compositor->opaque);
480 pixman_region32_init(&surface_opaque);
481
482- /* Go through surfaces top-down to calculate clipping regions. */
483- wl_list_for_each(surface, &compositor->surfaces, link)
484+ /* Go through views top-down to calculate clipping regions. */
485+ wl_list_for_each(view, &compositor->views, link)
486 {
487- view = (void *) surface->view;
488-
489 /* Clip the surface by the opaque region covering it. */
490 pixman_region32_copy(&view->clip, &compositor->opaque);
491
492 /* Translate the opaque region to global coordinates. */
493- pixman_region32_copy(&surface_opaque, &surface->state.opaque);
494- pixman_region32_translate(&surface_opaque, surface->geometry.x,
495- surface->geometry.y);
496+ pixman_region32_copy(&surface_opaque, &view->surface->state.opaque);
497+ pixman_region32_translate(&surface_opaque,
498+ view->base.geometry.x, view->base.geometry.y);
499
500 /* Add the surface's opaque region to the accumulated opaque
501 * region. */
502 pixman_region32_union(&compositor->opaque, &compositor->opaque,
503 &surface_opaque);
504
505- if (pixman_region32_not_empty(&surface->state.damage))
506+ surface_damage = &view->surface->state.damage;
507+
508+ if (pixman_region32_not_empty(surface_damage))
509 {
510- renderer_flush_surface(surface);
511+ renderer_flush_view(view);
512
513 /* Translate surface damage to global coordinates. */
514- pixman_region32_translate(&surface->state.damage,
515- surface->geometry.x,
516- surface->geometry.y);
517+ pixman_region32_translate
518+ (surface_damage, view->base.geometry.x, view->base.geometry.y);
519
520 /* Add the surface damage to the compositor damage. */
521 pixman_region32_union(&compositor->damage, &compositor->damage,
522- &surface->state.damage);
523- pixman_region32_clear(&surface->state.damage);
524+ surface_damage);
525+ pixman_region32_clear(surface_damage);
526 }
527
528 if (view->border.damaged)
529 {
530- pixman_region32_t border_region, surface_region;
531+ pixman_region32_t border_region, view_region;
532
533 pixman_region32_init_with_extents(&border_region, &view->extents);
534 pixman_region32_init_rect
535- (&surface_region, surface->geometry.x, surface->geometry.y,
536- surface->geometry.width, surface->geometry.height);
537+ (&view_region, view->base.geometry.x, view->base.geometry.y,
538+ view->base.geometry.width, view->base.geometry.height);
539
540 pixman_region32_subtract(&border_region, &border_region,
541- &surface_region);
542+ &view_region);
543
544 pixman_region32_union(&compositor->damage, &compositor->damage,
545 &border_region);
546
547 pixman_region32_fini(&border_region);
548- pixman_region32_fini(&surface_region);
549+ pixman_region32_fini(&view_region);
550
551 view->border.damaged = false;
552 }
553@@ -527,9 +462,9 @@ static void repaint_screen(struct swc_compositor * compositor,
554 target.geometry.y = screen->base.geometry.y + output->framebuffer_plane.y;
555 target.geometry.width = target.buffer->width;
556 target.geometry.height = target.buffer->height;
557+ target.mask = swc_screen_mask(screen);
558
559- renderer_repaint(&target, damage, &base_damage,
560- &compositor->surfaces);
561+ renderer_repaint(&target, damage, &base_damage, &compositor->views);
562
563 pixman_region32_fini(&base_damage);
564
565@@ -607,20 +542,20 @@ static void handle_focus(struct swc_pointer * pointer)
566 {
567 /* XXX: Temporary hack */
568 struct swc_compositor * compositor = swc.compositor;
569- struct swc_surface * surface;
570+ struct view * view;
571 int32_t x, y;
572
573- wl_list_for_each(surface, &compositor->surfaces, link)
574+ wl_list_for_each(view, &compositor->views, link)
575 {
576 x = wl_fixed_to_int(pointer->x);
577 y = wl_fixed_to_int(pointer->y);
578
579- if (swc_rectangle_contains_point(&surface->geometry, x, y)
580- && pixman_region32_contains_point(&surface->state.input,
581- x - surface->geometry.x,
582- y - surface->geometry.y, NULL))
583+ if (swc_rectangle_contains_point(&view->base.geometry, x, y)
584+ && pixman_region32_contains_point(&view->surface->state.input,
585+ x - view->base.geometry.x,
586+ y - view->base.geometry.y, NULL))
587 {
588- swc_pointer_set_focus(pointer, surface);
589+ swc_pointer_set_focus(pointer, view->surface);
590 return;
591 }
592 }
593@@ -645,14 +580,14 @@ static void handle_drm_event(struct wl_listener * listener, void * data)
594 case SWC_DRM_PAGE_FLIP:
595 {
596 struct swc_drm_event_data * event_data = event->data;
597- struct swc_surface * surface;
598+ struct view * view;
599
600 compositor->pending_flips &= ~SWC_OUTPUT_MASK(event_data->output);
601
602 if (compositor->pending_flips == 0)
603 {
604- wl_list_for_each(surface, &compositor->surfaces, link)
605- swc_view_frame(surface->view, event_data->time);
606+ wl_list_for_each(view, &compositor->views, link)
607+ swc_view_frame(&view->base, event_data->time);
608 }
609
610 /* If we had scheduled updates that couldn't run because we were
611@@ -744,7 +679,7 @@ bool swc_compositor_initialize(struct swc_compositor * compositor,
612
613 pixman_region32_init(&compositor->damage);
614 pixman_region32_init(&compositor->opaque);
615- wl_list_init(&compositor->surfaces);
616+ wl_list_init(&compositor->views);
617
618 swc_add_key_binding(SWC_MOD_CTRL | SWC_MOD_ALT, XKB_KEY_BackSpace,
619 &handle_terminate, display);
+1,
-1
1@@ -10,7 +10,7 @@ struct swc_screen_internal;
2 struct swc_compositor
3 {
4 struct wl_display * display;
5- struct wl_list surfaces;
6+ struct wl_list views;
7
8 /* Internal state related to repainting the screen. */
9 struct
+5,
-14
1@@ -1,6 +1,7 @@
2 #include "pointer.h"
3 #include "event.h"
4 #include "util.h"
5+#include "view.h"
6
7 #include <stdio.h>
8 #include <assert.h>
9@@ -19,8 +20,8 @@ static void enter(struct swc_input_focus_handler * handler,
10 display = wl_client_get_display(client);
11 serial = wl_display_next_serial(display);
12
13- surface_x = pointer->x - wl_fixed_from_int(surface->geometry.x);
14- surface_y = pointer->y - wl_fixed_from_int(surface->geometry.y);
15+ surface_x = pointer->x - wl_fixed_from_int(surface->view->geometry.x);
16+ surface_y = pointer->y - wl_fixed_from_int(surface->view->geometry.y);
17
18 printf("-> pointer.enter: %p (%d, %d)\n", resource, surface_x, surface_y);
19 wl_pointer_send_enter(resource, serial, surface->resource,
20@@ -135,8 +136,6 @@ static void set_cursor(struct wl_client * client,
21
22 if (surface)
23 {
24- surface->geometry.x = wl_fixed_to_int(pointer->x) - hotspot_x;
25- surface->geometry.y = wl_fixed_to_int(pointer->y) - hotspot_y;
26 wl_resource_add_destroy_listener(surface->resource,
27 &pointer->cursor.destroy_listener);
28 }
29@@ -218,20 +217,12 @@ void swc_pointer_handle_relative_motion
30 {
31 wl_fixed_t surface_x, surface_y;
32 surface_x = pointer->x
33- - wl_fixed_from_int(pointer->focus.surface->geometry.x);
34+ - wl_fixed_from_int(pointer->focus.surface->view->geometry.x);
35 surface_y = pointer->y
36- - wl_fixed_from_int(pointer->focus.surface->geometry.y);
37+ - wl_fixed_from_int(pointer->focus.surface->view->geometry.y);
38
39 wl_pointer_send_motion(pointer->focus.resource, time,
40 surface_x, surface_y);
41-
42- if (pointer->cursor.surface)
43- {
44- swc_surface_move
45- (pointer->cursor.surface,
46- wl_fixed_to_int(pointer->x) - pointer->cursor.hotspot_x,
47- wl_fixed_to_int(pointer->y) - pointer->cursor.hotspot_y);
48- }
49 }
50 }
51
+5,
-4
1@@ -26,6 +26,7 @@
2 #include "swc.h"
3 #include "surface.h"
4 #include "util.h"
5+#include "view.h"
6 #include "window.h"
7
8 #include <stdlib.h>
9@@ -87,8 +88,8 @@ static void set_transient(struct wl_client * client,
10 = wl_resource_get_user_data(resource);
11 struct swc_surface * parent = wl_resource_get_user_data(parent_resource);
12
13- swc_surface_move(shell_surface->window.surface,
14- parent->geometry.x + x, parent->geometry.y + y);
15+ swc_view_move(shell_surface->window.surface->view,
16+ parent->view->geometry.x + x, parent->view->geometry.y + y);
17 swc_compositor_surface_show(shell_surface->window.surface);
18
19 /* XXX: Handle transient */
20@@ -111,8 +112,8 @@ static void set_popup(struct wl_client * client, struct wl_resource * resource,
21 = wl_resource_get_user_data(resource);
22 struct swc_surface * parent = wl_resource_get_user_data(parent_resource);
23
24- swc_surface_move(shell_surface->window.surface,
25- parent->geometry.x + x, parent->geometry.y + y);
26+ swc_view_move(shell_surface->window.surface->view,
27+ parent->view->geometry.x + x, parent->view->geometry.y + y);
28 swc_compositor_surface_show(shell_surface->window.surface);
29
30 /* XXX: Handle popup */
+60,
-78
1@@ -24,7 +24,10 @@
2 #include "surface.h"
3 #include "buffer.h"
4 #include "event.h"
5+#include "internal.h"
6+#include "output.h"
7 #include "region.h"
8+#include "screen.h"
9 #include "util.h"
10 #include "view.h"
11 #include "wayland_buffer.h"
12@@ -33,37 +36,6 @@
13 #include <stdio.h>
14 #include <wld/wld.h>
15
16-static void set_size(struct swc_surface * surface,
17- uint32_t width, uint32_t height)
18-{
19- /* Check if the surface was resized. */
20- if (width != surface->geometry.width || height != surface->geometry.height)
21- {
22- struct swc_surface_event_data data = {
23- .surface = surface,
24- .resize = {
25- .old_width = surface->geometry.width,
26- .old_height = surface->geometry.height,
27- .new_width = width,
28- .new_height = height
29- }
30- };
31-
32- surface->geometry.width = width;
33- surface->geometry.height = height;
34-
35- pixman_region32_intersect_rect
36- (&surface->state.opaque, &surface->state.opaque,
37- 0, 0, width, height);
38- pixman_region32_intersect_rect
39- (&surface->state.damage, &surface->state.damage,
40- 0, 0, width, height);
41-
42- swc_send_event(&surface->event_signal,
43- SWC_SURFACE_EVENT_TYPE_RESIZE, &data);
44- }
45-}
46-
47 /**
48 * Removes a buffer from a surface state.
49 */
50@@ -73,21 +45,12 @@ static void handle_buffer_destroy(struct wl_listener * listener, void * data)
51
52 state = CONTAINER_OF(listener, typeof(*state), buffer_destroy_listener);
53 state->buffer = NULL;
54-
55- if (state->current)
56- {
57- struct swc_surface * surface;
58-
59- surface = CONTAINER_OF(state, typeof(*surface), state);
60- set_size(surface, 0, 0);
61- }
62 }
63
64-static void state_initialize(struct swc_surface_state * state, bool current)
65+static void state_initialize(struct swc_surface_state * state)
66 {
67 state->buffer = NULL;
68 state->buffer_destroy_listener.notify = &handle_buffer_destroy;
69- state->current = current;
70
71 pixman_region32_init(&state->damage);
72 pixman_region32_init(&state->opaque);
73@@ -232,6 +195,7 @@ static void set_input_region(struct wl_client * client,
74 static void commit(struct wl_client * client, struct wl_resource * resource)
75 {
76 struct swc_surface * surface = wl_resource_get_user_data(resource);
77+ struct wld_buffer * buffer;
78
79 /* Attach */
80 if (surface->pending.commit & SWC_SURFACE_COMMIT_ATTACH)
81@@ -243,24 +207,17 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
82 swc_wayland_buffer_release(current_buffer);
83
84 state_set_buffer(&surface->state, surface->pending.state.buffer);
85-
86- /* Determine size of buffer. */
87- if (current_buffer)
88- {
89- set_size(surface,
90- current_buffer->wld->width, current_buffer->wld->height);
91- }
92- else
93- set_size(surface, 0, 0);
94 }
95
96+ buffer = surface->state.buffer ? surface->state.buffer->wld : NULL;
97+
98 /* Damage */
99 if (surface->pending.commit & SWC_SURFACE_COMMIT_DAMAGE)
100 {
101 pixman_region32_intersect_rect(&surface->pending.state.damage,
102 &surface->pending.state.damage, 0, 0,
103- surface->geometry.width,
104- surface->geometry.height);
105+ buffer ? buffer->width : 0,
106+ buffer ? buffer->height : 0);
107 pixman_region32_union(&surface->state.damage, &surface->state.damage,
108 &surface->pending.state.damage);
109 pixman_region32_clear(&surface->pending.state.damage);
110@@ -271,8 +228,8 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
111 {
112 pixman_region32_intersect_rect(&surface->state.opaque,
113 &surface->pending.state.opaque, 0, 0,
114- surface->geometry.width,
115- surface->geometry.height);
116+ buffer ? buffer->width : 0,
117+ buffer ? buffer->height : 0);
118 }
119
120 /* Input */
121@@ -293,8 +250,8 @@ static void commit(struct wl_client * client, struct wl_resource * resource)
122 if (surface->view)
123 {
124 if (surface->pending.commit & SWC_SURFACE_COMMIT_ATTACH)
125- surface->view->impl->attach(surface->view, surface->state.buffer);
126- surface->view->impl->update(surface->view);
127+ swc_view_attach(surface->view, surface->state.buffer);
128+ swc_view_update(surface->view);
129 }
130
131 surface->pending.commit = 0;
132@@ -335,6 +292,9 @@ static void surface_destroy(struct wl_resource * resource)
133 state_finish(&surface->state);
134 state_finish(&surface->pending.state);
135
136+ if (surface->view)
137+ wl_list_remove(&surface->view_listener.link);
138+
139 printf("freeing surface %p\n", surface);
140 free(surface);
141 }
142@@ -362,6 +322,46 @@ static void handle_view_event(struct wl_listener * listener, void * data)
143 wl_list_init(&surface->state.frame_callbacks);
144 break;
145 }
146+ case SWC_VIEW_EVENT_SCREENS_CHANGED:
147+ {
148+ struct swc_screen_internal * screen;
149+ struct swc_output * output;
150+ struct wl_client * client;
151+ struct wl_resource * resource;
152+ uint32_t entered = event_data->screens_changed.entered,
153+ left = event_data->screens_changed.left;
154+
155+ client = wl_resource_get_client(surface->resource);
156+
157+ wl_list_for_each(screen, &swc.screens, link)
158+ {
159+ if (!((entered | left) & swc_screen_mask(screen)))
160+ continue;
161+
162+ wl_list_for_each(output, &screen->outputs, link)
163+ {
164+ resource = wl_resource_find_for_client
165+ (&output->resources, client);
166+
167+ if (resource)
168+ {
169+ if (entered & swc_screen_mask(screen))
170+ wl_surface_send_enter(surface->resource, resource);
171+ else if (left & swc_screen_mask(screen))
172+ wl_surface_send_leave(surface->resource, resource);
173+ }
174+ }
175+ }
176+ break;
177+ }
178+ case SWC_VIEW_EVENT_RESIZED:
179+ pixman_region32_intersect_rect
180+ (&surface->state.opaque, &surface->state.opaque, 0, 0,
181+ surface->view->geometry.width, surface->view->geometry.height);
182+ pixman_region32_intersect_rect
183+ (&surface->state.damage, &surface->state.damage, 0, 0,
184+ surface->view->geometry.width, surface->view->geometry.height);
185+ break;
186 }
187 }
188
189@@ -383,19 +383,13 @@ struct swc_surface * swc_surface_new(struct wl_client * client,
190 return NULL;
191
192 /* Initialize the surface. */
193- surface->screens = 0;
194- surface->geometry.x = 0;
195- surface->geometry.y = 0;
196- surface->geometry.width = 0;
197- surface->geometry.height = 0;
198 surface->pending.commit = 0;
199 surface->window = NULL;
200 surface->view = NULL;
201 surface->view_listener.notify = &handle_view_event;
202- surface->view_state = NULL;
203
204- state_initialize(&surface->state, true);
205- state_initialize(&surface->pending.state, false);
206+ state_initialize(&surface->state);
207+ state_initialize(&surface->pending.state);
208
209 wl_signal_init(&surface->event_signal);
210
211@@ -425,20 +419,8 @@ void swc_surface_set_view(struct swc_surface * surface, struct swc_view * view)
212 if (view)
213 {
214 wl_signal_add(&view->event_signal, &surface->view_listener);
215- surface->view->impl->attach(surface->view, surface->state.buffer);
216- surface->view->impl->update(surface->view);
217+ swc_view_attach(view, surface->state.buffer);
218+ swc_view_update(surface->view);
219 }
220 }
221
222-void swc_surface_update(struct swc_surface * surface)
223-{
224- if (surface->view)
225- surface->view->impl->update(surface->view);
226-}
227-
228-void swc_surface_move(struct swc_surface * surface, int32_t x, int32_t y)
229-{
230- if (surface->view)
231- surface->view->impl->move(surface->view, x, y);
232-}
233-
+1,
-11
1@@ -24,8 +24,7 @@
2 #ifndef SWC_SURFACE_H
3 #define SWC_SURFACE_H
4
5-#include "swc.h"
6-
7+#include <stdbool.h>
8 #include <wayland-server.h>
9 #include <pixman.h>
10
11@@ -58,7 +57,6 @@ struct swc_surface_state
12 {
13 struct swc_buffer * buffer;
14 struct wl_listener buffer_destroy_listener;
15- bool current;
16
17 /* The region that needs to be repainted. */
18 pixman_region32_t damage;
19@@ -88,10 +86,6 @@ struct swc_surface
20 struct swc_window * window;
21 struct swc_view * view;
22 struct wl_listener view_listener;
23- void * view_state;
24-
25- uint32_t screens;
26- struct swc_rectangle geometry;
27
28 struct wl_signal event_signal;
29 struct wl_list link;
30@@ -102,9 +96,5 @@ struct swc_surface * swc_surface_new(struct wl_client * client,
31
32 void swc_surface_set_view(struct swc_surface * surface, struct swc_view * view);
33
34-void swc_surface_update(struct swc_surface * surface);
35-
36-void swc_surface_move(struct swc_surface * surface, int32_t x, int32_t y);
37-
38 #endif
39
+120,
-0
1@@ -22,17 +22,137 @@
2 */
3
4 #include "view.h"
5+#include "buffer.h"
6 #include "event.h"
7+#include "internal.h"
8+#include "screen.h"
9+#include "util.h"
10+
11+#include <wld/wld.h>
12+
13+static void update_screens(struct swc_view * view)
14+{
15+ struct swc_view_event_data data = { .view = view };
16+ uint32_t old = view->screens, new = 0;
17+ struct swc_screen_internal * screen;
18+
19+ if (view->visible)
20+ {
21+ wl_list_for_each(screen, &swc.screens, link)
22+ {
23+ if (swc_rectangle_overlap(&screen->base.geometry, &view->geometry))
24+ new |= swc_screen_mask(screen);
25+ }
26+ }
27+
28+ if (new == old)
29+ return;
30+
31+ view->screens = new;
32+
33+ data.screens_changed.entered = new & ~old;
34+ data.screens_changed.left = old & ~new;
35+ swc_send_event(&view->event_signal, SWC_VIEW_EVENT_SCREENS_CHANGED, &data);
36+}
37+
38+static void set_size(struct swc_view * view, uint32_t width, uint32_t height)
39+{
40+ if (view->geometry.width != width || view->geometry.height != height)
41+ {
42+ struct swc_view_event_data data = { .view = view };
43+
44+ if (view->impl->resize)
45+ view->impl->resize(view);
46+
47+ view->geometry.width = width;
48+ view->geometry.height = height;
49+ update_screens(view);
50+
51+ swc_send_event(&view->event_signal, SWC_VIEW_EVENT_RESIZED, &data);
52+ }
53+}
54+
55+static void handle_buffer_destroy(struct wl_listener * listener, void * data)
56+{
57+ struct swc_view * view
58+ = CONTAINER_OF(listener, typeof(*view), buffer_destroy_listener);
59+
60+ view->impl->attach(view, NULL);
61+ view->buffer = NULL;
62+ set_size(view, 0, 0);
63+}
64
65 void swc_view_initialize(struct swc_view * view,
66 const struct swc_view_impl * impl)
67 {
68 view->impl = impl;
69+ view->visible = true;
70+ view->geometry.x = 0;
71+ view->geometry.y = 0;
72+ view->geometry.width = 0;
73+ view->geometry.height = 0;
74+ view->buffer = NULL;
75+ view->buffer_destroy_listener.notify = &handle_buffer_destroy;
76+ view->screens = 0;
77 wl_signal_init(&view->event_signal);
78 }
79
80 void swc_view_finalize(struct swc_view * view)
81 {
82+ if (view->buffer)
83+ wl_list_remove(&view->buffer_destroy_listener.link);
84+}
85+
86+bool swc_view_attach(struct swc_view * view, struct swc_buffer * buffer)
87+{
88+ if (view->impl->attach(view, buffer))
89+ {
90+ if (view->buffer)
91+ wl_list_remove(&view->buffer_destroy_listener.link);
92+
93+ if (buffer)
94+ {
95+ wl_signal_add(&buffer->destroy_signal,
96+ &view->buffer_destroy_listener);
97+ set_size(view, buffer->wld->width, buffer->wld->height);
98+ }
99+ else
100+ set_size(view, 0, 0);
101+
102+ view->buffer = buffer;
103+ return true;
104+ }
105+ else
106+ return false;
107+}
108+
109+bool swc_view_update(struct swc_view * view)
110+{
111+ return view->impl->update(view);
112+}
113+
114+bool swc_view_move(struct swc_view * view, int32_t x, int32_t y)
115+{
116+ struct swc_view_event_data data = { .view = view };
117+
118+ if (x == view->geometry.x && y == view->geometry.y)
119+ return true;
120+
121+ if (!view->impl->move || !view->impl->move(view, x, y))
122+ return false;
123+
124+ view->geometry.x = x;
125+ view->geometry.y = y;
126+ update_screens(view);
127+ swc_send_event(&view->event_signal, SWC_VIEW_EVENT_MOVED, &data);
128+
129+ return true;
130+}
131+
132+void swc_view_set_visibility(struct swc_view * view, bool visible)
133+{
134+ view->visible = visible;
135+ update_screens(view);
136 }
137
138 void swc_view_frame(struct swc_view * view, uint32_t time)
+33,
-9
1@@ -26,12 +26,20 @@
2
3 #include "swc.h"
4
5-struct swc_buffer;
6-
7 enum swc_view_event
8 {
9 /* Sent when the view has displayed the next frame. */
10 SWC_VIEW_EVENT_FRAME,
11+
12+ /* Sent when the origin of the view has moved. */
13+ SWC_VIEW_EVENT_MOVED,
14+
15+ /* Sent when the view's size changes. This occurs when a buffer of
16+ * different dimensions is attached to the view. */
17+ SWC_VIEW_EVENT_RESIZED,
18+
19+ /* Sent when the set of screens the view is visible on changes. */
20+ SWC_VIEW_EVENT_SCREENS_CHANGED
21 };
22
23 struct swc_view_event_data
24@@ -43,6 +51,11 @@ struct swc_view_event_data
25 {
26 uint32_t time;
27 } frame;
28+
29+ struct
30+ {
31+ uint32_t left, entered;
32+ } screens_changed;
33 };
34 };
35
36@@ -51,21 +64,28 @@ struct swc_view
37 const struct swc_view_impl * impl;
38
39 struct wl_signal event_signal;
40+ bool visible;
41+ uint32_t screens;
42+
43+ struct swc_rectangle geometry;
44+ struct swc_buffer * buffer;
45+ struct wl_listener buffer_destroy_listener;
46 };
47
48 struct swc_view_impl
49 {
50- /* Called when a source is removed from the view. */
51- void (* remove)(struct swc_view * view);
52+ /* Called when the view should present a new frame. */
53+ bool (* update)(struct swc_view * view);
54
55 /* Called when a new buffer is attached to the view. */
56- void (* attach)(struct swc_view * view, struct swc_buffer * buffer);
57+ bool (* attach)(struct swc_view * view, struct swc_buffer * buffer);
58
59- /* Called when the view should present a new frame. */
60- void (* update)(struct swc_view * view);
61+ bool (* move)(struct swc_view * view, int32_t x, int32_t y);
62
63- /* Move the view to the specified coordinates. */
64- void (* move)(struct swc_view * view, int32_t x, int32_t y);
65+ void (* resize)(struct swc_view * view);
66+
67+ /* Called when a source is removed from the view. */
68+ void (* remove)(struct swc_view * view);
69 };
70
71 void swc_view_initialize(struct swc_view * view,
72@@ -73,6 +93,10 @@ void swc_view_initialize(struct swc_view * view,
73
74 void swc_view_finalize(struct swc_view * view);
75
76+bool swc_view_attach(struct swc_view * view, struct swc_buffer * buffer);
77+bool swc_view_update(struct swc_view * view);
78+bool swc_view_move(struct swc_view * view, int32_t x, int32_t y);
79+void swc_view_set_visibility(struct swc_view * view, bool visible);
80 void swc_view_frame(struct swc_view * view, uint32_t time);
81
82 #endif
+2,
-1
1@@ -29,6 +29,7 @@
2 #include "seat.h"
3 #include "swc.h"
4 #include "util.h"
5+#include "view.h"
6
7 #include <stdlib.h>
8 #include <string.h>
9@@ -97,7 +98,7 @@ void swc_window_set_geometry(struct swc_window * window,
10 if (INTERNAL(window)->impl->configure)
11 INTERNAL(window)->impl->configure(window, geometry);
12
13- swc_surface_move(INTERNAL(window)->surface, geometry->x, geometry->y);
14+ swc_view_move(INTERNAL(window)->surface->view, geometry->x, geometry->y);
15 }
16
17 EXPORT
+2,
-1
1@@ -27,6 +27,7 @@
2 #include "surface.h"
3 #include "swc.h"
4 #include "util.h"
5+#include "view.h"
6 #include "window.h"
7
8 #include <stdio.h>
9@@ -341,7 +342,7 @@ void swc_xwm_manage_window(xcb_window_t id, struct swc_surface * surface)
10 if ((geometry_reply = xcb_get_geometry_reply(xwm.connection,
11 geometry_cookie, NULL)))
12 {
13- swc_surface_move(surface, geometry_reply->x, geometry_reply->y);
14+ swc_view_move(surface->view, geometry_reply->x, geometry_reply->y);
15 }
16
17 if (entry->override_redirect)