summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-05-16 22:06:03 -0400
committerKristian Høgsberg <krh@bitplanet.net>2013-05-16 22:06:03 -0400
commit68ed10bd33df4018e4fec2f99aac16bbe7e50ecc (patch)
tree36b98849cd2f90842ccbdf6a9f757e624cc8ccfe
parentb3cd14fd1be0e8c665ed6c207f2bb9c347ea7a83 (diff)
Expose events
-rw-r--r--NOTES8
-rw-r--r--src/display.c7
-rw-r--r--src/private.h3
-rw-r--r--src/test.c11
-rw-r--r--src/window.c115
5 files changed, 140 insertions, 4 deletions
diff --git a/NOTES b/NOTES
index 06b0a31..181abde 100644
--- a/NOTES
+++ b/NOTES
@@ -13,4 +13,10 @@
but we'll also need full substructure redirect since apps can do
that on their own windows.
- - Problem with popup placement and other global coords. \ No newline at end of file
+ - Problem with popup placement and other global coords.
+
+ - Difference in Expose events between xlib and csx when Mapping
+ window and then subwindow. csx sends the immediate Expose rects,
+ xlib sends the final result (the subwindow rect and the split up
+ rects around it)... Expose compression? We could do lazy exposure
+ events in XNextEvent(). \ No newline at end of file
diff --git a/src/display.c b/src/display.c
index b560560..daaa135 100644
--- a/src/display.c
+++ b/src/display.c
@@ -23,6 +23,13 @@ csx_display_bad_window(struct csx_display *display)
exit(1);
}
+void
+csx_display_bad_match(struct csx_display *display)
+{
+ fprintf(stderr, "error bad match\n");
+ exit(1);
+}
+
static void
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
diff --git a/src/private.h b/src/private.h
index 2dffdcc..197dd48 100644
--- a/src/private.h
+++ b/src/private.h
@@ -45,6 +45,8 @@ XID cxs_display_add_resource(struct csx_display *display, void *p);
void csx_display_remove_resource(struct csx_display *display, XID id);
void *csx_display_lookup_resource(struct csx_display *display, XID id);
void csx_display_bad_alloc(struct csx_display *display);
+void csx_display_bad_window(struct csx_display *display);
+void csx_display_bad_match(struct csx_display *display);
void csx_display_add_seat(struct csx_display *display,
uint32_t name, uint32_t version);
@@ -66,6 +68,7 @@ struct csx_window {
struct wl_list link;
struct wl_list child_list;
pixman_region32_t output_clip;
+ pixman_region32_t border_clip;
struct csx_pixmap *pixmap; /* viewable iff has pixmap */
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
diff --git a/src/test.c b/src/test.c
index a8928a0..a05b8be 100644
--- a/src/test.c
+++ b/src/test.c
@@ -39,6 +39,13 @@ print_event(XEvent *e)
printf("got CreateNotify event: window %d, parent %d\n",
e->xcreatewindow.window, e->xcreatewindow.parent);
break;
+ case Expose:
+ printf("got Expose event: window %d at %d,%d size %dx%d\n",
+ e->xexpose.window,
+ e->xexpose.x, e->xexpose.y,
+ e->xexpose.width, e->xexpose.height);
+ break;
+
default:
printf("got event type %d\n", e->type);
break;
@@ -71,6 +78,7 @@ int main(int argc, char *argv[])
root = XRootWindow(display, 0);
printf("opened display %p, root window is %d\n", display, root);
attributes.event_mask =
+ ExposureMask |
LeaveWindowMask |
EnterWindowMask |
Button1MotionMask |
@@ -90,6 +98,9 @@ int main(int argc, char *argv[])
XMapWindow(display, win);
XMapWindow(display, sub);
+
+ XMoveWindow(display, sub, 60, 60);
+
XFlush(display);
run(display);
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