diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2013-05-16 22:06:03 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-05-16 22:06:03 -0400 |
commit | 68ed10bd33df4018e4fec2f99aac16bbe7e50ecc (patch) | |
tree | 36b98849cd2f90842ccbdf6a9f757e624cc8ccfe | |
parent | b3cd14fd1be0e8c665ed6c207f2bb9c347ea7a83 (diff) |
Expose events
-rw-r--r-- | NOTES | 8 | ||||
-rw-r--r-- | src/display.c | 7 | ||||
-rw-r--r-- | src/private.h | 3 | ||||
-rw-r--r-- | src/test.c | 11 | ||||
-rw-r--r-- | src/window.c | 115 |
5 files changed, 140 insertions, 4 deletions
@@ -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; @@ -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 |