summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c115
1 files changed, 112 insertions, 3 deletions
diff --git a/src/window.c b/src/window.c
index af7f024..1a6160e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -24,7 +24,9 @@ csx_window_create(struct csx_display *display, struct csx_window *parent)
wl_list_init(&window->child_list);
if (parent)
wl_list_insert(&parent->child_list, &window->link);
+
pixman_region32_init(&window->output_clip);
+ pixman_region32_init(&window->border_clip);
return window;
}
@@ -197,6 +199,66 @@ csx_display_send_map_notify(struct csx_display *display,
}
void
+csx_window_send_expose(struct csx_window *window,
+ pixman_box32_t *rect, int count)
+{
+ struct csx_display *display = window->display;
+ struct csx_event *event;
+
+ event = malloc(sizeof *event);
+
+ event->xevent.xexpose.type = Expose;
+ event->xevent.xexpose.serial = display->serial;
+ event->xevent.xexpose.send_event = False;
+ event->xevent.xexpose.display = display->xdisplay;
+ event->xevent.xexpose.window = window->id;
+ event->xevent.xexpose.x = rect->x1;
+ event->xevent.xexpose.y = rect->y1;
+ event->xevent.xexpose.width = rect->x2 - rect->x1;
+ event->xevent.xexpose.height = rect->y2 - rect->y1;
+ event->xevent.xexpose.count = count;
+
+ wl_list_insert(display->event_list.prev, &event->link);
+}
+
+void
+csx_window_calculate_output_clip(struct csx_window *window)
+{
+ pixman_region32_t output_clip, expose_region;
+ struct csx_window *child;
+ pixman_box32_t *rects;
+ int i, nrects;
+
+ pixman_region32_init(&output_clip);
+ pixman_region32_copy(&output_clip, &window->border_clip);
+ wl_list_for_each(child, &window->child_list, link) {
+ if (!child->mapped)
+ continue;
+ pixman_region32_intersect_rect(&child->border_clip,
+ &output_clip,
+ child->x, child->y,
+ child->width, child->height);
+ pixman_region32_subtract(&output_clip,
+ &output_clip, &child->border_clip);
+ pixman_region32_translate(&child->border_clip,
+ -child->x, -child->y);
+ csx_window_calculate_output_clip(child);
+ }
+
+ pixman_region32_init(&expose_region);
+ pixman_region32_subtract(&expose_region,
+ &output_clip, &window->output_clip);
+ pixman_region32_copy(&window->output_clip, &output_clip);
+
+ rects = pixman_region32_rectangles(&expose_region, &nrects);
+ for (i = 0; i < nrects; i++)
+ csx_window_send_expose(window, &rects[i], nrects - i - 1);
+
+ pixman_region32_fini(&expose_region);
+ pixman_region32_fini(&output_clip);
+}
+
+void
csx_window_map_tree(struct csx_window *window, struct csx_pixmap *pixmap)
{
struct csx_window *child;
@@ -205,7 +267,6 @@ csx_window_map_tree(struct csx_window *window, struct csx_pixmap *pixmap)
csx_window_map_tree(child, pixmap);
window->pixmap = pixmap;
- csx_display_send_map_notify(window->display, window);
}
void
@@ -218,6 +279,11 @@ csx_window_map_toplevel(struct csx_window *window)
window->width, window->height, 32);
csx_window_map_tree(window, pixmap);
+ pixman_region32_fini(&window->border_clip);
+ pixman_region32_init_rect(&window->border_clip,
+ 0, 0, window->width, window->height);
+ csx_window_calculate_output_clip(window);
+
window->surface = wl_compositor_create_surface(display->compositor);
wl_surface_set_user_data(window->surface, window);
wl_surface_attach(window->surface, window->pixmap->buffer, 0, 0);
@@ -247,11 +313,12 @@ XMapWindow(Display *xdisplay, Window xwindow)
return 0;
window->mapped = 1;
+ csx_display_send_map_notify(display, window);
if (window->parent == display->root) {
csx_window_map_toplevel(window);
} else if (window->parent->mapped) {
window->pixmap = window->parent->pixmap;
- csx_display_send_map_notify(display, window);
+ csx_window_calculate_output_clip(window->parent);
}
}
@@ -275,6 +342,32 @@ XChangeWindowAttributes(Display *xdisplay, Window xwindow,
}
}
+void
+csx_window_send_configure_notify(struct csx_window *window,
+ struct csx_window *event_window)
+{
+ struct csx_display *display = window->display;
+ struct csx_event *event;
+
+ event = malloc(sizeof *event);
+
+ event->xevent.xconfigure.type = ConfigureNotify;
+ event->xevent.xconfigure.serial = display->serial;
+ event->xevent.xconfigure.send_event = False;
+ event->xevent.xconfigure.display = display->xdisplay;
+ event->xevent.xconfigure.event = event_window->id;
+ event->xevent.xconfigure.window = window->id;
+ event->xevent.xconfigure.x = window->x;
+ event->xevent.xconfigure.y = window->y;
+ event->xevent.xconfigure.width = window->width;
+ event->xevent.xconfigure.height = window->height;
+ event->xevent.xconfigure.border_width = window->border_width;
+ event->xevent.xconfigure.above = None; /* FIXME */
+ event->xevent.xconfigure.override_redirect = False;
+
+ wl_list_insert(display->event_list.prev, &event->link);
+}
+
WL_EXPORT int
XConfigureWindow(Display *xdisplay, Window xwindow,
unsigned int mask, XWindowChanges *values)
@@ -288,6 +381,11 @@ XConfigureWindow(Display *xdisplay, Window xwindow,
return 0; /* what's the return value? */
}
+ if ((mask & CWSibling) && !(mask & CWStackMode)) {
+ csx_display_bad_match(display);
+ return 0; /* what's the return value? */
+ }
+
if (mask & CWX)
window->x = values->x;
if (mask & CWY)
@@ -297,7 +395,18 @@ XConfigureWindow(Display *xdisplay, Window xwindow,
if (mask & CWHeight)
window->height = values->height;
- /* Send out events as necessary: exposures, configure notify etc */
+ if (mask & CWBorderWidth)
+ window->border_width = values->border_width;
+ if (mask & CWSibling)
+ window->border_width = values->border_width;
+
+ if (mask & (CWX | CWY | CWWidth | CWHeight))
+ csx_window_calculate_output_clip(window->parent);
+
+ if (window->event_mask & StructureNotifyMask)
+ csx_window_send_configure_notify(window, window);
+ if (window->parent && window->parent->event_mask & StructureNotifyMask)
+ csx_window_send_configure_notify(window, window->parent);
}
WL_EXPORT int